我的 Java 应用程序在 Amazon Elastic Compute Cloud (Amazon EC2) 实例上使用适用于 Java 的 AWS SDK。但是,我收到了 "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)" 错误消息。
简短描述
所有应用程序 API 请求都必须使用 AWS 提供的凭证进行数字签名。如果您的应用程序使用临时凭证创建 AWS 客户端,则必须在凭证过期之前续订这些凭证。如果您的凭证过期,您将会收到 "security token included in the request is expired" 错误消息。
解决方法
确保您的实例具有一致的时间参考
如果凭证使用的时间不正确,则会导致凭证过期,因此请确保您的服务器准确无误。您的 EC2 实例必须具有一致且准确的时间和日期参考。在您的实例上配置 Amazon Time Sync Service 或其他网络时间协议 (NTP) 源。有关更多信息,请参阅更改实例的时区。
确保您的临时凭证未过期
如果您使用临时凭证,请确保它们没有过期。如果临时凭证已过期,则您必须生成一组新的临时凭证并使用这些凭证。最佳做法是在临时凭证过期前五分钟刷新该凭证。
检查您的 IAM 配置
对于在实例上运行的应用程序,最佳做法是为实例使用 AWS Identity and Access Management (IAM) 角色。
如果您使用 IAM 角色,请确保仅在实例配置文件中列出该角色的凭证。使用 IAM 角色时,默认服务构造函数将使用默认凭证提供商链按以下顺序搜索凭证:
- 系统环境变量 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY。
- Java 系统属性 aws.accessKeyId 和 aws.secretKey。
- 默认凭证文件。
- 实例配置文件凭证,位于与 IAM 角色关联的实例元数据中。
如果您列出除实例配置文件以外的任何位置的凭证,则默认客户端构造函数会首先找到这些凭证。此配置会阻止 IAM 角色凭证。要解决此问题,请检查其他位置是否存在凭证。要检查默认凭证文件,请根据您的操作系统 (OS) 检查以下位置:
- 对于 Linux、macOS 或 Unix,请检查 * ~/.aws/credentials。
- 对于 Windows,请检查 C:\Users\USERNAME\.aws\credentials
注意: 将 USERNAME 替换为您的用户名。
如果您在实例配置文件之外的任何位置找到凭证,请将其移除。有关临时凭证配置的更多信息,请参阅为适用于 Java 的 AWS SDK 提供临时凭证。
要检查 IAM 角色的凭证,请根据您的操作系统运行以下命令。确保使用 Windows PowerShell 版本 3.0 或更高版本,或从 Linux Shell 中运行。
Windows:
PS C:\> Invoke-RestMethod http://169.254.169.254/latest/meta-data/iam/security-credentials/examplerole
注意: 将 examplerole 替换为您的 IAM 角色的名称。如果您使用临时凭证,则上述命令会显示实例的最新临时凭证。
输出示例:
Code : SuccessLastUpdated : 2016-07-18T18:09:47Z
Type : AWS-HMAC
AccessKeyId : AKIAIOSFODNN7EXAMPLE
SecretAccessKey : wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Token : token
Expiration : 2016-04-27T22:39:16Z
Linux:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/examplerole
注意: 将 examplerole 替换为您的 IAM 角色的名称。如果您使用临时凭证,则上述命令会显示实例的最新临时凭证。如果您在运行上述命令时收到 404 错误,请验证是否为元数据 IP 地址停用了 HTTP 代理。此外,请确保实例配置文件已附加到实例。
输出示例:
{ "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"
}
注意: 角色凭证会在分配的临时凭证过期前五分钟自动轮换或刷新。
配置重试
注意: 如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
如果您仍然遇到问题,请确认该实例没有发出多个并发请求或并行运行多个会话。这种情况可能会导致实例元数据服务 (IMDS) 限制查询。要缓解此问题,请使用通过指数回退重试模式。
要设置重试,请增加 AWS_METADATA_SERVICE_NUM_ATTEMPTS 的值,以便 Boto3 可以重试从实例元数据服务获取凭证的尝试。默认情况下,Boto3 在超时之前只尝试一次。此外,增加 AWS_METADATA_SERVICE_TIMEOUT 的值,以增加连接到实例元数据服务超时之前的秒数。默认情况下,连接在 1 秒后超时。
配置示例:
AWS_METADATA_SERVICE_TIMEOUT = 10
AWS_METADATA_SERVICE_NUM_ATTEMPTS = 5
要配置上述选项,请使用环境变量、~/.aws/config 文件或用户的 botocore 会话。有关说明,请参阅 Boto3 文档网站上的 Configuration(配置)。
如果您在 Docker 容器中运行 curl 命令,请运行以下 modify-instance-metadata-options AWS CLI 命令将跳数限制提高到 2:
aws ec2 modify-instance-metadata-options --instance-id instance --http-put-response-hop-limit 2 --http-endpoint enabled
注意: 将 instance 替换为您的实例 ID。有关详细信息,请参阅实例元数据访问注意事项中的在容器环境中,考虑重新配置或将跳数限制提高到 2。
相关信息
Authenticating with AWS using the AWS SDK for Java 2.x(使用适用于 Java 2.x 的 AWS SDK 进行 AWS 身份验证)
适用于 Amazon EC2 的 IAM 角色
Add defense in depth against open firewalls, reverse proxies, and SSRF vulnerabilities with enhancements to the Amazon EC2 Instance Metadata Service(通过增强 Amazon EC2 实例元数据服务,为开放式防火墙、反向代理和 SSRF 漏洞增加纵深防御)