使用临时角色凭证时无法从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
相关产品推荐
相关产品推荐

