前提条件
認証アプリ:Google Authenticator (Google 認証アプリ)
結論
認証アプリへ登録したアカウントを、認証アプリ内から一回消して、QRコードをすぐ読み直しましょう。
当初
AWSのrootアカウントへ、MFA(Multi Factor Authentication)を有効化しようとしたんです。
しかし、アクセス権限が必要です
と出てきて進みませんでした。
説明文章にある認証コード1
、認証コード2
、連続
の意味を思い出せず、ちょっと四苦八苦してた時に、
「ああ、順次表示されたコードを2回連続で入力するのね」
と理解したのですが、それでもダメでした。後にググって、同じ様に若干ハマってた人がいたので、手順はOKと判断しました。
しかし、何故かアクセス権限が必要です
がまだ出ます。
root
なんだから、アクセス権限が必要です≠IAMのアクセス権限が必要です
だよなぁ・・・と思いつつ、IAMユーザにアクセス権限を付加したりなんだりと無駄な事をやり・・・
解決
もう一度、rootアカウントのMFA有効化を試し、
「一回認証アプリへ登録したアカウントに異常があるかもしれない」
と判断し、認証アプリへ登録したアカウントを認証アプリから削除、登録し直しました。
→この行動を取った理由は、以前MFA有効化をした時用に別のモバイルデバイスがあって、
新旧の認証アプリで表示されていた認証コードが不一致だったので、
時間なのかsaltなのかは分からないけども、認証コードの仕組みで違いが出たのだろうなぁ・・・と想像したためです。
で、結論は先に書きましたが、MFA有効化は成功し、ログアウトしてサインイン、認証コードが通る事を確認出来ました。
認証コードをフワっとした理解のまま使っていたので、小一時間無駄にしてしまいました。
これを機会に、認証コードについての理解を少しだけでも仕入れてみました。
認証コードについてのザックリした理解
↓ググって掴みに良さそうな記事を見つけたのでリンク貼っておきます。
Google 認証システムの仕組み(sekika.github.io)
元仕様
RFCなんですねー、6238です。
仕組み
ほぼワンタイムパスワードを作って認証する仕組みです。
準備や手順は非常に単純で、
- QRコードを読み込むと、サーバが生成した秘密鍵を受け取れる
- なので、QRコードを読み込んだ時点でサーバとクライアントで秘密鍵を共有した状態になります。
-
30秒間だけ有効になるワンタイムパスワードを作っている
- クライアント側では30秒ずつ別のパスワードが表示されるのは、これが理由
ザックリ図解
<<準備: 秘密鍵を盗まれたらOut>>
[ ケータイ電話 ] [ サーバ ]
秘密鍵 <- Google認証アプリ <- QRコード <- 秘密鍵
<<認証: 確認コードを盗まれたらOut(ただし約30秒間)>>
[ ケータイ電話 ] [ サーバ ]
秘密鍵 -> <- 秘密鍵
現在時刻 -> カウンタ -> 認証コード <- カウンタ <- 現在時刻
補足
- QRコード以外にもBase32文字列でも認証アプリへ登録可能だそうです。
- 参考リンクにもある通り、中間者攻撃を防ぐ仕様は無いらしいので、
30秒間はずっと有効なパスワードという扱いなので、One-Period Passwordと呼んだ方が適切に思えます。
(サーバ側で、「一回認証OKになったら、次の認証コード発行までは同じ認証コードは無効化」としておけば、本当にワンタイムなパスワードになりますね)
結局、手順をどう誤ったのか
おそらくは以下の通りでしょう。
- 「MFAの有効化」で認証アプリへQRコードを読み込み → 秘密鍵を認証アプリへ保存した
- 「認証コード1」、「認証コード2」と「連続」の意味が分からず、MFA有効化に失敗したので一旦「キャンセル」した → おそらく、この時点でサーバ内の秘密鍵は無効化されたのでしょう
- ヘルプを調べたりググったりして情報を得てから再度MFA有効化のためにQRコードを読み込み、しかしMFA有効化に失敗した
→QRコードの再読み込みでは、認証アプリ内に既に作成した秘密鍵は上書きされなかった、しかもサーバ内には新しい秘密鍵が作成されたので、認証アプリとサーバとの間で秘密鍵の不一致が発生と推論します。(秘密鍵を照合したいですが、公開してもらえないでしょうから。。) - 小一時間経過後、認証アプリ内のアカウントを削除し、QRコードを再読み込みする事で、MFA有効化に成功