🐕‍🦺

YubiKeyで二要素認証しながらAWSリソースへ対しTerraformを実行する話

2021/12/16に公開

この記事はterraform Advent Calendar 2021の16日目です。

TL;DR

  • ローカル環境からAWSリソースに対しTerraformを実行する際にYubiKeyで二要素認証を行う記事です

  • Terraform/AWS Vault/ykman(YubiKey Manager CLI)を使用します

  • terraform plan/apply/importなどがTerraform Enterprise/Terraform CloudやCI/CD Pipeline&tfmigrateで実行されるようになっている環境では不要な記事です

  • 投稿者環境はmacOSです。他OSの場合は公式ドキュメントを参考に適宜読み替えてください

  • YubiKey 5Cを使用した記事です。OATHが有効なモデルであれば流用できると思います

    • 使用しているYubiKeyがOATH対応しているかの確認方法は後述します
  • AWS VaultのUSAGE.md#using-a-yubikeyに当記事でやろうとしていることの全てが書いてあります

背景

  • お仕事でローカル環境のTerraformを使用して顧客のパブリッククラウド環境にアクセスする際、セキュリティ要件としてYubiKeyなどの物理デバイスでの二要素認証対応を求められる場合があります
  • AWSの場合、AWS Management Consoleは物理デバイスでの二要素認証をサポートしていますが、AWS CLIやTerraformなどのAccess Keyを使用したCLIツール経由のアクセスでは物理デバイスをサポートしていないため、AWS Vaultなどのツールの助けが必要になります
  • Terraform Enterprise/Terraform CloudとCI/CD Pipeline&tfmigrateを使用すれば各自のローカル環境に顧客AWSリソースに対する強力な操作権限を付与することを排除することもできますが、そこに至っていない環境の場合に参考になれば幸いです

こんな感じに仕上がります

  • aws-vaultでterraform実行時にYubiKeyをTouchすれば二要素認証を通過できるようになります。OTPはykmanがYubiKeyデバイスから取得してくれます
❯ aws-vault exec --prompt ykman ${YOUR_AWS_PROFILE} -- terraform apply
Touch your YubiKey...

aws_s3_bucket.log: Refreshing state... [id=${YOUR_AWS_PROFILE}]

..(snip)..

事前準備

01.Terraform / AWS Vaultのセットアップ

02.ykman(YubiKey Manager CLI)のセットアップ

  • 公式ドキュメント: YubiKey Manager CLI
  • Installation
    • brew install ykman
  • [必要かどうか確認中]ykmanにキーボードの入力監視を許可する
    • YubiKey Manager(ykmanのGUI版)では必要な権限なのでykmanでも必要…に見えるんだけど確証が無いので確認取れ次第更新します
    • システム環境設定 > セキュリティとプライバシー > 入力監視 > "+" > 開いたウインドウにykmanのディレクトリをドラッグ&ドロップ > ykmanを選択し追加
      • ykmanをドラッグ&ドロップするためにykmanのあるディレクトリをFinderで開く: open $(dirname $(which ykman))

03.使用しているYubiKeyデバイスがOATH対応しているか確認しておく

  • 使用しているYubiKeyがOATH対応しているか確認確認する
    • ykman --device $(ykman list --serials) info
      • OATH EnabledとなっていればそのYubiKeyデバイスはOATH対応している
      $ ykman --device $(ykman list --serials) info
      Device type: YubiKey 5C
      ..(snip)..
      Applications
      ..(snip)..
      OATH        	Enabled
      ..(snip)..
      
    • 複数のYubiKeyを使用している場合は"$(ykman list --serials)"を任意のYubiKeyのシリアルに置き換えてください

AWS VaultでYubiKeyを使った二要素認証を通しつつ、AWSリソースへTerraformでアクセスする

  • 流れはAWS VaultのUSAGE.md#using-a-yubikeyにある通りです
    • 当記事におかしな点があれば上記を参照してみてください

IAM Userの二要素認証デバイスにYubiKeyを登録する

  • YubiKeyで二要素認証したいIAM UserのARN(A)を手元に用意しておきます
    • AWS Management Cosoleの下記から取得できます
      • IAM Management Cosole > Users > ${TARGET_IAM_User}
      • こんなやつ: arn:aws:iam::${AWS_ACCOUNT_ID}:mfa/${TARGET_IAM_User}
  • AWS Management ConsoleからIAM Userの二要素認証デバイス登録画面を開き、Secret Key(B)を取得します
    • IAM Management Cosole > Users > ${TARGET_IAM_User} > Security credentials > Assigned MFA device > Manage > Virtual MFA device > Continue > Show secret key
  • ykmanに(A)をOATH accountとして登録する
    $ ykman oath accounts add -t (A)
    Enter a secret key (base32): (B)
    
  • ykmanで認証コードx2を取得しAWS Management Consoleの二要素認証デバイス登録画面に登録する
    • 認証コードは下記で取得できます。30秒ごとにコードが更新されるので時間を空けつつ下記を実行し、2つの認証コードを取得して二要素認証デバイス登録画面の"3. Type two consecutive MFA codes below"に登録します
    $ ykman oath accounts code (A)
    
  • ここまでで問題無ければ二要素認証デバイス登録画面の"Assign MFA"ボタンを押し、デバイス登録を完了させます

AWS Vaultで(A)のAccess Keyを紐付けたAWS Profileを作成し、二要素認証デバイスを紐付ける

  • AWS Vaultで(A)のAccess Keyを紐付けたAWS Profileを作成する
    • 今回は"MFAbyYubikey"という名前のAWS Profileを作成しています
    $ aws-vault add MFAbyYubikey
    ※Access Key IDとSecret access keyを聞かれるので(A)のものを登録する
    
  • 上で作成したAWS ProfileにMFAデバイスのARN(B)を紐付ける
    • 今回は"MFAbyYubikey"という名前のAWS Profileを作成しています
    $ vi ~/.aws/config
    [profile MFAbyYubikey]
    mfa_serial=${(B)}
    
    • 雑にやるならこれでもいい
    $ echo "mfa_serial=${(B)}" >> ~/.aws/config
    

terraform applyしてみる

  • 下記のようにaws-vaultでMFAデバイスを通して二要素認証しつつterraform applyします
$ aws-vault exec --prompt ykman MFAbyYubikey -- terraform apply
Enter token for (A): ここにOTPを入力
aws_s3_bucket.log: Refreshing state... [id=MFAbyYubikey]
..(snip)..
  • "Enter token for (A):"にはMFAデバイスから取得したOTPを入力します
    • OTPはykmanで取得します
      $ ykman oath accounts code (A)
      Touch your YubiKey...
      (A)  xxxxxx
      
  • 一度二要素認証を通した後は
    • STS Sessionの有効期限切れるまでは何もしなくても(=YubiKeyのボタンにタッチすることも不要)terraformコマンドが通る
    • STS Sessionの有効期限が切れてもYubiKeyのボタンをタッチするだけでykmanがOTPを取得してAWSへ送ってくれます。便利。
    • STS Sessionの有効期限はaws-valut listで確認できる。*マイナス値の場合は有効期限が切れている
      $ aws-vault exec --prompt ykman MFAbyYubikey -- terraform apply
      Touch your YubiKey... *ここでYubiKeyのボタンをタッチ
      
      いつものplanが表示されます
      

おわりに

当記事では各自のローカル環境からTerraformでAWSリソースを操作する際にYubiKeyで二要素認証を通す方法について説明しました。

個人的には各自のローカル環境にAWSリソースを操作できる権限を置きたくない派です。当記事の内容はあくまで環境が整うまでのつなぎに留め、早めにplan/applyはTFC/TFE、import/state mvはCI/CD+tfmigrateに移行していきたいですね。

ではでは。

Discussion