From 3b461ffcb3d2848c5b266740c5dc1fd898740646 Mon Sep 17 00:00:00 2001 From: Luke Hoban Date: Mon, 11 Dec 2017 15:40:39 -0800 Subject: [PATCH] Use AWS access key in operations prvider when available (#697) If the stack config specifies AWS credentials, these should be used in the operations provider instead of ambient credentials. This is necessary to ensure that we have access to resources in the target account. Fixes pulumi/pulumi-service#389 --- pkg/operations/operations_aws.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/pkg/operations/operations_aws.go b/pkg/operations/operations_aws.go index e41ab0048..db06c6e30 100644 --- a/pkg/operations/operations_aws.go +++ b/pkg/operations/operations_aws.go @@ -9,6 +9,7 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/golang/glog" @@ -31,7 +32,17 @@ func AWSOperationsProvider( return nil, errors.New("no AWS region found") } - awsConnection, err := getAWSConnection(awsRegion) + // If provided, also pass along the access and secret keys so that we have permission to access operational data on + // resources in the target account. + // + // [pulumi/pulumi#608]: We are only approximating the actual logic that the AWS provider (via + // terraform-provdider-aws) uses to turn config into a valid AWS connection. We should find some way to unify these + // as part of moving this code into a separate process on the other side of an RPC boundary. + awsAccessKey := config[accessKey] + awsSecretKey := config[secretKey] + awsToken := config[token] + + awsConnection, err := getAWSConnection(awsRegion, awsAccessKey, awsSecretKey, awsToken) if err != nil { return nil, err } @@ -53,6 +64,9 @@ var _ Provider = (*awsOpsProvider)(nil) const ( // AWS config keys regionKey = "aws:config:region" + accessKey = "aws:config:accessKey" + secretKey = "aws:config:secretKey" // nolint: gas + token = "aws:config:token" // AWS resource types awsFunctionType = tokens.Type("aws:lambda/function:Function") @@ -100,13 +114,19 @@ type awsConnection struct { var awsConnectionCache = map[string]*awsConnection{} var awsConnectionCacheMutex = sync.RWMutex{} -func getAWSConnection(awsRegion string) (*awsConnection, error) { +func getAWSConnection(awsRegion, awsAccessKey, awsSecretKey, token string) (*awsConnection, error) { awsConnectionCacheMutex.RLock() connection, ok := awsConnectionCache[awsRegion] awsConnectionCacheMutex.RUnlock() if !ok { awsConfig := aws.NewConfig() awsConfig.Region = aws.String(awsRegion) + if awsAccessKey != "" || awsSecretKey != "" { + awsConfig.Credentials = credentials.NewStaticCredentials(awsAccessKey, awsSecretKey, token) + glog.V(5).Infof("Using credentials from stack config for AWS operations provider.") + } else { + glog.V(5).Infof("Using ambient credentials for AWS operations provider.") + } sess, err := session.NewSession(awsConfig) if err != nil { return nil, errors.Wrap(err, "failed to create AWS session")