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

使用Amazon SDK通过access_key/secret_key获取AWS凭证遇权限异常求助

AWS SDK 凭证获取权限异常排查

问题现象

  • 当isUseProfile = true时,通过配置文件调用chain.TryGetAWSCredentials(profile, out awsCredentials)获取凭证,执行ssm:SendCommand操作正常,返回"Success"。
  • 当isUseProfile = false时,通过BasicAWSCredentials(accessKey, secretKey)创建凭证和客户端,执行相同操作抛出权限异常:

Error: User: arn:aws:iam::xxx:user/xxx-xxx-xxx is not authorized to perform: ssm:SendCommand on resource: arn:aws:ec2:region_endpoint:xxxxxx:instance/i-xxxxxxx because no identity-based policy allows the ssm:SendCommand action

已确认配置文件对应的凭证具备ssm:SendCommand权限,怀疑硬编码凭证的逻辑存在遗漏。

测试代码

public static async Task ConnectByAWSRunShellScript(
    string instanceId,
    string databaseHost,
    string databaseUsername,
    string databasePassword,
    string databaseName,
    RegionEndpoint regionEndpoint,
    string accessKey,
    string secretKey)
{
    try
    {
        AWSCredentials awsCredentials;
        AmazonSimpleSystemsManagementClient ssmClient;

        bool isUseProfile = true;
        if (isUseProfile == true)
        {
            var profile = "profile_name";
            var chain = new CredentialProfileStoreChain();
            if (!chain.TryGetAWSCredentials(profile, out awsCredentials))
            {
                Console.WriteLine("Failed to get AWS credentials");
                return;
            }
            ssmClient = new AmazonSimpleSystemsManagementClient(awsCredentials);
        }
        else
        {
            awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
            ssmClient = new AmazonSimpleSystemsManagementClient(awsCredentials);
        }

        var command = $"hostname";
        var sendCommandRequest = new SendCommandRequest
        {
            InstanceIds = new List<string> { instanceId },
            DocumentName = "AWS-RunShellScript",
            Parameters = new Dictionary<string, List<string>>
            {
                { "commands", new List<string> { command } }
            }
        };

        var sendCommandResponse = await ssmClient.SendCommandAsync(sendCommandRequest);
        if (sendCommandResponse != null)
        {
            Console.WriteLine("Success");
        }
        else
        {
            Console.WriteLine("Fail");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

问题分析与解决方案

1. 核对凭证一致性

检查硬编码的accessKey和secretKey是否与配置文件中profile_name对应的凭证完全一致。配置文件(通常在~/.aws/credentials或C:\Users\<User>\.aws\credentials)格式如下:

[profile_name]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

如果两者不一致,会导致使用不同IAM用户,自然触发权限问题。

2. 显式指定区域参数

配置文件的config文件(~/.aws/config或对应Windows路径)可能为profile绑定了区域,而CredentialProfileStoreChain会自动加载该区域。但直接用BasicAWSCredentials创建客户端时,若未显式传入regionEndpoint,SDK会使用默认区域,若默认区域与目标实例区域不匹配,会导致请求发送到错误区域,进而触发权限异常。

修改第二种分支的客户端创建代码:

ssmClient = new AmazonSimpleSystemsManagementClient(awsCredentials, regionEndpoint);

3. 检查profile是否为角色配置

如果配置文件中的profile_name是角色而非IAM用户(比如通过STS角色假设),CredentialProfileStoreChain会自动调用STS获取临时凭证,此时临时凭证的权限来自角色而非原用户。若硬编码的是原用户的凭证,该用户可能仅具备角色假设权限,没有直接执行ssm:SendCommand的权限。

这种情况需改用STS假设角色的方式获取临时凭证:

var roleArn = "arn:aws:iam::xxx:role/your-role-name";
var stsClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey);
var assumeRoleRequest = new AssumeRoleRequest
{
    RoleArn = roleArn,
    RoleSessionName = "test-session"
};
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
var tempCredentials = new SessionAWSCredentials(
    assumeRoleResponse.Credentials.AccessKeyId,
    assumeRoleResponse.Credentials.SecretAccessKey,
    assumeRoleResponse.Credentials.SessionToken);
ssmClient = new AmazonSimpleSystemsManagementClient(tempCredentials, regionEndpoint);

4. 验证IAM策略资源范围

检查硬编码凭证对应的IAM用户策略,确认ssm:SendCommand的资源是否包含目标实例的ARN,或使用通配符*。异常信息明确提示资源不匹配,若配置文件用的角色有更宽松的资源权限,而硬编码用户的策略资源范围有限,也会出现该问题。

快速验证步骤

在两种分支中添加代码,打印凭证对应的IAM身份ARN,确认是否为同一身份:

// 配置文件分支
var profileCreds = await awsCredentials.GetCredentialsAsync();
var iamClientProfile = new AmazonIdentityManagementServiceClient(awsCredentials);
var profileUser = await iamClientProfile.GetUserAsync();
Console.WriteLine($"Profile User ARN: {profileUser.User.Arn}");

// 硬编码分支
var iamClientHardcode = new AmazonIdentityManagementServiceClient(awsCredentials, regionEndpoint);
var hardcodeUser = await iamClientHardcode.GetUserAsync();
Console.WriteLine($"Hardcoded User ARN: {hardcodeUser.User.Arn}");

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:35:08