AWS 实例配置文件不适用于 Spring Cloud AWS
AWS Instance Profile doesn't work with Spring Cloud AWS
我有一个小型 Spring 启动应用程序,使用 Spring Cloud AWS (1.0.0.RELEASE
) 访问 SQS 队列。它正在部署在设置了实例配置文件的 EC2 实例上。看起来 AWS 方面的事情正在运作,因为我可以访问两个相关的元数据链接:iam/info
和 iam/security-credentials/role-name
,它们确实包含正确的信息。可以肯定的是,我使用了 aws cmdline 实用程序 (aws sqs list-queues),它确实有效,所以我想设置没问题。但是,当应用程序启动时,它会读取 application.properties
(其中包含行 cloud.aws.credentials.instanceProfile=true
),然后丢弃以下警告:com.amazonaws.util.EC2MetadataUtils: Unable to retrieve the requested metadata
并最终抛出以下异常:
Caused by: com.amazonaws.AmazonServiceException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1071)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:719)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:454)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:294)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2291)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:516)
at com.amazonaws.services.sqs.buffered.AmazonSQSBufferedAsyncClient.getQueueUrl(AmazonSQSBufferedAsyncClient.java:278)
at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.java:78)
at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.java:37)
at org.springframework.messaging.core.CachingDestinationResolverProxy.resolveDestination(CachingDestinationResolverProxy.java:88)
at org.springframework.cloud.aws.messaging.listener.AbstractMessageListenerContainer.start(AbstractMessageListenerContainer.java:295)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.start(SimpleMessageListenerContainer.java:38)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
... 17 common frames omitted
...这意味着由于某种原因 Spring Cloud AWS 未获取实例配置文件凭证。我在 com.amazonaws.request
上启用了 debug
日志级别,看起来发送请求时没有访问密钥和秘密密钥。
DEBUG --- com.amazonaws.request : Sending Request: POST https://sqs.eu-west-1.amazonaws.com / Parameters: (Action: GetQueueUrl, Version: 2012-11-05, QueueName: xxxxxxxxxxxxx, ) Headers: (User-Agent: aws-sdk-java/1.9.3 Linux/3.14.35-28.38.amzn1.x86_64 Java_HotSpot(TM)_64-Bit_Server_VM/25.45-b02/1.8.0_45 AmazonSQSBufferedAsyncClient/1.9.3, )
有人知道我遗漏了什么或至少有任何提示如何进一步调试吗?
编辑: 在浏览了一些 spring-cloud-aws 代码之后,我有点前进了。与 jar 捆绑在一起的配置文件 application.properties
有一些 accessKey
和 secretKey
的文本值。我的自定义 application.properties
没有这些属性,这可能导致 spring 使用捆绑文件中的值作为默认值。我将它们包含在空值中,这将异常更改为 com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain
。 AWS SDK 似乎配置了 DefaultProviderChain,但它仍然无法获取实例配置文件凭证。
这个问题的解决方案来自两个截然不同的事实。
将仅使用实例配置文件凭据,如果 application.properties
已将 instanceProfile
属性 设置为 仅 true
和 accessKey
设置为 null
(ContextCredentialsAutoConfiguration).
即使您将提供自定义 application.properties
文件,Spring 也会读取与应用程序 jar 捆绑在一起的 application.properties
文件(如果它确实存在)。如果是这样的话,两个文件的属性将加起来创建一个执行环境。我怀疑首先解析捆绑文件,然后再解析自定义文件,覆盖捆绑文件中存在的任何 属性。
在我的例子中,捆绑的 application.properties
有 accessKey 和 secretKey 占位符(带有假值),只要开发人员想要在 EC2 环境之外进行一些测试,就会填写这些占位符。这使得 accessKey 不为空,因此排除了实例配置文件路径。我刚刚从 jar 中删除了 application.properties 文件并解决了问题。
cloud:
aws:
credentials:
accessKey:
secretKey:
instanceProfile: true
useDefaultAwsCredentialsChain: true
如果您使用的是最新的 (2.X.X) Spring AWS 云,这就可以了。
我有一个小型 Spring 启动应用程序,使用 Spring Cloud AWS (1.0.0.RELEASE
) 访问 SQS 队列。它正在部署在设置了实例配置文件的 EC2 实例上。看起来 AWS 方面的事情正在运作,因为我可以访问两个相关的元数据链接:iam/info
和 iam/security-credentials/role-name
,它们确实包含正确的信息。可以肯定的是,我使用了 aws cmdline 实用程序 (aws sqs list-queues),它确实有效,所以我想设置没问题。但是,当应用程序启动时,它会读取 application.properties
(其中包含行 cloud.aws.credentials.instanceProfile=true
),然后丢弃以下警告:com.amazonaws.util.EC2MetadataUtils: Unable to retrieve the requested metadata
并最终抛出以下异常:
Caused by: com.amazonaws.AmazonServiceException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1071)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:719)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:454)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:294)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2291)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:516)
at com.amazonaws.services.sqs.buffered.AmazonSQSBufferedAsyncClient.getQueueUrl(AmazonSQSBufferedAsyncClient.java:278)
at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.java:78)
at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.java:37)
at org.springframework.messaging.core.CachingDestinationResolverProxy.resolveDestination(CachingDestinationResolverProxy.java:88)
at org.springframework.cloud.aws.messaging.listener.AbstractMessageListenerContainer.start(AbstractMessageListenerContainer.java:295)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.start(SimpleMessageListenerContainer.java:38)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
... 17 common frames omitted
...这意味着由于某种原因 Spring Cloud AWS 未获取实例配置文件凭证。我在 com.amazonaws.request
上启用了 debug
日志级别,看起来发送请求时没有访问密钥和秘密密钥。
DEBUG --- com.amazonaws.request : Sending Request: POST https://sqs.eu-west-1.amazonaws.com / Parameters: (Action: GetQueueUrl, Version: 2012-11-05, QueueName: xxxxxxxxxxxxx, ) Headers: (User-Agent: aws-sdk-java/1.9.3 Linux/3.14.35-28.38.amzn1.x86_64 Java_HotSpot(TM)_64-Bit_Server_VM/25.45-b02/1.8.0_45 AmazonSQSBufferedAsyncClient/1.9.3, )
有人知道我遗漏了什么或至少有任何提示如何进一步调试吗?
编辑: 在浏览了一些 spring-cloud-aws 代码之后,我有点前进了。与 jar 捆绑在一起的配置文件 application.properties
有一些 accessKey
和 secretKey
的文本值。我的自定义 application.properties
没有这些属性,这可能导致 spring 使用捆绑文件中的值作为默认值。我将它们包含在空值中,这将异常更改为 com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain
。 AWS SDK 似乎配置了 DefaultProviderChain,但它仍然无法获取实例配置文件凭证。
这个问题的解决方案来自两个截然不同的事实。
将仅使用实例配置文件凭据,如果
application.properties
已将instanceProfile
属性 设置为 仅true
和accessKey
设置为null
(ContextCredentialsAutoConfiguration).即使您将提供自定义
application.properties
文件,Spring 也会读取与应用程序 jar 捆绑在一起的application.properties
文件(如果它确实存在)。如果是这样的话,两个文件的属性将加起来创建一个执行环境。我怀疑首先解析捆绑文件,然后再解析自定义文件,覆盖捆绑文件中存在的任何 属性。
在我的例子中,捆绑的 application.properties
有 accessKey 和 secretKey 占位符(带有假值),只要开发人员想要在 EC2 环境之外进行一些测试,就会填写这些占位符。这使得 accessKey 不为空,因此排除了实例配置文件路径。我刚刚从 jar 中删除了 application.properties 文件并解决了问题。
cloud:
aws:
credentials:
accessKey:
secretKey:
instanceProfile: true
useDefaultAwsCredentialsChain: true
如果您使用的是最新的 (2.X.X) Spring AWS 云,这就可以了。