.Net SDK调用AWS Assume Role访问S3报Access Denied,CLI正常
问题描述
尝试通过AWS Assume Role机制向S3存储桶上传文件时,AWS CLI操作完全正常,但使用.Net SDK调用始终返回Access Denied(访问被拒绝)错误。
CLI侧正常操作流程
- 执行
aws configure配置对应用户的Access Key/Secret Key - 执行角色代入命令:
aws sts assume-role --role-arn "arn:aws:iam::1010101010:role/Test-Account-Role" --role-session-name AWSCLI-Session - 提取返回结果中的Access Key / Secret Key / Session Token,配置为新的AWS Profile
- 执行
set AWS_PROFILE=<对应配置名>切换到Assume Role生成的Profile - 执行
aws sts get-caller-identity验证当前身份已切换为目标角色 - 使用
ls/cp/rm等S3命令访问目标存储桶,所有操作均执行成功
.Net Core侧实现代码
使用和CLI完全一致的根用户Access Key/Secret Key,核心上传逻辑如下:
try { var region = RegionEndpoint.GetBySystemName(awsRegion); SessionAWSCredentials tempCredentials = await GetTemporaryCredentialsAsync(awsAccessKey, awsSecretKey, region, roleARN); // 使用临时凭证创建S3客户端 IAmazonS3 client = new AmazonS3Client(tempCredentials, region); TransferUtility utility = new TransferUtility(client); // 构造上传请求 TransferUtilityUploadRequest request = new TransferUtilityUploadRequest { BucketName = bucketName, Key = $"{subFolder}/{fileName}", FilePath = localFilePath }; utility.Upload(request); // 执行上传 fileUploadedSuccessfully = true; } catch (AmazonS3Exception ex) { // 异常处理 } catch (Exception ex) { // 异常处理 }
获取临时凭证的GetTemporaryCredentialsAsync方法实现:
private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync(string awsAccessKey, string awsSecretKey, RegionEndpoint region, string roleARN) { using (var stsClient = new AmazonSecurityTokenServiceClient(awsAccessKey, awsSecretKey, region)) { var getSessionTokenRequest = new GetSessionTokenRequest { DurationSeconds = 7200 }; await stsClient.AssumeRoleAsync( new AssumeRoleRequest() { RoleArn = roleARN, RoleSessionName = "mySession" }); GetSessionTokenResponse sessionTokenResponse = await stsClient.GetSessionTokenAsync(getSessionTokenRequest); Credentials credentials = sessionTokenResponse.Credentials; var sessionCredentials = new SessionAWSCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.SessionToken); return sessionCredentials; } }
异常现象
- 代码可以成功获取临时凭证,但执行S3上传时返回访问被拒绝
- SDK生成的Session Token长度比CLI生成的更短
- 将SDK生成的临时凭证手动配置到本地AWS Profile后访问S3,同样返回访问被拒绝
问题根因
临时凭证获取逻辑存在本质错误:
- 调用了
AssumeRoleAsync但完全没有使用它返回的结果 - 后续调用的
GetSessionTokenAsync接口,返回的是长期IAM用户的临时会话凭证,根本不是Assume Role之后的角色凭证——这就是Token长度更短、权限和CLI拿到的角色凭证完全不匹配的直接原因,访问S3自然会被拒绝。
GetSessionToken返回的凭证继承的是初始化STS客户端所用长期密钥对应的用户权限,完全没有代入目标角色,和CLI执行assume-role拿到的角色凭证是两套完全独立的凭证体系。
修复方案
删除GetSessionToken相关的冗余逻辑,直接使用AssumeRoleAsync返回的凭证构造S3客户端即可,修复后的GetTemporaryCredentialsAsync方法如下:
private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync(string awsAccessKey, string awsSecretKey, RegionEndpoint region, string roleARN) { using (var stsClient = new AmazonSecurityTokenServiceClient(awsAccessKey, awsSecretKey, region)) { // 直接调用AssumeRole,使用返回的角色凭证 AssumeRoleResponse assumeRoleResponse = await stsClient.AssumeRoleAsync( new AssumeRoleRequest() { RoleArn = roleARN, RoleSessionName = "mySession", DurationSeconds = 7200 // 角色会话有效期直接在AssumeRole请求中配置 }); Credentials credentials = assumeRoleResponse.Credentials; var sessionCredentials = new SessionAWSCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.SessionToken); return sessionCredentials; } }
修复后拿到的凭证和CLI执行aws sts assume-role返回的完全一致,权限匹配,S3上传即可正常执行。
内容的提问来源于stack exchange,提问作者mahesh_ing
相关产品推荐
相关产品推荐

