ジャンプアカウント運用下でAWS CLI(+ AIエージェント)の認証情報を安全に扱う
ジャンプアカウント+スイッチロールを活用する環境における、AWS CLIの認証情報の扱い方についての検討・対応記録です。
概要
- ジャンプアカウントにサインイン後、スイッチロールで個人の検証用アカウントへ切り替える運用
- マネジメントコンソールへのサインインは1Passwordに任せている
- アクセスキーなどの認証情報を平文でローカルに保持することは禁止
- そのため、AWS CLIの
~/.aws/credentialsに直接アクセスキー・シークレットキーを書くことはできない
この制約の中で、AWS CLIをローカルから安全に実行し、さらにClaude Code等のAIエージェントからもAWS CLI操作を行えるようにするための認証構成を検討・構築しました。本記事ではその過程と最終的な構成を紹介します。
検討した方式と、採用しなかった方式
案1: 1Password CLIプラグイン方式(不採用)
1Password CLIのop plugin init awsを使い、awsコマンド自体をシェル関数でラップして1Passwordから認証情報を注入する方式を最初に検討しました。
この方式はターミナルから直接awsコマンドを叩く分には問題なく動作しました。しかし、AIエージェント(Claude Code)が内部でAWS CLIを呼び出す場合には利用できませんでした。理由は、この仕組みが「awsコマンドの呼び出しそのものを1Passwordが横取りして毎回認証情報を注入する」設計になっているためです。事前に取得しておいた認証情報を後からエージェント経由で再利用する、という使い方とは前提が噛み合いませんでした。
参考: AWSの認証情報を平文で保存しないように、1Password CLIに移行してみた
案2: aws login + export-credentials(不採用)
AWS CLIのaws loginコマンド(コンソールのサインインセッションをCLI用の一時認証情報に変換する機能)と、aws configure export-credentials --format envを組み合わせ、同一シェルセッションの環境変数にAIエージェント起動前に認証情報を注入する方式も試しました。
この方法はAIエージェントからも利用できましたが、
- 期限切れになると
aws loginからの認証操作をやり直す必要がある - ジャンプアカウント側の認証情報自体が
~/.aws/login/cacheに平文でキャッシュされる(平文ローカル保持の制約に照らすとグレー)
という課題があり、最終的な採用は見送りました。
参考: Claude Codeで1Password管理のAWS認証情報を用いてAWSの操作をする方法
案3: aws-vault + 1Password(MFA用途)(採用)
最終的に、認証情報の暗号化保持はaws-vaultに任せ、1PasswordはMFAのワンタイムパスワードの発行にのみ利用する構成に落ち着きました。
aws-vaultとは
aws-vaultは、AWSのアクセスキーなどの認証情報をOS標準の認証情報ストア(macOSならKeychain、WindowsならCredential Manager、LinuxならSecret Service/passなど)に暗号化した状態で保管し、必要なときだけ復号して一時的にAWS CLIやSDKへ渡してくれるオープンソースのツールです。
主な特徴は以下の通りです。
- アクセスキーを平文でファイルに書かない:
aws-vault add <profile名>で登録したアクセスキーは~/.aws/credentialsには保存されず、OSの暗号化ストアに保管されます credential_processとの連携:aws-vault exec <profile名> --jsonのように実行すると、AWS CLIのcredential_process仕様に沿ったJSON形式で一時認証情報を標準出力に返せます。これを他のプロファイルのcredential_process設定として指定することで、通常のAWS CLIコマンドから透過的に利用できます- MFA・セッションのハンドリング: プロファイルに
mfa_serialを設定しておくと、aws-vault exec実行時にMFAコードの入力を求め、GetSessionTokenで得た一時認証情報をキャッシュします(セッションの有効期限は環境変数で調整可能) - ロールチェーンのサポート:
role_arn・source_profileを使ったスイッチロール構成にもそのまま対応しています
今回の構成では、この「アクセスキーの暗号化保管」と「credential_processによるAWS CLIプロファイルへの一時認証情報の受け渡し」という2つの機能を利用し、1Passwordは仮想MFAデバイスとしての役割に限定しています。
シーケンスイメージ

登場人物が多いので複雑に見えますが、ユーザの操作は
- コマンドを実行
- パスワードを入力
- MFAコードを確認
- MFAコードを入力
- Claude起動
だけです。
AWSアカウント側の作業
- ジャンプアカウント側のIAMユーザーに仮想MFAデバイスを割り当てる(後述)
- 検証用アカウント側に、ジャンプアカウントのIAMユーザー(またはそのユーザーが所属するグループ/ロール)からのスイッチロールを許可するIAMロールを用意し、信頼ポリシーでジャンプアカウントを許可する
- 必要に応じて、信頼ポリシーに
aws:MultiFactorAuthPresent条件を付与し、MFA認証済みの場合のみロールを引き受けられるようにする
- 必要に応じて、信頼ポリシーに
- スイッチ先ロールに、実際の作業に必要な権限ポリシーをアタッチする
MFAデバイス登録(1Password)
- IAMユーザーの「セキュリティ認証情報」からMFAデバイスの割り当てを開始し、「認証アプリ」を選択する
- 表示されたQRコード(またはシークレットキー)を、スマートフォンの認証アプリの代わりに1Passwordの対象アイテムに登録する
- 1Passwordのアイテム編集画面で「ワンタイムパスワード」フィールドを追加し、QRコードをスキャンするかシークレットキーを手入力する
- 1Passwordに表示される最初のワンタイムパスワードと、続けて表示される次のワンタイムパスワードをそれぞれAWS側の入力欄に入力し、デバイス登録を完了する
これにより、以降のMFAコード入力は1Passwordから都度取得する運用になります。
ローカルPC側の作業
事前準備
認証情報を暗号化して保持するaws-vaultをローカルにインストールします。
brew install aws-vault
~/.aws/configの設定
ジャンプアカウントのIAMユーザー用プロファイル(MFAあり)、そこから認証情報を受け渡す中継プロファイル、実際にロールを引き受けるプロファイルの3段構成にします。
[profile main]
region = ap-northeast-1
output = json
mfa_serial = arn:aws:iam::123456789012:mfa/your-iam-user-name
[profile common]
region = ap-northeast-1
credential_process = aws-vault exec main --json --prompt=osascript --duration=8h
[profile target]
role_arn = arn:aws:iam::234567890123:role/your-switch-role-name
source_profile = common
region = ap-northeast-1
role_session_name = target
main: アクセスキーを保持する実体。mfa_serialをここに設定することで、aws-vaultが一時セッションを取得する際に必ずMFAを要求するようにしているcommon:mainの認証情報をaws-vault経由(暗号化ストレージ)で受け渡すだけの中継プロファイル。--prompt=osascriptでMFA入力をmacOSのダイアログに、--duration=8hでセッションを8時間に延長している(後述の「運用上の注意」を参照)target: 実際にスイッチロールで検証アカウントへアクセスするためのプロファイル
認証情報の登録
$ aws-vault add main
Enter Access Key Id: ABDCDEFDASDASF
Enter Secret Key: %%%
このように、コマンド実行後に対話形式でアクセスキーID・シークレットアクセスキーの入力を求められます。入力した内容は平文のファイルには保存されず、OSのキーチェーンに暗号化された状態で登録されます。
動作確認
$ aws sts get-caller-identity --profile target
{
"UserId": "AROAEXAMPLEROLEID:target",
"Account": "234567890123",
"Arn": "arn:aws:sts::234567890123:assumed-role/your-switch-role-name/target"
}
CLIから直接使う場合は、コマンドごとに--profile targetを付けるか、事前に
export AWS_PROFILE=target
を実行しておきます。この状態で同じターミナルセッション内でClaude Codeなどのエージェントを起動すると、エージェントが内部で呼び出すAWS CLIも同じプロファイル・認証情報チェーンを利用でき、継続してAWS操作を指示できることを確認しました。
運用上の注意
Claude Codeから実行した例
同じターミナルセッションで起動したClaude Codeに、次のように指示してみます。
> targetプロファイルを利用してS3バケットの一覧を取得して
targetプロファイルでS3バケットの一覧を取得しました。以下の3つのバケットが見つかりました。
sample-bucket-logs
sample-bucket-assets
sample-bucket-backup
まとめ
- コンソールサインインは1Password、AWS CLIの長期キーはaws-vaultの暗号化ストレージ、MFAコードの発行は1Password、という役割分担にすることで、平文でのローカル認証情報保持を避けつつ、CLIおよびAIエージェントからのAWS操作を両立できました
- 1Password CLIのAWSプラグインは便利ですが、「コマンド呼び出しそのものをラップする」設計のため、エージェント経由でのサブプロセス実行とは相性が悪い点に注意が必要です








