Spring Cloud AWS 3.0.1与SCS Kinesis Binder 4.0.0中StsWebIdentityTokenFileCredentialsProvider自动配置失效
查阅Spring Cloud AWS 3.0.0官方文档后,我认为只需添加software.amazon.awssdk:sts依赖,Spring就会自动配置StsWebIdentityTokenFileCredentialsProvider,但通过KPL向Kinesis写入消息时始终报错,错误日志如下:
2023-08-07 | 10:34:20.256 | kpl-daemon-0003 | WARN | c.a.s.k.producer.LogInputStreamReader | Trace: | Span: | [2023-08-07 14:34:20.256507] [0x00000071][0x00007f379cdfa6c0] [warning] [AWS Log: ERROR](AWSXmlClient)HTTP response code: 403 Resolved remote host IP address: xx.xxx.xxx.xxx Request ID: xxxxxxxxxxxxxxx Exception name: InvalidClientTokenId Error message: The security token included in the request is invalid. 4 response headers: content-length : 306 content-type : text/xml date : Mon, 07 Aug 2023 14:34:19 GMT x-amzn-requestid : xxxxxxxxxxxxxxxxxxxx 2023-08-07 | 10:34:20.256 | kpl-daemon-0003 | ERROR | c.a.s.k.producer.LogInputStreamReader | Trace: | Span: | [2023-08-07 14:34:20.256566] [0x00000071][0x00007f379cdfa6c0] [error] [pipeline.h:228] Failed to get StreamARN using STS GetCallerIdentity | Code: InvalidClientTokenId | Message: The security token included in the request is invalid. | Request was: Action=GetCallerIdentity&Version=2011-06-15 2023-08-07 | 10:34:20.256 | kpl-daemon-0003 | WARN | c.a.s.k.producer.LogInputStreamReader | Trace: | Span: | terminate called after throwing an instance of 'boost::wrapexcept<boost::exception_detail::error_info_injector<boost::log::v2s_mt_posix::system_error> >' 2023-08-07 | 10:34:20.257 | kpl-daemon-0003 | WARN | c.a.s.k.producer.LogInputStreamReader | Trace: | Span: | what(): Failed to set TLS value: Invalid argument 2023-08-07 | 10:34:21.276 | kpl-daemon-0005 | ERROR | c.a.s.kinesis.producer.KinesisProducer | Trace: | Span: | Error in child process java.lang.RuntimeException: EOF reached during read at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:532) at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:508) at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:504) at com.amazonaws.services.kinesis.producer.Daemon.readSome(Daemon.java:553) at com.amazonaws.services.kinesis.producer.Daemon.receiveMessage(Daemon.java:243) at com.amazonaws.services.kinesis.producer.Daemon.access$500(Daemon.java:61) at com.amazonaws.services.kinesis.producer.Daemon$3.run(Daemon.java:298) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) 2023-08-07 | 10:34:21.285 | -pool-1-thread-0 | ERROR | o.s.integration.handler.LoggingHandler | Trace: | Span: | org.springframework.integration.aws.support.AwsRequestFailureException, failedMessage=GenericMessage [payload=byte[27], headers={...omitted for security purposes... at org.springframework.integration.aws.outbound.AbstractAwsMessageHandler.handleResponse(AbstractAwsMessageHandler.java:148) at org.springframework.integration.aws.outbound.AbstractAwsMessageHandler.lambda$handleMessageInternal$0(AbstractAwsMessageHandler.java:117) at java.base/java.util.concurrent.CompletableFuture.uniHandle(Unknown Source) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.postComplete(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(Unknown Source) at org.springframework.integration.aws.outbound.KplMessageHandler$2.onFailure(KplMessageHandler.java:488) at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1124) at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:31) at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1270) at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1038) at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:808) at com.google.common.util.concurrent.SettableFuture.setException(SettableFuture.java:55) at com.amazonaws.services.kinesis.producer.KinesisProducer$MessageHandler$2.run(KinesisProducer.java:200) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Caused by: java.util.concurrent.CompletionException: java.lang.RuntimeException: EOF reached during read at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(Unknown Source) at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(Unknown Source) ... 13 more Caused by: java.lang.RuntimeException: EOF reached during read at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:532) at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:508) at com.amazonaws.services.kinesis.producer.Daemon.fatalError(Daemon.java:504) at com.amazonaws.services.kinesis.producer.Daemon.readSome(Daemon.java:553) at com.amazonaws.services.kinesis.producer.Daemon.receiveMessage(Daemon.java:243) at com.amazonaws.services.kinesis.producer.Daemon.access$500(Daemon.java:61) at com.amazonaws.services.kinesis.producer.Daemon$3.run(Daemon.java:298) ... 3 more
我们已在EKS中配置了服务账号,并且通过kubectl exec进入容器确认AWS_ROLE_ARN和AWS_WEB_IDENTITY_TOKEN_FILE环境变量已正确映射,但看起来StsWebIdentityTokenFileCredentialsProvider并未被自动配置,而是使用了其他凭证提供者。请问还需要哪些配置才能确保该Bean被正确自动配置?
1. 完善依赖配置
除了sts依赖,必须引入Spring Cloud AWS的核心启动依赖,确保自动配置机制生效:
Maven示例
<dependency> <groupId>io.awspring.cloud</groupId> <artifactId>spring-cloud-aws-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sts</artifactId> </dependency>
Gradle示例
implementation 'io.awspring.cloud:spring-cloud-aws-starter:3.0.0' implementation 'software.amazon.awssdk:sts'
2. 显式指定凭证提供者优先级
Spring Cloud AWS默认会按顺序遍历凭证源,可能优先选择了其他凭证(如环境变量中的access key/secret)。通过配置强制指定使用Web Identity凭证:
application.yml
spring: cloud: aws: credentials: provider: web-identity
application.properties
spring.cloud.aws.credentials.provider=web-identity
3. 确保KPL使用Spring管理的凭证
KPL是JNI组件,默认可能不会自动关联Spring的凭证提供者。需要显式将Spring配置的AwsCredentialsProvider注入到KPL配置中:
@Bean public KinesisProducer kinesisProducer(AwsCredentialsProvider credentialsProvider) { KinesisProducerConfiguration config = new KinesisProducerConfiguration(); // 注入Spring管理的凭证提供者 config.setCredentialsProvider(credentialsProvider); // 补充其他KPL配置(如区域、流名称等) config.setRegion("your-aws-region"); config.setStreamName("your-kinesis-stream"); return new KinesisProducer(config); }
如果使用Spring Integration的KplMessageHandler,确保它依赖的是上述Spring管理的KinesisProducer实例。
4. 验证自动配置结果
添加一个组件打印当前使用的凭证提供者,确认是否正确加载:
@Component public class CredentialsValidator { public CredentialsValidator(AwsCredentialsProvider credentialsProvider) { System.out.println("当前生效的凭证提供者:" + credentialsProvider.getClass().getName()); } }
启动应用后,若控制台输出software.amazon.awssdk.auth.credentials.StsWebIdentityTokenFileCredentialsProvider,说明自动配置成功。
5. 检查权限与文件可访问性
- 确认
AWS_WEB_IDENTITY_TOKEN_FILE指向的文件拥有容器进程可读的权限; - 确认
AWS_ROLE_ARN对应的IAM角色具备:- Kinesis流的写入权限;
- STS服务的
AssumeRoleWithWebIdentity权限。
内容的提问来源于stack exchange,提问作者Keith Bennett

