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

使用临时角色凭证时无法从EC2实例获取IAM安全凭证求助

问题:EC2实例使用IAM角色访问S3时报错"Unable to get IAM security credentials from EC2 Instance Metadata Service"

问题背景

按照AWS安全最佳实践,我给EC2实例关联了带有AmazonS3FullAccess策略的ec2-test-role角色,避免在实例内硬编码AccessKey和Secret。我复制了AWS提供的.NET示例代码,配置好S3桶ARN和对应区域端点后,编译发布到EC2实例运行,却触发以下错误:

Listing objects stored in a bucket
Unhandled exception. System.AggregateException: One or more errors occurred. (Unable to get IAM security credentials from EC2 Instance Metadata Service.)
 ---> Amazon.Runtime.AmazonServiceException: Unable to get IAM security credentials from EC2 Instance Metadata Service.
   at Amazon.Runtime.DefaultInstanceProfileAWSCredentials.FetchCredentials()
   at Amazon.Runtime.DefaultInstanceProfileAWSCredentials.GetCredentials()
   at Amazon.Runtime.DefaultInstanceProfileAWSCredentials.GetCredentialsAsync()
   at Amazon.Runtime.Internal.CredentialsRetriever.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.ErrorCallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.MetricsHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.DocSamples.S3.TempCredExplicitSessionStartTest.GetTemporaryCredentialsAsync() in C:\Code\TestAwsEC2TemporaryCredentials\TestAwsEC2TemporaryCredentials\Program.cs:line 67
   at Amazon.DocSamples.S3.TempCredExplicitSessionStartTest.ListObjectsAsync() in C:\Code\TestAwsEC2TemporaryCredentials\TestAwsEC2TemporaryCredentials\Program.cs:line 33
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at Amazon.DocSamples.S3.TempCredExplicitSessionStartTest.Main() in C:\Code\TestAwsEC2TemporaryCredentials\TestAwsEC2TemporaryCredentials\Program.cs:line 23

原代码如下:

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;

namespace Amazon.DocSamples.S3
{
    class TempCredExplicitSessionStartTest
    {
        private const string bucketName = "arn:aws:s3:::mys3bucketnamegoeshere";
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.APSoutheast2;
        private static IAmazonS3 s3Client;
        public static void Main()
        {
            ListObjectsAsync().Wait();
        }

        private static async Task ListObjectsAsync()
        {
            try
            {
                Console.WriteLine("Listing objects stored in a bucket");
                SessionAWSCredentials tempCredentials = await GetTemporaryCredentialsAsync();

                using (s3Client = new AmazonS3Client(tempCredentials, bucketRegion))
                {
                    var listObjectRequest = new ListObjectsRequest
                    {
                        BucketName = bucketName
                    };
                    ListObjectsResponse response = await s3Client.ListObjectsAsync(listObjectRequest);
                    List<S3Object> objects = response.S3Objects;
                    Console.WriteLine("Object count = {0}", objects.Count);
                }
            }
            catch (AmazonS3Exception s3Exception)
            {
                Console.WriteLine(s3Exception.Message, s3Exception.InnerException);
            }
            catch (AmazonSecurityTokenServiceException stsException)
            {
                Console.WriteLine(stsException.Message, stsException.InnerException);
            }
        }

        private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync()
        {
            using (var stsClient = new AmazonSecurityTokenServiceClient())
            {
                var getSessionTokenRequest = new GetSessionTokenRequest
                {
                    DurationSeconds = 7200 
                };

                GetSessionTokenResponse sessionTokenResponse =
                              await stsClient.GetSessionTokenAsync(getSessionTokenRequest);

                Credentials credentials = sessionTokenResponse.Credentials;

                var sessionCredentials =
                    new SessionAWSCredentials(credentials.AccessKeyId,
                                              credentials.SecretAccessKey,
                                              credentials.SessionToken);
                return sessionCredentials;
            }
        }
    }
}

问题原因及解决方法

1. 核心问题:冗余的STS调用逻辑

EC2实例关联IAM角色后,AWS会自动通过实例元数据服务提供临时凭证,不需要手动调用STS的GetSessionToken接口生成会话令牌。你当前的代码手动初始化STS客户端并请求令牌,反而会导致SDK在凭证链查找过程中出现冲突,触发元数据服务访问失败的错误。

2. 修正后的代码

直接利用AWS SDK的默认凭证链初始化S3客户端,SDK会自动从EC2实例元数据服务获取角色的临时凭证,同时注意桶名不需要写ARN,只需要纯桶名:

using Amazon.S3;
using Amazon.S3.Model;

namespace Amazon.DocSamples.S3
{
    class TempCredExplicitSessionStartTest
    {
        // 仅需填写纯桶名,无需ARN格式
        private const string bucketName = "mys3bucketnamegoeshere";
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.APSoutheast2;

        public static void Main()
        {
            ListObjectsAsync().Wait();
        }

        private static async Task ListObjectsAsync()
        {
            try
            {
                Console.WriteLine("Listing objects stored in a bucket");
                // 直接使用默认凭证链初始化S3客户端
                using var s3Client = new AmazonS3Client(bucketRegion);
                
                var listObjectRequest = new ListObjectsRequest
                {
                    BucketName = bucketName
                };
                
                ListObjectsResponse response = await s3Client.ListObjectsAsync(listObjectRequest);
                Console.WriteLine("Object count = {0}", response.S3Objects.Count);
            }
            catch (AmazonS3Exception s3Exception)
            {
                Console.WriteLine("S3 Error: {0}", s3Exception.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("General Error: {0}", ex.Message);
            }
        }
    }
}

3. 额外验证步骤

  • 确认EC2实例已正确关联ec2-test-role:在EC2控制台实例详情的「IAM角色」标签下查看,确保角色状态为已附加。
  • 测试元数据服务访问:在EC2实例内执行以下命令,验证能否获取角色凭证:
    # 获取关联的角色名
    curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
    # 获取角色的临时凭证
    curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-test-role
    
  • 检查VPC网络限制:确认实例所在VPC的安全组、网络ACL未禁止访问169.254.169.254(默认允许,除非手动配置了限制)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:17:56