Amazon Elastic Compute Cloud (Amazon EC2) インスタンスで AWS SDK for Java を使用している Java アプリケーションが、次のような例外を受け取ります。
com.amazonaws.AmazonServiceException: The security token included in the request is expired (Service: AmazonSQS; Status Code: 403; Error Code: ExpiredToken; Request ID: 12a345b6-78cd-901e-fg23-45hi67890jkl)
このエラーはどのように解決すればよいですか?
簡単な説明
アマゾン ウェブ サービス (AWS) へのアプリケーション API リクエストはすべて、AWS が発行した認証情報を使用して暗号で署名される必要があります。
アプリケーションが AWS クライアントの作成時に一時的な認証情報を使用すると、その認証情報は、クライアントの作成中に、指定された時間間隔で有効期限が切れます。認証情報は、有効期限が切れる前に更新する必要があります。
有効期限が切れるもうひとつの理由は、誤った時間の使用です。一貫性がある正確なタイムリファレンスは、多くのサーバータスクとプロセスにとって必要不可欠です。インスタンスの日付と時刻が正しく設定されていなければ、AWS の認証情報は拒否されます。
アプリケーションが Amazon EC2 インスタンスで実行されている場合は、インスタンスに割り当てられた AWS Identity and Access Management (IAM) ロールを使用することがベストプラクティスです。IAM ロールを使用することにより、デフォルトのサービスコンストラクタを使用できるようになります。デフォルトのコンストラクタクライアントは、次の順序で、デフォルトの認証情報プロバイダーチェーンを使用して認証情報を検索します。
- システム環境変数: AWS_ACCESS_KEY_ID および AWS_SECRET_ACCESS_KEY。
- Java システムプロパティ: aws.accessKeyId と aws.secretKey。
- デフォルトの認証情報ファイル (このファイルの場所はプラットフォームによって異なります)。
- EC2 インスタンスの IAM ロールに関連付けられたインスタンスメタデータに含まれるインスタンスプロファイルの認証情報。インスタンスプロファイルをインスタンスにアタッチすることにより、デフォルトの認証情報プロバイダーチェーンにインスタンスプロファイルの認証情報が追加されます。詳細については、「Amazon EC2 インスタンスで実行されるアプリケーションに IAM ロールを使用してアクセス許可を付与する」をご参照ください。
インスタンスプロファイルの認証情報が有効な場合、デフォルトのクライアントコンストラクタは、AWS SDK InstanceProfileCredentialsProvider クラスのインスタンスを作成します。AWS は、Amazon EC2 インスタンスメタデータからの一時的なセキュリティ認証情報を使用して AWS の認証情報で API リクエストに署名するために、このクラスを使用します。
重要: アプリケーションで、AWS SDK の ProfileCredentialsProvider クラスを使用して、一時的な AWS 認証情報を指定している場合は、有効期限が切れる前に、認証情報を確認して更新する必要があります。認証情報の確認や更新を行わない場合、ExpiredToken エラーによってアプリケーションの障害が発生する可能性が高くなります。
解決方法
Amazon Time Sync Service または NTP ソースを使用する
Amazon EC2 インスタンスで Amazon Time Sync Service、または別のネットワークタイムプロトコル (NTP) ソースを設定します。これにより、Linux インスタンスで一貫した正確なタイムリファレンスが確実に行われるようになります。詳細については、「Linux インスタンスの時刻の設定」、または「Windows インスタンスの時刻の設定」をご参照ください。
カスタムの一時的な AWS 認証情報を使用する
有効期限が切れる 5 分前に一時的認証情報を更新する
インスタンスに割り当てられた IAM ロールを使用する
インスタンスプロファイルをインスタンスにアタッチします。詳細については、「Amazon EC2 インスタンスで実行されるアプリケーションに IAM ロールを使用してアクセス許可を付与する」をご参照ください。コードまたはインスタンスで他の認証情報が指定されていないことを確認します。デフォルトの認証情報プロバイダーチェーンが認証情報を検索する際にインスタンスプロファイルの認証情報を使用することはほとんどありません。検索チェーンのこれより前の場所に認証情報がある場合、それらの認証情報によって IAM の使用が妨げられます。詳細については、「AWS 認証情報の使用」をご参照ください。
インスタンスにアタッチされている IAM ロールの AWS 認証情報を表示するには、Linux シェル、または Windows PowerShell (v3.0 以降) から次のコマンドを実行します。examplerole は必ず、IAM ロールの名前に置き換えてください。
Linux
curl コマンドを使用して、AWS 認証情報を表示します。
$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/examplerole
このコマンドは、次のような出力を返します。
{
"Code" : "Success",
"LastUpdated" : "2016-04-26T16:39:16Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Token" : "token",
"Expiration" : "2016-04-27T22:39:16Z"
}
注: 前述の curl コマンドを実行すると 404 エラーが返される場合は、次の点を確認してください。
1. 次のコマンドを使用して、メタデータ IP アドレスの HTTP プロキシが無効になっていることを確認します。
$ export NO_PROXY=169.254.169.254
2. インスタンスが複数の同時リクエストを行っておらず、複数のセッションを並行して実行していないことを確認します。複数の同時リクエストと複数のセッションを並行して実行すると、Instance Metadata Service (IMDS) によるスロットリングが発生する可能性があります。これを緩和するには、キャッシュを使用し、エクスポネンシャルバックオフで再試行します。他のサービスと同様に、たまに呼び出しが失敗することがあります。この問題が発生すると、クライアントは再試行する必要があります。詳細については、「クエリのスロットリング」をご参照ください。
再試行を実行するには、AWS_METADATA_SERVICE_NUM_ATTEMPTS を変更します。~/.aws/config ファイル、またはユーザーの botocore セッションで、環境変数を使用してオプションを設定できます。詳細については、Boto3 DOCS 1.17.6 ドキュメントの「設定」をご参照ください。
例:
AWS_METADATA_SERVICE_TIMEOUT = 10
AWS_METADATA_SERVICE_NUM_ATTEMPTS = 5
3. Docker コンテナで curl テストを実行している場合は、instance-metadata-options http-put-response-hop-limit を調整します。
$ aws ec2 modify-instance-metadata-options --instance-id $(curl 169.254.169.254/latest/meta-data/instance-id) --http-put-response-hop-limit 2 --http-endpoint enabled
詳細については、「EC2 Instance Metadata Service の機能強化を使用して、オープンファイアウォール、リバースプロキシ、および SSRF 脆弱性に対する詳細な防御を追加する」をご参照ください。
4. インスタンスプロファイルがインスタンスに正しくアタッチされていることを確認します。
Windows
Invoke-RestMethod コマンドを使用して、AWS 認証情報を表示します。
PS C:\> Invoke-RestMethod http://169.254.169.254/latest/meta-data/iam/security-credentials/examplerole
このコマンドは、次のような出力を返します。
Code : Success
LastUpdated : 2016-07-18T18:09:47Z
Type : AWS-HMAC
AccessKeyId : AKIAIOSFODNN7EXAMPLE
SecretAccessKey : wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Token : token
Expiration : 2016-04-27T22:39:16Z
これらのコマンドを使用して、インスタンスのための最新の一時的な認証情報を確認します。これらの認証情報は、割り当てられた一時的な認証情報の有効期限が切れる約 5 分前に、自動的にローテーションまたは更新されます。
関連情報
Working with AWS credentials (AWS 認証情報の使用) (AWS SDK for Java)
Using credentials (認証情報の使用) (AWS SDK for Java 2.0)
Amazon EC2 の IAM ロール