Use AWS access key in operations prvider when available
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
@@ -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")
