AWS CLIにおける「アクセス拒否」と認証問題のトラブルシューティング

AWS CLI使用時に発生する「アクセス拒否」や認証エラーを体系的にトラブルシューティングします。このガイドでは、`aws sts get-caller-identity`を使用した認証情報の検証、複雑なIAMポリシー評価階層の調査、一時的な認証情報やリソースベースのポリシー(S3バケットポリシーなど)に起因する問題の解決など、重要な診断手順を網羅しています。主要なコマンドとIAMポリシーシミュレーターを活用して、AWS環境における認証失敗を迅速に特定し修正する方法を学びます。

AWS CLIにおける「アクセス拒否」と認証問題のトラブルシューティング

AWS CLIでのAccess Denied(アクセス拒否)は、エラーメッセージに失敗したAPI呼び出しは表示されるものの、その原因となったポリシー行が示されないため、 frustration(フラストレーション)が溜まります。これらの問題は、ほとんどの場合、誤って設定されたIdentity and Access Management(IAM)ポリシー、期限切れの一時認証情報、またはCLI環境の誤った設定に起因します。

問題を2つの質問に分割する習慣が役立ちます。CLIは誰として呼び出しているのか、そしてそのIDがアクションを実行するのを妨げているポリシーバウンダリーは何か、です。

1. 初期診断:呼び出し元と認証情報の特定

複雑なポリシー分析に飛び込む前に、まずAWS CLIがどのIAM IDを使用しているか、そしてそれらの認証情報がまだ有効かを明確に確認することが最初のステップです。

現在のIDの確認:sts get-caller-identity

これは最も重要な診断コマンドです。後続のAWSコマンドを実行しているのが、どのユーザーARN、ロールARN、または引き受けたロールセッションかを正確に教えてくれます。

aws sts get-caller-identity

期待される出力:

{
    "UserId": "AIDAIAMUSERID",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/DevUser"
}

返されたARNが期待するユーザーやロールと一致しない場合、間違ったAWSプロファイルまたは環境変数で操作していることになります。

プロファイル設定とリージョンの確認

正しいAWSプロファイルが使用されていることを確認します。これは--profileフラグで指定するか、AWS_PROFILE環境変数で設定します。

# デフォルトプロファイルの設定内容を確認
aws configure list

# 特定のプロファイルを確認
aws configure list --profile prod-admin

出力にリージョンがない、または誤ったリージョンが表示されている場合、グローバルリソースやリージョン固有のサービス(S3バケットやEC2インスタンスなど)に対する操作が失敗し、CLIが探している場所にリソースが見つからないためにAccess Deniedが発生することがあります。

ヒント: sts get-caller-identityコマンド自体が認証エラーで失敗する場合、アクセスキーに根本的な問題があることを示しています(キーが削除、失効、または誤っている可能性があります)。

一時認証情報の扱い

IAMロール(STS AssumeRole経由)を使用している場合、CLIはSessionTokenを含む一時認証情報で動作します。これらの認証情報は、セッションに設定された期間(デフォルト設定では多くの場合1時間)後に期限切れになります。AWS CLIは通常、標準の認証情報プロバイダーチェーンから情報を取得する場合、自動的にそれらを更新しますが、手動設定では失敗する可能性があります。

症状: コマンドは最初は動作するが、一定期間(例:60分)後に認証エラーで失敗する。

解決策: カスタムスクリプトや手動でロードした環境を使用している場合は、ロールを引き受ける方法に、認証情報の期限切れ時に更新するメカニズムが含まれていることを確認してください。


2. IAMポリシーと認可の詳細調査

使用されているIDを確認したら、次はそのIDに必要な権限がなぜ不足しているのかを判断します。AWSの認可失敗は、複数のポリシーが同時に評価されるため複雑です。

IAMポリシー評価階層

認可エラーは、通常、以下のポリシーコンポーネントのいずれかが原因で発生します。

  1. 明示的な拒否(Explicit Deny): 任意の適用可能なポリシー(ID、リソース、バウンダリー)内の明示的なDenyステートメントは、常にAllowステートメントを上書きします。
  2. 許可の欠如(Missing Allow): IDまたはリソースに適用されるポリシーが、特定のアクションを許可していない。

A. IDベースのポリシー(ユーザーとロール)

ユーザーまたは引き受けているロールに直接アタッチされているIAMポリシーを確認します。以下を確認してください。

  • アクションの欠如: ポリシーに必要なAPIアクション(例:s3:ListBucketec2:DescribeInstances)が具体的にリストされていますか?
  • リソースの制約: ポリシーはResource要素を使用して、アクションを特定のリソースに制限していますか?アクションが特定のARNを必要とする場合にResource: "*"を設定する、またはその逆を行うことは、よくあるエラーです。
  • 条件: 満たされていない条件(例:送信元IPアドレス、時刻、MFA要求)はありませんか?

B. リソースベースのポリシー(S3、SQS、KMS)

S3やKMSのようなサービスの場合、リソース自体に誰がアクセスできるかを指定するポリシーがあります。クロスアカウントアクセスや、多くのリソース固有の設計では、リソースポリシーもプリンシパルを許可する必要があります。同じアカウント内では、正確な相互作用はプリンシパルのタイプとサービスによって異なるため、IDポリシーだけで全ての結果が説明できるとは考えないでください。

例: 特定のVPCエンドポイント外のすべてのユーザーに対して明示的なDenyがあるS3バケット(リソースポリシー)にアクセスしようとすると、ユーザーのIAMポリシーに関係なく、Access Deniedになります。

C. 許可境界とSCP

組織がAWS Organizationsを使用している場合、サービスコントロールポリシー(SCP) はアカウント内で許可される最大権限を定義します。同様に、許可境界(Permission Boundaries) はIAMエンティティが持つことができる最大権限を制限します。

SCPまたはバウンダリーが必要なアクションを拒否している場合、IDポリシーが権限を付与していても、CLI操作は失敗します。

実用的なツール:IAMポリシーシミュレーター

複雑な障害をトラブルシューティングする場合、AWS Management ConsoleのIAMポリシーシミュレーターは非常に価値があります。特定のアクション(例:s3:GetObject)を特定のリソース(例:arn:aws:s3:::my-bucket/key)に対してテストし、IAMエンティティを指定することで、拒否の原因となっているポリシーステートメントを正確に特定するのに役立ちます。


3. よくある「アクセス拒否」シナリオと解決策

シナリオ1:S3アクセス拒否(リソース vs ID)

S3のAccess Deniedは、ユーザーポリシーまたはバケットポリシーのいずれかに起因する可能性があるため、注意が必要です。

原因 診断 解決策
バケットポリシーの許可欠如 sts get-caller-identityは成功するが、aws s3 lsが失敗する。 バケットポリシーを変更して、呼び出し元ARNが必要なアクション(s3:ListBuckets3:GetObject)を実行することを明示的に許可します。
KMS復号化権限の欠如 暗号化されたオブジェクトへのアクセスが失敗する(S3ポリシーで許可されていても)。 IAMエンティティが、オブジェクトを暗号化した基盤となるKMSキーを使用する権限(kms:Decrypt)を持っていることを確認します。
リクエスタ支払い(Requester Pays) 大きなファイルのダウンロード試行が失敗する。 バケットがRequester Paysを要求する場合、CLIコマンドに--request-payer requesterフラグを含める必要があります。

シナリオ2:条件失敗による暗黙的な拒否

多くのポリシーは、Multi-Factor Authentication(MFA)の要求など、セキュリティのベストプラクティスを強制する条件を利用します。

ポリシーに次のような条件が含まれている場合:

"Condition": {
    "Bool": {
        "aws:MultiFactorAuthPresent": "true"
    }
}

認証されたMFAなしでコマンドを実行しようとすると、アクションは暗黙的に拒否されます。

解決策: MFAが必要なコマンドの場合、まずMFAデバイスで認証されたSTSセッションを作成する必要があります。

# 1. MFAトークンを使用して一時認証情報を取得
aws sts get-session-token --serial-number arn:aws:iam::123456:mfa/user --token-code 123456

# 2. 結果のAccessKeyId、SecretAccessKey、SessionTokenをCLIセッションの環境変数としてエクスポートします。

シナリオ3:リージョンの欠落または誤り

常にAccess Deniedエラーになるわけではありませんが、正しいリージョンを指定せずにリソースに対してアクションを実行しようとすると、特にEC2、DynamoDB、EKSなどのリージョナルサービスを扱う場合、認可エラーやリソース未検出の失敗につながることがよくあります。

解決策: コマンドでリージョンを明示的に定義するか、プロファイルが正しく設定されていることを確認します。

aws ec2 describe-instances --region us-west-2

時間を節約するサービス固有のチェック

IAMエラーのデバッグは、AWSを1つの権限システムとして扱うのをやめると容易になります。各サービスは、独自のリソースモデルと条件キーを追加します。

S3の場合、バケットレベルのアクションとオブジェクトレベルのアクションを分離します。s3:ListBucketはバケットARNを使用しますが、s3:GetObjects3:PutObjectはバケット配下のオブジェクトARNを使用します。arn:aws:s3:::my-bucketに対してs3:GetObjectを許可するポリシーは形式が間違っています。オブジェクトアクセスにはarn:aws:s3:::my-bucket/*が必要です。逆の間違いもリスト操作では同様によくあります。

KMSの場合、IAMポリシーだけでなくキーポリシーも確認してください。ロールがkms:Decryptを持っているように見えても、キーポリシーがそのロールパスを許可していない場合、復号化は失敗します。これは、暗号化されたS3オブジェクトのダウンロード、暗号化されたEBSスナップショットの取得、またはカスタマーマネージドキーを使用するシークレットの読み取り時に発生します。

ECRの場合、Dockerログインとイメージプルには複数のサービスが連携する必要があります。CLI IDにはecr:GetAuthorizationTokenが必要な場合があり、リポジトリがアカウント間で共有されている場合、リポジトリポリシーでプルアクションを許可する必要があるかもしれません。クラスターノードロールがイメージをプルしている場合、個人の管理者プロファイルでデバッグしてもほとんど意味がありません。ノードロールまたはタスク実行ロールとしてテストしてください。

STS AssumeRoleワークフローの場合、信頼関係の両側を確認します。呼び出し元にはsts:AssumeRoleを呼び出す権限が必要であり、ターゲットロールの信頼ポリシーは呼び出し元を信頼する必要があります。信頼ポリシーに外部IDやMFA条件が存在する場合、AssumeRoleコマンドはそれを満たす必要があります。

環境の優先順位は経験者を惑わす可能性がある

AWS CLIは~/.aws/credentialsだけを読み取るわけではありません。コマンドラインフラグ、環境変数、名前付きプロファイル、SSOキャッシュエントリ、Web IDトークン、EC2またはECSメタデータ、プロファイルで設定されたロール引き受けなどを含む、認証情報プロバイダーチェーンを辿ります。そのため、aws configure listは1つのファイルを開くよりも有用です。

よくあるローカルの失敗は次のようなものです。export AWS_PROFILE=devを実行し、後で本番用の一時認証情報をAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENに貼り付けます。環境キーが優先されるため、devを使用しているように見えるコマンドが、実際にはエクスポートされたセッションを使用していることになります。一日中開いているターミナルでは、次を実行します。

env | sort | grep '^AWS_'

アカウントを頻繁に切り替える場合は、別々のターミナルタブ、認証情報ヘルパー、または破壊的なコマンドの前に呼び出し元IDを出力するラッパースクリプトを使用してください。出力の余分な行は、間違ったアカウントから削除するよりもコストがかかりません。

4. 診断コマンドのまとめ

以下のコマンドチェックリストを使用して、認証失敗の連鎖を迅速に診断します。

目標 コマンド 目的
IDの確認 aws sts get-caller-identity コマンドを実行しているARNを確認します。
設定の確認 aws configure list プロファイル設定、リージョン、出力形式を確認します。
ポリシーの有効性テスト (IAMポリシーシミュレーターを使用) IAM IDがリソースに対して特定のAPIアクションを実行できるか確認します。
ポリシー拒否の特定 aws cloudtrail lookup-events ... CloudTrailを使用して、ポリシー評価が失敗した正確なイベントレコードを確認します。

実際のデバッグ手順

良い最初のパスは次のようになります。シェルが既に設定されていると思っていても、プロファイルとリージョンを明示的に指定して失敗したコマンドを再度実行します。

AWS_PROFILE=prod-readonly aws s3 ls s3://example-audit-logs --region us-east-1
aws sts get-caller-identity --profile prod-readonly
aws configure list --profile prod-readonly

IDが間違っている場合は、そこで止めてください。環境内のAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENAWS_PROFILEAWS_REGIONを確認します。環境認証情報はプロファイルよりも優先され、以前エクスポートしたロールを忘れてCLIがそのロールとして動作することがあります。CIでは、失敗したステップの近くでaws sts get-caller-identityを出力して、ビルドログが実行時に使用されたロールを証明できるようにします。

IDが正しい場合は、正確なAPIアクションを書き留めてください。高レベルのコマンドはこれを隠すことがあります。aws s3 cpは、方向、暗号化、およびCLIがバケットを検査する必要があるかどうかに応じて、s3:GetObjects3:PutObjects3:ListBucketkms:Decrypt、またはkms:GenerateDataKeyを必要とする場合があります。エラーメッセージにAccessDeniedが含まれているがアクションが含まれていない場合、CloudTrailは通常、イベント名とリソースを提供します。

S3の場合は、バケットポリシー、オブジェクト所有権、ブロックパブリックアクセス設定、VPCエンドポイントポリシー、KMSキーポリシーを確認してください。KMSで暗号化されたオブジェクトの場合、S3の許可だけでは不十分です。呼び出し元は関連するKMS権限も必要であり、キーポリシーはプリンシパルパスを許可する必要があります。組織の場合は、IDポリシーを編集する前にSCPを確認してください。SCPはアクセスを許可することはできませんが、アカウント内の任意のプリンシパルが実行できることを制限できます。

予防策は、ほとんどが退屈な衛生管理です。つまり、短命なロール認証情報、明確に名前付けられたプロファイル、実際のARNに対してテストされた最小権限ポリシー、そしてエンジニアが実際にクエリできるCloudTrailの有効化です。最善の修正は、より広範なAction: "*"ではなく、リクエストに一致する1つの欠落したアクションまたは1つの拒否条件を見つけることです。