状況の説明
深夜のこと。デプロイが失敗した。何かを確認しようと aws s3 ls を実行すると、バケット一覧の代わりにこんなエラーが返ってくる:
An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.
コードは何も変わっていない。パイプラインは昨日まで動いていた。それなのに、AWSはあなたが誰なのかすら認識しようとしない。
このエラーは、AWSがパーミッションポリシーを評価する前に認証情報を拒否したことを意味する。そこまで到達すらしていない――アクセスキー自体が無効、削除済み、あるいは実在するIAMユーザーと一致していないのだ。
何が起きているのか
InvalidClientTokenId は「アクセス拒否」エラーではない。それよりも手前の段階で発生している。AWSは送信されたアクセスキーIDに一致するIAMエンティティを見つけられなかったのだ。よくある原因:
- アクセスキーがIAMで削除または無効化された
- キーが、操作対象とは別のAWSアカウントに属している
- リージョンの設定が間違っている――一部のサービス(特にSTS)は明示的なリージョン指定が必要
- 認証情報ファイルに、別の場所でローテーションされた古いキーが残っている
- 環境変数
AWS_ACCESS_KEY_IDがプロファイルの設定を暗黙的に上書きしている - キーが、後から削除されたIAMユーザー向けに生成されたものだった
- コピー&ペースト時にキー文字列に不可視文字が混入した
素早い診断
何かを触る前に、CLIが実際にどの認証情報を使っているか確認する:
# 送信されているキーIDを正確に確認する
aws configure list
# 出力例:
# Name Value Type Location
# ---- ----- ---- --------
# profile <not set> None None
#access_key ****************ABCD shared-credentials-file
#secret_key ****************wxyz shared-credentials-file
# region us-east-1 config-file ~/.aws/config
表示されているアクセスキーIDの末尾4文字をメモしておく。AWSコンソールのIAMと照合する――IAM → ユーザー → 対象ユーザー → セキュリティ認証情報の順に進む。そのキーがアクティブとして表示されていなければ、それが原因だ。
次に、環境変数がプロファイルを上書きしていないか確認する:
# Linux / macOS
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_PROFILE
# Windows (PowerShell)
$env:AWS_ACCESS_KEY_ID
$env:AWS_SECRET_ACCESS_KEY
これらの変数に古い値が残っていると、~/.aws/credentials の設定をすべて暗黙的に上書きしてしまう。警告も表示されず、何も示さずに優先されてしまうのだ。
修正1 — 古い環境変数をクリアする
環境変数が原因の場合は、削除してから再試行する:
# Linux / macOS
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
# Windows (PowerShell)
Remove-Item Env:AWS_ACCESS_KEY_ID -ErrorAction SilentlyContinue
Remove-Item Env:AWS_SECRET_ACCESS_KEY -ErrorAction SilentlyContinue
Remove-Item Env:AWS_SESSION_TOKEN -ErrorAction SilentlyContinue
その後、確認する:
aws sts get-caller-identity
修正2 — 有効なキーで再設定する
キー自体が古くなっているか削除されている場合は、新しいキーを生成する:
- AWSコンソールにログイン → IAM → ユーザー → 対象ユーザー → セキュリティ認証情報
- 古いキーが一覧にある場合は、まず無効化してから削除する
- アクセスキーを作成をクリック → ユースケースで「CLI」を選択
- アクセスキーIDとシークレットアクセスキーの両方を即座にコピーする――シークレットは一度しか表示されない
次に、CLIを設定する:
aws configure
# AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
# AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Default region name [None]: ap-southeast-1
# Default output format [None]: json
あるいは、リージョンや出力形式を変更せずに認証情報だけを更新する:
aws configure set aws_access_key_id AKIAIOSFODNN7EXAMPLE
aws configure set aws_secret_access_key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
修正3 — 認証情報ファイルを直接編集する
複数のプロファイルを管理する際はこちらの方が速い。ファイルを開いて内容を確認する:
# Linux / macOS
cat ~/.aws/credentials
# Windows
type %USERPROFILE%\.aws\credentials
正常なファイルはこのような形式になっている:
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[staging]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
キー値の前後に不可視文字が混入していないか確認する。Slack、Confluence、またはPDFからコピーした際に発生しやすい。長期キーは常に AKIA で始まり、一時的なSTSキーは ASIA で始まる。それ以外の文字が前後に付いていれば、それがバグの原因だ。
修正4 — STSの一時認証情報が期限切れ
ASIA で始まるキーは一時的なもの――aws sts assume-role またはSSOによって発行される。デフォルトでは1時間後に期限切れとなり、設定によっては最大12時間まで延長できる。更新するには:
# 認証情報にセッショントークンがあるか確認する
grep session_token ~/.aws/credentials
# SSOを使用している場合は再ログイン
aws sso login --profile your-profile
# assume-roleを使用している場合は再度assume-roleを実行
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/YourRole \
--role-session-name session1 \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text
修正の確認
# アカウントID、ユーザーARN、ユーザーIDが返されるはず
aws sts get-caller-identity
# 期待される出力:
# {
# "UserId": "AIDIODR4TAW7CSEXAMPLE",
# "Account": "123456789012",
# "Arn": "arn:aws:iam::123456789012:user/your-username"
# }
正常な出力が返れば完了だ。それでも InvalidClientTokenId が表示される場合は、認証情報ファイルのキーがアクティブなIAMユーザーと一致していない。正しいキーを保存したか再確認し、IAMユーザー自体がアカウントから削除されていないかも確認すること。
予防策
InvalidClientTokenId のインシデントのほとんどは同じことが原因だ:IAMでキーをローテーションしたのに、CI/CD、ローカルマシン、またはデプロイ済みサービスを更新し忘れる。キーと、そのキーの記録が乖離してしまうのだ。
- 可能な限りIAMロールを使用し、長期キーを避ける――EC2インスタンスプロファイル、Lambda実行ロール、ECSタスクロールなど。これらは自動的にローテーションされ、期限切れにもならない。
- 長期キーは90日ごとにローテーションする。 IAM Access Analyzerを使えば、ポリシーの閾値を超えた古いキーにフラグを立てられる。
- キーはシークレットマネージャーに保存する――AWS Secrets Manager、1Password、または類似のツール。プレーンテキストのファイルには監査証跡がなく、一元的な更新手段もない。
- 認証情報のワークフローをテストする際は、ToolCraftのパスワードジェネレーターのようなツールを使って強力なランダム文字列を生成する。ブラウザ上で完全に動作し、何もアップロードされない。
- アクティブなキーを監査するには:
aws iam list-access-keys --user-name your-user
複数のプロファイルで混乱している場合
複数のAWSアカウントを管理しているなら、対象のプロファイルを明示的に指定する:
# 特定のプロファイルを一時的に使用する
AWS_PROFILE=staging aws sts get-caller-identity
# フラグとして渡す
aws --profile staging s3 ls
# 現在のシェルセッションのデフォルトを設定する
export AWS_PROFILE=staging
これにより、stagingにいると思いながらprodに対してコマンドを実行してしまうという典型的なミスを防げる。また、キーの不一致をすぐに発見できる――被害が出た後ではなく、環境ごとに即座に気づけるのだ。

