― credentialsとconfigの扱い、そしてAssumeRoleの動きについて ―
プロジェクトで複数AWSアカウント(dev / stg)を切り替えながらCLI操作する必要があり、久々にAWS SSOまわりでトラブルに遭遇しました。
今回はその実体験をもとに、「なぜトークンが切れるのか?」「credentialsはどう扱うべきか?」といった点をまとめます。
SSOでCLI操作する場合、credentialsは基本的に空で問題ない
AWS CLIの認証情報ファイルには ~/.aws/credentials
と ~/.aws/config
の2つがあります。
しかしSSO認証を使う場合、credentials
には何も書かないのが基本方針です。
ところが今回は、過去に設定したままの以下のようなトークン付き認証情報を credentials
に書いてしまっていました。
[default]
aws_access_key_id = ASIAxxxxxx
aws_secret_access_key = yyyyyyyyy
aws_session_token = zzzzzzzzz
この設定が残っていたせいで、CLIコマンド実行時に古いトークンが読み込まれてしまい、下記のようなエラーが出ました。
aws s3 ls --profile stg@app
→ ExpiredTokenException: The security token included in the request is expired
SSOログインは正常に完了していたにもかかわらず、CLIは先にcredentials
の内容を読み込んでしまうため、古いトークンが優先されてしまっていたのです。
では credentials
が必要になるのは、どんなとき?
1. IAMユーザーによる認証(最も一般的)
SSOを導入していない組織や、CI/CDツールなどで明示的にアクセスキーを使う場合に使います。
[default]
aws_access_key_id = AKIAXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxx
このように ~/.aws/credentials
にアクセスキーとシークレットキーを記載することで、CLIやSDKがその情報を使って認証します。
例:
aws s3 ls --profile default
2. 一時クレデンシャルを使う AssumeRole の手動切り替え
外部アカウントに対して明示的に sts assume-role
でスイッチするケース。
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/YourRole \
--role-session-name my-session
このコマンドを実行すると、3点セットの一時的なクレデンシャルが得られます。
{
"AccessKeyId": "...",
"SecretAccessKey": "...",
"SessionToken": "..."
}
これを ~/.aws/credentials
の別プロファイルに手動で書くことで、その後のコマンドで使用できます。
3. CI/CD環境(GitHub Actions, Jenkins など)で明示的にキーを渡す場合
SSOはCLIやブラウザベースでの操作には向いていますが、CI/CDのような非対話的環境では向きません。
そのため、IAMユーザーやIAMロールに割り当てたアクセスキーを環境変数や credentials
経由で渡すことが一般的です。
例:GitHub Actions では以下のように環境変数で設定することが多いです。
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
アクセスポータルと aws sso login
の関係
AWSにはブラウザベースの「アクセスポータル」と、CLIで使う aws sso login --profile XXX
がありますが、本質的には同じ目的を持った入り口です。
- アクセスポータル:GUIでSSOログインする入り口
-
aws sso login
:CLIからSSOログインする入り口
どちらも、.aws/config
に設定された sso_start_url
, sso_account_id
, sso_role_name
などの情報に基づいてトークンを取得し、CLI操作ができるようになります。
複数環境では AWS_PROFILE
の指定が不可欠
プロジェクトでは、開発環境(dev)とステージング環境(stg)が別のAWSアカウントで管理されています。
SSOでは、まずdevアカウントにログインし、その後 stg
に対してAssumeRoleでスイッチしています。
このような場合は、CLIコマンド実行時に環境を明示する必要があり、以下のように AWS_PROFILE
を付けて実行しています。
AWS_PROFILE=stg@app <実行したいコマンド>
ちなみに、AssumeRoleとは?
- AssumeRoleは「他の権限を一時的に借りる」仕組み
- セキュリティ強化・環境分離・最小権限の実現に役立つ
- SSOと組み合わせることも多い
- 手動でも自動(SSO経由やIAMロール)でも使われる
AssumeRoleが必要な主なケース
ケース | 説明 | 目的 |
---|---|---|
1. 複数AWSアカウント間の操作 | 本番用・開発用などでアカウントが分かれており、AアカウントからBアカウントのリソース操作をしたい | セキュリティ境界を保ちつつ操作権限を切り替える |
2. 限定的な権限での一時的操作 | 例えば通常は閲覧権限のみ、必要時にだけ「管理者ロール」にAssumeする | 必要なときだけ強い権限を持たせる(セキュリティ強化) |
3. SSOなどでログイン後、実際の操作権限をロールで制御 |
AWSReservedSSO_XXXXX のようなロールにAssumeされて操作される |
SSOの仕組み上、自動的にAssumeRoleされて権限を付与 |
4. LambdaやEC2などAWSサービスが実行時に使うIAMロール | 例:Lambda関数が別のサービスを呼び出すためのロールをAssumeする | サービス実行者に明示的なアクセスキーを渡さずに済む |
ロールの確認方法
SSOログイン後に、自分がAssumeしているロールを確認したい場合は以下のコマンドを使います。
aws sts get-caller-identity --profile xxx
この出力に含まれる arn:aws:sts::xxxx:assumed-role/〜〜〜/ユーザー名
を見ることで、現在どのロールにスイッチしているかを把握できます。
そして、そのロールの内容(AssumeRoleの信頼関係など)を確認するには、以下のように get-role
コマンドを使います。
aws iam get-role --role-name <ロール名>
ただし、SSO経由でAssumeしたロールによっては、IAM情報を閲覧する権限が制限されていて、このコマンドが実行できない場合もあります。
今回の学び(まとめ)
- SSOを使う場合、
credentials
ファイルには何も書かないほうが安全。 - CLIで操作する場合は、
.aws/config
にSSO情報を書いてaws sso login
を実行します。 - 環境ごとの切り替えは
AWS_PROFILE=xxx
を使って明示的に行う必要がある。 -
aws sts get-caller-identity
によって、今自分がAssumeしているロールを確認できます。 - 誤って古いアクセスキーやトークンが
credentials
に残っていると、SSOログイン後でもCLIコマンドが失敗します。
経験的な補足
CLIが読み込む順序やロールの扱いは非常に繊細です。
一見うまくいっているように見えても、一度発行したトークンが期限切れで残っていたり、SSO対象のアカウント・ロールの設定が不完全だったりすると、謎のエラーに直面することがあります。
今回は、昔設定していた credentials
の情報が悪さをしていたことに気づくまで時間がかかりました。
SSO + CLI運用では、「不要な情報をcredentialsに書かない」「コマンドごとにロールとアカウントを明示する」ことを徹底するのが肝要だと、改めて実感しました。