使用 AWS 开发工具包 Go 从 Fargate 任务中的角色加载 AWS 凭证的正确方法是什么?



我有以下代码片段:

awsCredentials := credentials.NewChainCredentials(
[]credentials.Provider{
&ec2rolecreds.EC2RoleProvider{
Client: ec2metadata.New(newSession, aws.NewConfig()),
},
&credentials.SharedCredentialsProvider{},
&credentials.EnvProvider{},
})

每当代码在 EC2 实例上运行或通过变量(用于本地测试)传递时,它都可以正常工作。

但是,在 ECS+Fargate 上运行时,此代码失败,因为NoCredentialProviders: no valid providers in chain。检查了正在运行的容器的环境变量,它具有预期的AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,因此credentials.EnvProvider应该读取它。

所以,我的问题是,阅读这些凭据的正确方法是什么?因为我面临的问题不是缺少权限(这将指示策略/角色中的错误),而是该代码无法获取凭据。

更新

我已将其缩小到使用ec2rolescreds.

使用这个简单的例子:

package main
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func main() {
newSession, err := session.NewSession()
if err != nil {
log.Fatal(err)
}
awsCredentials := credentials.NewChainCredentials(
[]credentials.Provider{
&ec2rolecreds.EC2RoleProvider{
Client: ec2metadata.New(newSession, aws.NewConfig()),
},
&credentials.SharedCredentialsProvider{},
&credentials.EnvProvider{},
})
sess, err := session.NewSession(&aws.Config{
Region:      aws.String("us-east-1"),
Credentials: awsCredentials},
)
if err != nil {
log.Fatal(err)
}
// Create S3 service client
svc := s3.New(sess)
result, err := svc.ListBuckets(nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Buckets:")
for _, b := range result.Buckets {
fmt.Printf("* %s created on %sn",
aws.StringValue(b.Name), aws.TimeValue(b.CreationDate))
}
}

如果我删除ec2rolescreds,在本地和 ECS+Fargate 中一切正常。

但是,如果我按原样运行此代码,则会出现相同的错误NoCredentialProviders: no valid providers in chain

解决方案是使用会话而不是凭据初始化客户端,即:

conf := aws.NewConfig().WithRegion("us-east-1")
sess := session.Must(session.NewSession(conf))
svc := s3.New(sess)
// others:
//   svc := sqs.New(sess)
//   svc := dynamodb.New(sess)
//   ... 

因为,正如@Ay0点,默认凭据链已经包括EnvProviderRemoteCredProvider

如果您仍需要凭据,则可以使用:

creds := stscreds.NewCredentials(sess, "myRoleARN")

正如文档指出的那样。请注意,角色的策略必须启用sts:AssumeRole操作。有关更多信息,以下是stscreds.NewCredentials(...)文档

因此,可以使用 Config 对象配置会话。

通读此对象的规格,它说凭据:

// The credentials object to use when signing requests. Defaults to a
// chain of credential providers to search for credentials in environment
// variables, shared credential file, and EC2 Instance Roles.
Credentials *credentials.Credentials

默认值已经是我的代码片段正在做的事情,所以我删除了所有awsCredentials块,现在它在任何地方都可以正常工作。在本地,EC2,Fargate...

更新

为了扩展答案,删除awsCredentials使这项工作工作的原因是,如果您检查SDK的代码,https://github.com/aws/aws-sdk-go/blob/master/aws/defaults/defaults.go#L107,默认凭据会同时检查EnvProviderRemoteCredProvider

通过覆盖默认链凭据,它无法在RemoteCredProvider中查找凭据,这是处理环境变量AWS_CONTAINER_CREDENTIALS_FULL_URI的提供程序。

相关内容

  • 没有找到相关文章

最新更新