使用Cognito凭证通过.NET SDK访问AWS S3遇STS报错求助
问题
我希望通过Cognito用户将S3存储桶中的文件下载到Windows机器。已完成以下配置:
- 创建用户池、演示用户,启用授权码流的应用客户端;
- 创建拥有S3全权限的角色,分配给组并将演示用户加入该组。
在.NET 8应用中,已通过浏览器跳转Cognito登录页获取OAuth 2.0令牌,现需通过STS的AmazonSecurityTokenServiceClient调用AssumeRoleWithWebIdentity接口获取AWS凭证以访问S3,但报错:
"Unable to get IAM security credentials from EC2 Instance Metadata Service"
请问:
- EC2服务为何涉及其中?
AmazonSecurityTokenServiceClient存在什么问题?- 如何通过Cognito凭证访问S3?
相关代码:
// Get AWS credentials using the identity pool AmazonSecurityTokenServiceClient securityTokenServiceClient = new AmazonSecurityTokenServiceClient(RegionEndpoint.EUNorth1); AssumeRoleWithWebIdentityResponse roleResponse = await securityTokenServiceClient.AssumeRoleWithWebIdentityAsync(new AssumeRoleWithWebIdentityRequest() { WebIdentityToken = tokenResponse?.IdToken, RoleArn = "arn:aws:iam::1234:role/cognito-demo-bucket", RoleSessionName = "demo" }); _logger.LogTrace("Access key: {awsCredentials}\nSecret access key: {secretAccessKey}", roleResponse.Credentials.AccessKeyId, roleResponse.Credentials.SecretAccessKey);
回答
1. EC2服务为何涉及其中?
当无参实例化AmazonSecurityTokenServiceClient时,AWS SDK会按默认凭证链查找可用凭证:环境变量 > 共享凭证文件 > EC2实例元数据服务(IMDS)。你的Windows机器不在EC2上,SDK找不到前两类有效凭证,就会尝试访问IMDS,从而抛出这个和EC2相关的错误。
2. AmazonSecurityTokenServiceClient存在什么问题?
问题出在实例化方式上:无参构造会触发默认凭证链查找,但当前场景不需要依赖链中的任何凭证(要通过Web Identity Token获取临时凭证),SDK找不到有效凭证就报错。本质是你没有明确告知SDK“不需要预先提供凭证,直接调用STS接口”。
3. 如何通过Cognito凭证访问S3?
有两种可行方案:
方案一:修正STS客户端的实例化方式
使用AnonymousAWSCredentials实例化STS客户端,明确告知SDK不需要预先的凭证,直接调用接口:
// 使用匿名凭证初始化STS客户端 var stsClient = new AmazonSecurityTokenServiceClient(new AnonymousAWSCredentials(), RegionEndpoint.EUNorth1); var roleResponse = await stsClient.AssumeRoleWithWebIdentityAsync(new AssumeRoleWithWebIdentityRequest { WebIdentityToken = tokenResponse.IdToken, RoleArn = "arn:aws:iam::1234:role/cognito-demo-bucket", RoleSessionName = "demo" }); // 使用获取到的临时凭证创建S3客户端 var s3Client = new AmazonS3Client( roleResponse.Credentials.AccessKeyId, roleResponse.Credentials.SecretAccessKey, roleResponse.Credentials.SessionToken, RegionEndpoint.EUNorth1); // 示例:下载S3文件 await s3Client.DownloadToFilePathAsync("your-bucket-name", "object-key", @"C:\local-path\file.ext");
方案二:直接使用WebIdentityCredentials简化流程
AWS SDK提供了WebIdentityCredentials类,可以自动处理STS的AssumeRoleWithWebIdentity调用,无需手动操作STS客户端:
// 使用WebIdentityCredentials直接创建S3客户端 var s3Client = new AmazonS3Client(new WebIdentityCredentials( tokenResponse.IdToken, "arn:aws:iam::1234:role/cognito-demo-bucket", "demo"), RegionEndpoint.EUNorth1); // 示例:下载S3文件 await s3Client.DownloadToFilePathAsync("your-bucket-name", "object-key", @"C:\local-path\file.ext");
内容的提问来源于stack exchange,提问作者LouBen3010

