Skip to content

Commit

Permalink
Read all AWS env vars
Browse files Browse the repository at this point in the history
For both programmatic access, and for pre configuration, we must read in all the appropriate env vars.

Fixes #252
  • Loading branch information
lukehoban authored and stack72 committed Feb 12, 2020
1 parent d1b5c8a commit cc5cd84
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 27 deletions.
42 changes: 35 additions & 7 deletions resources.go
Expand Up @@ -18,6 +18,7 @@ import (
"errors"
"fmt"
"math/rand"
"os"
"strings"
"unicode"

Expand Down Expand Up @@ -201,11 +202,17 @@ func boolRef(b bool) *bool {
}

// stringValue gets a string value from a property map if present, else ""
func stringValue(vars resource.PropertyMap, prop resource.PropertyKey) string {
func stringValue(vars resource.PropertyMap, prop resource.PropertyKey, envs []string) string {
val, ok := vars[prop]
if ok && val.IsString() {
return val.StringValue()
}
for _, env := range envs {
val, ok := os.LookupEnv(env)
if ok {
return val
}
}
return ""
}

Expand All @@ -214,14 +221,15 @@ func stringValue(vars resource.PropertyMap, prop resource.PropertyKey) string {
// before passing control to the TF provider to ensure we can report actionable errors.
func preConfigureCallback(vars resource.PropertyMap, c *terraform.ResourceConfig) error {
config := &awsbase.Config{
AccessKey: stringValue(vars, "accessKey"),
SecretKey: stringValue(vars, "secretKey"),
Profile: stringValue(vars, "profile"),
Token: stringValue(vars, "token"),
Region: stringValue(vars, "region"),
AccessKey: stringValue(vars, "accessKey", []string{"AWS_ACCESS_KEY_ID"}),
SecretKey: stringValue(vars, "secretKey", []string{"AWS_SECRET_ACCESS_KEY"}),
Profile: stringValue(vars, "profile", []string{"AWS_PROFILE"}),
Token: stringValue(vars, "token", []string{"AWS_SESSION_TOKEN"}),
Region: stringValue(vars, "region", []string{"AWS_REGION", "AWS_DEFAULT_REGION"}),
}

credsPath, err := homedir.Expand(stringValue(vars, "sharedCredentialsFile"))
sharedCredentialsFile := stringValue(vars, "sharedCredentialsFile", []string{"AWS_SHARED_CREDENTIALS_FILE"})
credsPath, err := homedir.Expand(sharedCredentialsFile)
if err != nil {
return err
}
Expand Down Expand Up @@ -251,6 +259,16 @@ func Provider() tfbridge.ProviderInfo {
Repository: "https://github.com/pulumi/pulumi-aws",
Version: version.Version,
Config: map[string]*tfbridge.SchemaInfo{
"access_key": {
Default: &tfbridge.DefaultInfo{
EnvVars: []string{"AWS_ACCESS_KEY_ID"},
},
},
"secret_key": {
Default: &tfbridge.DefaultInfo{
EnvVars: []string{"AWS_SECRET_ACCESS_KEY"},
},
},
"region": {
Type: awsTypeNoFile("region", "Region"),
Default: &tfbridge.DefaultInfo{
Expand All @@ -262,6 +280,16 @@ func Provider() tfbridge.ProviderInfo {
EnvVars: []string{"AWS_PROFILE"},
},
},
"token": {
Default: &tfbridge.DefaultInfo{
EnvVars: []string{"AWS_SESSION_TOKEN"},
},
},
"shared_credentials_file": {
Default: &tfbridge.DefaultInfo{
EnvVars: []string{"AWS_SHARED_CREDENTIALS_FILE"},
},
},
},
PreConfigureCallback: preConfigureCallback,
Resources: map[string]*tfbridge.ResourceInfo{
Expand Down
8 changes: 4 additions & 4 deletions sdk/dotnet/Config/Config.cs
Expand Up @@ -13,7 +13,7 @@ public static class Config
/// The access key for API operations. You can retrieve this from the 'Security & Credentials' section of
/// the AWS console.
/// </summary>
public static string? AccessKey { get; set; } = __config.Get("accessKey");
public static string? AccessKey { get; set; } = __config.Get("accessKey") ?? Utilities.GetEnv("AWS_ACCESS_KEY_ID");

public static ImmutableArray<string> AllowedAccountIds { get; set; } = __config.GetObject<ImmutableArray<string>>("allowedAccountIds");

Expand Down Expand Up @@ -65,12 +65,12 @@ public static class Config
/// The secret key for API operations. You can retrieve this from the 'Security &amp; Credentials' section of
/// the AWS console.
/// </summary>
public static string? SecretKey { get; set; } = __config.Get("secretKey");
public static string? SecretKey { get; set; } = __config.Get("secretKey") ?? Utilities.GetEnv("AWS_SECRET_ACCESS_KEY");

/// <summary>
/// The path to the shared credentials file. If not set this defaults to ~/.aws/credentials.
/// </summary>
public static string? SharedCredentialsFile { get; set; } = __config.Get("sharedCredentialsFile");
public static string? SharedCredentialsFile { get; set; } = __config.Get("sharedCredentialsFile") ?? Utilities.GetEnv("AWS_SHARED_CREDENTIALS_FILE");

/// <summary>
/// Skip the credentials validation via STS API. Used for AWS API implementations that do not have STS
Expand Down Expand Up @@ -101,7 +101,7 @@ public static class Config
/// <summary>
/// session token. A session token is only required if you are using temporary security credentials.
/// </summary>
public static string? Token { get; set; } = __config.Get("token");
public static string? Token { get; set; } = __config.Get("token") ?? Utilities.GetEnv("AWS_SESSION_TOKEN");

}
namespace ConfigTypes
Expand Down
4 changes: 4 additions & 0 deletions sdk/dotnet/Provider.cs
Expand Up @@ -188,8 +188,12 @@ public InputList<string> IgnoreTags

public ProviderArgs()
{
AccessKey = Utilities.GetEnv("AWS_ACCESS_KEY_ID");
Profile = Utilities.GetEnv("AWS_PROFILE");
Region = Utilities.GetEnv("AWS_REGION", "AWS_DEFAULT_REGION");
SecretKey = Utilities.GetEnv("AWS_SECRET_ACCESS_KEY");
SharedCredentialsFile = Utilities.GetEnv("AWS_SHARED_CREDENTIALS_FILE");
Token = Utilities.GetEnv("AWS_SESSION_TOKEN");
}
}

Expand Down
36 changes: 32 additions & 4 deletions sdk/go/aws/config/config.go
Expand Up @@ -10,7 +10,14 @@ import (

// The access key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
func GetAccessKey(ctx *pulumi.Context) string {
return config.Get(ctx, "aws:accessKey")
v, err := config.Try(ctx, "aws:accessKey")
if err == nil {
return v
}
if dv, ok := getEnvOrDefault("", nil, "AWS_ACCESS_KEY_ID").(string); ok {
return dv
}
return v
}

func GetAllowedAccountIds(ctx *pulumi.Context) string {
Expand Down Expand Up @@ -82,12 +89,26 @@ func GetS3ForcePathStyle(ctx *pulumi.Context) bool {

// The secret key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
func GetSecretKey(ctx *pulumi.Context) string {
return config.Get(ctx, "aws:secretKey")
v, err := config.Try(ctx, "aws:secretKey")
if err == nil {
return v
}
if dv, ok := getEnvOrDefault("", nil, "AWS_SECRET_ACCESS_KEY").(string); ok {
return dv
}
return v
}

// The path to the shared credentials file. If not set this defaults to ~/.aws/credentials.
func GetSharedCredentialsFile(ctx *pulumi.Context) string {
return config.Get(ctx, "aws:sharedCredentialsFile")
v, err := config.Try(ctx, "aws:sharedCredentialsFile")
if err == nil {
return v
}
if dv, ok := getEnvOrDefault("", nil, "AWS_SHARED_CREDENTIALS_FILE").(string); ok {
return dv
}
return v
}

// Skip the credentials validation via STS API. Used for AWS API implementations that do not have STS
Expand Down Expand Up @@ -118,5 +139,12 @@ func GetSkipRequestingAccountId(ctx *pulumi.Context) bool {

// session token. A session token is only required if you are using temporary security credentials.
func GetToken(ctx *pulumi.Context) string {
return config.Get(ctx, "aws:token")
v, err := config.Try(ctx, "aws:token")
if err == nil {
return v
}
if dv, ok := getEnvOrDefault("", nil, "AWS_SESSION_TOKEN").(string); ok {
return dv
}
return v
}
8 changes: 4 additions & 4 deletions sdk/nodejs/config/vars.ts
Expand Up @@ -11,7 +11,7 @@ let __config = new pulumi.Config("aws");
/**
* The access key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
*/
export let accessKey: string | undefined = __config.get("accessKey");
export let accessKey: string | undefined = __config.get("accessKey") || utilities.getEnv("AWS_ACCESS_KEY_ID");
export let allowedAccountIds: string[] | undefined = __config.getObject<string[]>("allowedAccountIds");
export let assumeRole: { externalId?: string, policy?: string, roleArn?: string, sessionName?: string } | undefined = __config.getObject<{ externalId?: string, policy?: string, roleArn?: string, sessionName?: string }>("assumeRole");
export let endpoints: { accessanalyzer?: string, acm?: string, acmpca?: string, amplify?: string, apigateway?: string, applicationautoscaling?: string, applicationinsights?: string, appmesh?: string, appstream?: string, appsync?: string, athena?: string, autoscaling?: string, autoscalingplans?: string, backup?: string, batch?: string, budgets?: string, cloud9?: string, cloudformation?: string, cloudfront?: string, cloudhsm?: string, cloudsearch?: string, cloudtrail?: string, cloudwatch?: string, cloudwatchevents?: string, cloudwatchlogs?: string, codebuild?: string, codecommit?: string, codedeploy?: string, codepipeline?: string, cognitoidentity?: string, cognitoidp?: string, configservice?: string, cur?: string, dataexchange?: string, datapipeline?: string, datasync?: string, dax?: string, devicefarm?: string, directconnect?: string, dlm?: string, dms?: string, docdb?: string, ds?: string, dynamodb?: string, ec2?: string, ecr?: string, ecs?: string, efs?: string, eks?: string, elasticache?: string, elasticbeanstalk?: string, elastictranscoder?: string, elb?: string, emr?: string, es?: string, firehose?: string, fms?: string, forecast?: string, fsx?: string, gamelift?: string, glacier?: string, globalaccelerator?: string, glue?: string, greengrass?: string, guardduty?: string, iam?: string, imagebuilder?: string, inspector?: string, iot?: string, iotanalytics?: string, iotevents?: string, kafka?: string, kinesis?: string, kinesisAnalytics?: string, kinesisanalytics?: string, kinesisvideo?: string, kms?: string, lakeformation?: string, lambda?: string, lexmodels?: string, licensemanager?: string, lightsail?: string, macie?: string, managedblockchain?: string, marketplacecatalog?: string, mediaconnect?: string, mediaconvert?: string, medialive?: string, mediapackage?: string, mediastore?: string, mediastoredata?: string, mq?: string, neptune?: string, opsworks?: string, organizations?: string, personalize?: string, pinpoint?: string, pricing?: string, qldb?: string, quicksight?: string, r53?: string, ram?: string, rds?: string, redshift?: string, resourcegroups?: string, route53?: string, route53resolver?: string, s3?: string, s3control?: string, sagemaker?: string, sdb?: string, secretsmanager?: string, securityhub?: string, serverlessrepo?: string, servicecatalog?: string, servicediscovery?: string, servicequotas?: string, ses?: string, shield?: string, sns?: string, sqs?: string, ssm?: string, stepfunctions?: string, storagegateway?: string, sts?: string, swf?: string, transfer?: string, waf?: string, wafregional?: string, wafv2?: string, worklink?: string, workspaces?: string, xray?: string }[] | undefined = __config.getObject<{ accessanalyzer?: string, acm?: string, acmpca?: string, amplify?: string, apigateway?: string, applicationautoscaling?: string, applicationinsights?: string, appmesh?: string, appstream?: string, appsync?: string, athena?: string, autoscaling?: string, autoscalingplans?: string, backup?: string, batch?: string, budgets?: string, cloud9?: string, cloudformation?: string, cloudfront?: string, cloudhsm?: string, cloudsearch?: string, cloudtrail?: string, cloudwatch?: string, cloudwatchevents?: string, cloudwatchlogs?: string, codebuild?: string, codecommit?: string, codedeploy?: string, codepipeline?: string, cognitoidentity?: string, cognitoidp?: string, configservice?: string, cur?: string, dataexchange?: string, datapipeline?: string, datasync?: string, dax?: string, devicefarm?: string, directconnect?: string, dlm?: string, dms?: string, docdb?: string, ds?: string, dynamodb?: string, ec2?: string, ecr?: string, ecs?: string, efs?: string, eks?: string, elasticache?: string, elasticbeanstalk?: string, elastictranscoder?: string, elb?: string, emr?: string, es?: string, firehose?: string, fms?: string, forecast?: string, fsx?: string, gamelift?: string, glacier?: string, globalaccelerator?: string, glue?: string, greengrass?: string, guardduty?: string, iam?: string, imagebuilder?: string, inspector?: string, iot?: string, iotanalytics?: string, iotevents?: string, kafka?: string, kinesis?: string, kinesisAnalytics?: string, kinesisanalytics?: string, kinesisvideo?: string, kms?: string, lakeformation?: string, lambda?: string, lexmodels?: string, licensemanager?: string, lightsail?: string, macie?: string, managedblockchain?: string, marketplacecatalog?: string, mediaconnect?: string, mediaconvert?: string, medialive?: string, mediapackage?: string, mediastore?: string, mediastoredata?: string, mq?: string, neptune?: string, opsworks?: string, organizations?: string, personalize?: string, pinpoint?: string, pricing?: string, qldb?: string, quicksight?: string, r53?: string, ram?: string, rds?: string, redshift?: string, resourcegroups?: string, route53?: string, route53resolver?: string, s3?: string, s3control?: string, sagemaker?: string, sdb?: string, secretsmanager?: string, securityhub?: string, serverlessrepo?: string, servicecatalog?: string, servicediscovery?: string, servicequotas?: string, ses?: string, shield?: string, sns?: string, sqs?: string, ssm?: string, stepfunctions?: string, storagegateway?: string, sts?: string, swf?: string, transfer?: string, waf?: string, wafregional?: string, wafv2?: string, worklink?: string, workspaces?: string, xray?: string }[]>("endpoints");
Expand Down Expand Up @@ -49,11 +49,11 @@ export let s3ForcePathStyle: boolean | undefined = __config.getObject<boolean>("
/**
* The secret key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
*/
export let secretKey: string | undefined = __config.get("secretKey");
export let secretKey: string | undefined = __config.get("secretKey") || utilities.getEnv("AWS_SECRET_ACCESS_KEY");
/**
* The path to the shared credentials file. If not set this defaults to ~/.aws/credentials.
*/
export let sharedCredentialsFile: string | undefined = __config.get("sharedCredentialsFile");
export let sharedCredentialsFile: string | undefined = __config.get("sharedCredentialsFile") || utilities.getEnv("AWS_SHARED_CREDENTIALS_FILE");
/**
* Skip the credentials validation via STS API. Used for AWS API implementations that do not have STS
* available/implemented.
Expand All @@ -76,4 +76,4 @@ export let skipRequestingAccountId: boolean | undefined = __config.getObject<boo
/**
* session token. A session token is only required if you are using temporary security credentials.
*/
export let token: string | undefined = __config.get("token");
export let token: string | undefined = __config.get("token") || utilities.getEnv("AWS_SESSION_TOKEN");
8 changes: 4 additions & 4 deletions sdk/nodejs/provider.ts
Expand Up @@ -42,7 +42,7 @@ export class Provider extends pulumi.ProviderResource {
constructor(name: string, args?: ProviderArgs, opts?: pulumi.ResourceOptions) {
let inputs: pulumi.Inputs = {};
{
inputs["accessKey"] = args ? args.accessKey : undefined;
inputs["accessKey"] = (args ? args.accessKey : undefined) || utilities.getEnv("AWS_ACCESS_KEY_ID");
inputs["allowedAccountIds"] = pulumi.output(args ? args.allowedAccountIds : undefined).apply(JSON.stringify);
inputs["assumeRole"] = pulumi.output(args ? args.assumeRole : undefined).apply(JSON.stringify);
inputs["endpoints"] = pulumi.output(args ? args.endpoints : undefined).apply(JSON.stringify);
Expand All @@ -54,14 +54,14 @@ export class Provider extends pulumi.ProviderResource {
inputs["profile"] = (args ? args.profile : undefined) || utilities.getEnv("AWS_PROFILE");
inputs["region"] = (args ? args.region : undefined) || utilities.getEnv("AWS_REGION", "AWS_DEFAULT_REGION");
inputs["s3ForcePathStyle"] = pulumi.output(args ? args.s3ForcePathStyle : undefined).apply(JSON.stringify);
inputs["secretKey"] = args ? args.secretKey : undefined;
inputs["sharedCredentialsFile"] = args ? args.sharedCredentialsFile : undefined;
inputs["secretKey"] = (args ? args.secretKey : undefined) || utilities.getEnv("AWS_SECRET_ACCESS_KEY");
inputs["sharedCredentialsFile"] = (args ? args.sharedCredentialsFile : undefined) || utilities.getEnv("AWS_SHARED_CREDENTIALS_FILE");
inputs["skipCredentialsValidation"] = pulumi.output(args ? args.skipCredentialsValidation : undefined).apply(JSON.stringify);
inputs["skipGetEc2Platforms"] = pulumi.output(args ? args.skipGetEc2Platforms : undefined).apply(JSON.stringify);
inputs["skipMetadataApiCheck"] = pulumi.output(args ? args.skipMetadataApiCheck : undefined).apply(JSON.stringify);
inputs["skipRegionValidation"] = pulumi.output(args ? args.skipRegionValidation : undefined).apply(JSON.stringify);
inputs["skipRequestingAccountId"] = pulumi.output(args ? args.skipRequestingAccountId : undefined).apply(JSON.stringify);
inputs["token"] = args ? args.token : undefined;
inputs["token"] = (args ? args.token : undefined) || utilities.getEnv("AWS_SESSION_TOKEN");
}
if (!opts) {
opts = {}
Expand Down
8 changes: 4 additions & 4 deletions sdk/python/pulumi_aws/config/vars.py
Expand Up @@ -11,7 +11,7 @@

__config__ = pulumi.Config('aws')

access_key = __config__.get('accessKey')
access_key = __config__.get('accessKey') or utilities.get_env('AWS_ACCESS_KEY_ID')
"""
The access key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
"""
Expand Down Expand Up @@ -61,12 +61,12 @@
Specific to the Amazon S3 service.
"""

secret_key = __config__.get('secretKey')
secret_key = __config__.get('secretKey') or utilities.get_env('AWS_SECRET_ACCESS_KEY')
"""
The secret key for API operations. You can retrieve this from the 'Security & Credentials' section of the AWS console.
"""

shared_credentials_file = __config__.get('sharedCredentialsFile')
shared_credentials_file = __config__.get('sharedCredentialsFile') or utilities.get_env('AWS_SHARED_CREDENTIALS_FILE')
"""
The path to the shared credentials file. If not set this defaults to ~/.aws/credentials.
"""
Expand Down Expand Up @@ -95,7 +95,7 @@
Skip requesting the account ID. Used for AWS API implementations that do not have IAM/STS API and/or metadata API.
"""

token = __config__.get('token')
token = __config__.get('token') or utilities.get_env('AWS_SESSION_TOKEN')
"""
session token. A session token is only required if you are using temporary security credentials.
"""
Expand Down

0 comments on commit cc5cd84

Please sign in to comment.