Spring Boot(AWS SDK v1)迁移至EKS后S3 403:如何使用SA角色凭证?
问题
将Spring Boot应用从EC2迁移至EKS,已在AWS中配置好角色及策略并绑定到Pod的ServiceAccount。应用需向S3上传对象并生成预签名URL,使用AWS SDK v1,依赖配置如下:
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.12.273</version> </dependency>
当前S3Client初始化代码:
AmazonS3ClientBuilder.standard() .withRegion(awsRegion) .enablePathStyleAccess() .enablePayloadSigning() .withCredentials(new InstanceProfileCredentialsProvider(true)) .build();
EC2部署时可正常与S3交互,但EKS部署后出现S3 403禁止访问错误,日志如下:
S3 failed with an error. No link will be generated. com.amazonaws.services.s3.model.AmazonS3Exception: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request ID: xxxxxxxx; S3 Extended Request ID: xxxxxxxxxxxxxxxx; Proxy: null) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1879) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1418) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1387) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1157) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:814) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715) at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697) at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561) at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:541) at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5456) at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5403) at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1372) at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1346) at com.amazonaws.services.s3.AmazonS3Client.doesObjectExist(AmazonS3Client.java:1427)
AWS控制台显示该角色未被使用,推测应用无法获取角色凭证导致403问题。需解答:
- 在EKS Pod中,需要使用哪种凭证提供者来获取ServiceAccount关联的角色凭证?
- 不升级至新版SDK v2是否可行?
- 升级至SDK v2后是否仍存在相同问题?
解决方案
1. EKS Pod中SDK v1的凭证提供者修改
当前使用的InstanceProfileCredentialsProvider仅适配EC2实例元数据服务,无法读取EKS Pod通过IRSA(IAM Roles for Service Accounts)提供的Web身份凭证。需替换为**DefaultAWSCredentialsProviderChain**,它会按优先级自动尝试多种凭证获取方式,包括EKS Pod中的Web身份凭证:
AmazonS3ClientBuilder.standard() .withRegion(awsRegion) .enablePathStyleAccess() .enablePayloadSigning() .withCredentials(DefaultAWSCredentialsProviderChain.getInstance()) .build();
也可直接指定WebIdentityTokenCredentialsProvider手动配置凭证路径,但默认链已能自动处理,推荐使用默认链。
2. 不升级SDK v2完全可行
你使用的1.12.273版本AWS SDK v1已完全支持IRSA,早在v1.11.700版本就加入了Web身份凭证支持,无需升级SDK v2即可解决问题。
3. 升级至SDK v2后不会存在相同问题
升级到AWS SDK v2后,默认凭证提供者链同样会自动识别EKS Pod中的IRSA凭证,初始化代码更简洁:
S3Client s3Client = S3Client.builder() .region(Region.of(awsRegion)) .serviceConfiguration(config -> config.pathStyleAccessEnabled(true)) .credentialsProvider(DefaultCredentialsProvider.create()) .build();
只要ServiceAccount与角色的绑定配置正确,SDK v2会自动获取凭证,不会出现类似403问题,且SDK v2在性能、API设计上更具优势。
内容的提问来源于stack exchange,提问作者KJ0797

