🔒

aws-vaultを使った複数のAWS環境管理術

2023/04/04に公開
2

こんにちは、へたれです。
株式会社AidemyでModeloyという伴走型のDXプロジェクト内製化支援サービスを提供するチームに所属しています。

クラウドインフラをメインに、バックエンドからフロントエンドまで幅広く携わっています。
複数のプロジェクトに横断的に関わっており、頻繁に作業環境を切り替えることも多い中で、どのように管理しているか記事にしました。

TL;DR

自社のテスト環境や複数のお客様向けにAWS環境をセキュアに管理するために以下の方針を採用

  • シークレットキーの管理はaws-vaultを使う
  • profileを使い分け、素早く環境の切り替えが行えるようにする

Terraformの実行はaws-vault exec <profile-name> -- terraform planを使う。
CodeCommitの切り替えは.github/configを使う。

はじめに

Modeloy Engineeringでは同時に複数社のお客様を支援することがあり、それぞれのお客様向けに異なるAWS環境で作業をする必要がありました。

その中でいくつか困りごとが出てきました。

  • ローカル環境に生のシークレットキーを置くことの不安
  • 複数の環境を頻繁に往来するときの手間
  • 誤ったTerraformをapplyしないかの心配

これらの課題を解決するために導入したツールや運用方法をご紹介します。

導入したツールと運用

aws-vaultの導入

aw-vaultはAWSのシークレットキーをmacOSのKeyChainで管理してくれるツールです。
~/.aws/credentialsなどに生データ保存せずに済み、アクセスにアカウントのパスワード入力が必要となるため、漏洩によるセキュリティリスクを抑えることが可能です。
またaws-vault実行時にプロファイル指定でき、すべてのコマンドをaws-vault経由で実行することで切り替えが容易になるのもとても便利です。

導入はHomebrew経由で実施できるので非常に簡単です。
使用時の雰囲気はこんな感じです。

# プロファイルにシークレットキーを登録
$ aws-vault add oriishi-t
Enter Access Key ID:
Enter Secret Access Key:

# プロファイルの登録を確認
$ aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
oriishi-t                oriishi-t                -

# aws-vaultを通じて任意のプロファイルで任意のコマンドを実行
$ aws-vault exec -- aws sts get-caller-identity
XXXXXXXXXXX    arn:aws:iam::XXXXXXXXXXX:user/oriishi-t   XXXXXXXXXXX

# aws-vaultを通じて任意のプロファイルでAWSコンソールへのログインも可能
$ aws-vault login oriihi-t

またスイッチロールやMFAを利用する場合は、いつもどおり~/.aws/configに各種設定値を書きます。

~/.aws/config
[profile oriishi-t]
region=ap-northeast-1
output=text

[profile env1]
source_profile=oriishi-t
role_arn=arn:aws:iam::XXXXXXXXXXX:role/RoleName
aws_mfa_device=arn:aws:iam::XXXXXXXXXXX:mfa/device-name
mfa_serial=arn:aws:iam::XXXXXXXXXXX:mfa/device-name

[profile env2]
source_profile=oriishi-t
role_arn=arn:aws:iam::XXXXXXXXXXX:role/RoleName
aws_mfa_device=arn:aws:iam::XXXXXXXXXXX:mfa/device-name
mfa_serial=arn:aws:iam::XXXXXXXXXXX:mfa/device-name

[profile env3]
source_profile=oriishi-t
role_arn=arn:aws:iam::XXXXXXXXXXX:role/RoleName
aws_mfa_device=arn:aws:iam::XXXXXXXXXXX:mfa/device-name
mfa_serial=arn:aws:iam::XXXXXXXXXXX:mfa/device-name

これだけで使えるようになります。

自分はプロファイル名に以下の情報を含めています。

  • プロジェクト名
  • 環境名(dev, stg, prdなど)
  • IAMロールに付与された権限 (admin, roなど)

そうすることで以下のような効果が得られています。

  • どのプロファイルで作業すべきかがすぐにわかる
  • 作業するプロファイルを毎回手入力するので、作業環境を間違えることが少なくなる

terraformとの併用

Terraformで利用する際にはバックエンドにprofileパラメタを指定します。

env1.tfbackend
profile        = "env1"

実行時はaws-vaultを通すだけです。

$ aws-vault env1 -- terraform init -backend-config=env1.tfbackend
$ aws-vault env1 -- terraform apply

注意
aws-vault exec oriihi-t -- tf applyのようにexecにそのままコマンドを渡すと、エイリアスが継承されません。
一方でaws-vault exec oriishi-tを実行すると、シェルが新規に展開されるため、.bashrc等に設定しているエイリアスも使えるようになります。

codecommitとの併用

aws-vaultを使ったCodeCommitへのクレデンシャル情報の設定も可能です。
GitHubとCodeCommitの併用が必要な場合はリモートリポジトリを複数設定することも可能です。
クレデンシャルヘルパーの設定をしましょう。

.git/config
...
[remote "prj1"]
  url = https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/repository-name
  fetch = +refs/heads/*:refs/remotes/prj1/*
[credential "https://git-codecommit.ap-northeast-1.amazonaws.com"]
 helper = !aws-vault exec env1 -- aws codecommit credential-helper $@
 UseHttpPath = true
...

以上の設定ができればCodeCommitとのpush/pull操作が可能になるはずです。

# MFAが有効な場合のみ必要
$ aws-vault exec env1 -- echo ''

# prj1リモートを使用
$ git push prj1 HEAD

注意
gitのクレデンシャルヘルパーはMFAの認証ができません。
aws-vault exec env1 -- echo ''を実行することで、あらかじめMFAの認証を通しておき、有効期限のうちにgitの操作を済ませてしまいます。
また、aws-vaultで実行している環境下ではAWS_VAULT環境変数が設定されており、これが設定されているとaws-vaultが使えないためaws-vault exec env1 -- git push prj1 HEADのようなコマンドは使えません。

注意
CodeCommitのクレデンシャルヘルパーはKeyChainに認証情報を保存するため、認証情報が切れる時に403エラーを吐き出します。
403エラー時の対応として、KeyChainから対象の情報を削除してください。

終わりに

ここで紹介した運用を導入した結果、シークレットキーの安全な管理と利便性の向上が両立できました。
新しくジョインしたメンバーにもこの運用を広めており、改善を重ねていきがながらこの運用をチームのスタンダードにしていきたいと思っています。
今日も一日、ご安全に!

Aidemy Tech Blog

Discussion

2357gi2357gi

下記設定を使用することで、わざわざ execして認証情報通ったshellを作成しないでも --profile <profile名>オプションを使用することができますよ

[profile <profile名>]
credential_process=aws-vault exec <profile名> 

あらかじめMFAの認証を通しておき、有効期限のうちにgitの操作を済ませてしまいます。

aws-vaultがデフォルト1時間なので、 --duration 12hオプションを渡してあげるのが個人的には好みです

へたれへたれ

おお、ありがとうございます!
credential_process は知らなかったです...情報提供感謝します!

aws-vaultがデフォルト1時間なので、 --duration 12hオプションを渡してあげるのが個人的には好みです

なるほど...頻度が多くなってくるとこういった対策は有効ですね。