You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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,同样返回访问被拒绝

问题根因

临时凭证获取逻辑存在本质错误:

  1. 调用了AssumeRoleAsync但完全没有使用它返回的结果
  2. 后续调用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 23:21:34