diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ac79918e2f..861041aa8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### Improvements -- Addition of enums for SSM Parameter Types +- Add an enumeration for SSM Parameter Types +- Fixed a bug where `AWS_PROFILE` and the ~/.aws/config files were not honoured. ## 0.18.6 (Released May 24th, 2019) diff --git a/examples/switchrole/create-user-and-role/.gitignore b/examples/switchrole/create-user-and-role/.gitignore new file mode 100644 index 00000000000..c6958891dd2 --- /dev/null +++ b/examples/switchrole/create-user-and-role/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/node_modules/ diff --git a/examples/switchrole/create-user-and-role/Pulumi.yaml b/examples/switchrole/create-user-and-role/Pulumi.yaml new file mode 100644 index 00000000000..46c60c57cab --- /dev/null +++ b/examples/switchrole/create-user-and-role/Pulumi.yaml @@ -0,0 +1,3 @@ +name: create-user-and-role +runtime: nodejs +description: Demonstrate use of AWS profiles for role switching diff --git a/examples/switchrole/create-user-and-role/index.ts b/examples/switchrole/create-user-and-role/index.ts new file mode 100644 index 00000000000..c2e49d7f58f --- /dev/null +++ b/examples/switchrole/create-user-and-role/index.ts @@ -0,0 +1,37 @@ +import * as aws from "@pulumi/aws"; +import * as pulumi from "@pulumi/pulumi"; + +const config = new pulumi.Config(); +const unprivilegedUsername = config.require("unprivilegedUsername"); + +const unprivilegedUser = new aws.iam.User("unprivileged-user", { + name: unprivilegedUsername, +}); + +const unprivilegedUserCreds = new aws.iam.AccessKey("unprivileged-user-key", { + user: unprivilegedUser.name, +}); + +const allowS3ManagementRole = new aws.iam.Role("allow-s3-management", { + description: "Allow management of S3 buckets", + assumeRolePolicy: unprivilegedUser.arn.apply(arn => { + return aws.iam.assumeRolePolicyForPrincipal({AWS: arn}) + }), +}); + +new aws.iam.RolePolicy("allow-s3-management-policy", { + role: allowS3ManagementRole, + policy: { + Version: "2012-10-17", + Statement: [{ + Sid: "AllowS3Management", + Effect: "Allow", + Resource: "*", + Action: "s3:*", + }] + } +}, {parent: allowS3ManagementRole}); + +export const roleArn = allowS3ManagementRole.arn; +export const accessKeyId = unprivilegedUserCreds.id; +export const secretAccessKey = unprivilegedUserCreds.secret; diff --git a/examples/switchrole/create-user-and-role/package.json b/examples/switchrole/create-user-and-role/package.json new file mode 100644 index 00000000000..eb2e46a9781 --- /dev/null +++ b/examples/switchrole/create-user-and-role/package.json @@ -0,0 +1,10 @@ +{ + "name": "typescript", + "devDependencies": { + "@types/node": "latest" + }, + "dependencies": { + "@pulumi/aws": "^0.18.6", + "@pulumi/pulumi": "latest" + } +} diff --git a/examples/switchrole/create-user-and-role/tsconfig.json b/examples/switchrole/create-user-and-role/tsconfig.json new file mode 100644 index 00000000000..16caa48c2a4 --- /dev/null +++ b/examples/switchrole/create-user-and-role/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "outDir": "bin", + "target": "es6", + "lib": [ + "es6" + ], + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "pretty": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true + }, + "files": [ + "index.ts" + ] +} diff --git a/examples/switchrole/use-role/.gitignore b/examples/switchrole/use-role/.gitignore new file mode 100644 index 00000000000..c6958891dd2 --- /dev/null +++ b/examples/switchrole/use-role/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/node_modules/ diff --git a/examples/switchrole/use-role/Pulumi.yaml b/examples/switchrole/use-role/Pulumi.yaml new file mode 100644 index 00000000000..e43d8ba77b2 --- /dev/null +++ b/examples/switchrole/use-role/Pulumi.yaml @@ -0,0 +1,3 @@ +name: use-role +runtime: nodejs +description: Use the created role diff --git a/examples/switchrole/use-role/index.ts b/examples/switchrole/use-role/index.ts new file mode 100644 index 00000000000..77ba100c27a --- /dev/null +++ b/examples/switchrole/use-role/index.ts @@ -0,0 +1,5 @@ +import * as aws from "@pulumi/aws"; + +const bucket = new aws.s3.Bucket("created-with-role"); + +export const bucketArn = bucket.arn; diff --git a/examples/switchrole/use-role/package.json b/examples/switchrole/use-role/package.json new file mode 100644 index 00000000000..eb2e46a9781 --- /dev/null +++ b/examples/switchrole/use-role/package.json @@ -0,0 +1,10 @@ +{ + "name": "typescript", + "devDependencies": { + "@types/node": "latest" + }, + "dependencies": { + "@pulumi/aws": "^0.18.6", + "@pulumi/pulumi": "latest" + } +} diff --git a/examples/switchrole/use-role/tsconfig.json b/examples/switchrole/use-role/tsconfig.json new file mode 100644 index 00000000000..16caa48c2a4 --- /dev/null +++ b/examples/switchrole/use-role/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "outDir": "bin", + "target": "es6", + "lib": [ + "es6" + ], + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "pretty": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true + }, + "files": [ + "index.ts" + ] +} diff --git a/resources.go b/resources.go index b32af5b6e8a..81709a5c2a1 100644 --- a/resources.go +++ b/resources.go @@ -1,4 +1,4 @@ -// Copyright 2016-2018, Pulumi Corporation.( +// Copyright 2016-2018, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -191,17 +191,7 @@ func preConfigureCallback(vars resource.PropertyMap, c *terraform.ResourceConfig } config.CredsFilename = credsPath - // TODO[pulumi/pulumi-terraform#48] We should also be setting `config.AssumeRole*` here, but we are currently - // blocked on not being able to read out list-valued provider config. - - creds, err := awsbase.GetCredentials(config) - if err != nil { - return errors.New("unable to discover AWS AccessKeyID and/or SecretAccessKey " + - "- see https://pulumi.io/install/aws.html for details on configuration") - } - - _, err = creds.Get() - if err != nil { + if _, err := awsbase.GetCredentials(config); err != nil { return errors.New("unable to discover AWS AccessKeyID and/or SecretAccessKey " + "- see https://pulumi.io/install/aws.html for details on configuration") } @@ -230,6 +220,11 @@ func Provider() tfbridge.ProviderInfo { EnvVars: []string{"AWS_REGION", "AWS_DEFAULT_REGION"}, }, }, + "profile": { + Default: &tfbridge.DefaultInfo{ + EnvVars: []string{"AWS_PROFILE"}, + }, + }, }, PreConfigureCallback: preConfigureCallback, Resources: map[string]*tfbridge.ResourceInfo{ diff --git a/sdk/go/aws/config/config.go b/sdk/go/aws/config/config.go index d47caae8b27..ccf6bbf6312 100644 --- a/sdk/go/aws/config/config.go +++ b/sdk/go/aws/config/config.go @@ -41,7 +41,14 @@ func GetMaxRetries(ctx *pulumi.Context) int { // The profile for API operations. If not set, the default profile created with `aws configure` will be used. func GetProfile(ctx *pulumi.Context) string { - return config.Get(ctx, "aws:profile") + v, err := config.Try(ctx, "aws:profile") + if err == nil { + return v + } + if dv, ok := getEnvOrDefault("", nil, "AWS_PROFILE").(string); ok { + return dv + } + return v } // The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. diff --git a/sdk/nodejs/config/vars.ts b/sdk/nodejs/config/vars.ts index fd257884048..74b3a8ea7e3 100644 --- a/sdk/nodejs/config/vars.ts +++ b/sdk/nodejs/config/vars.ts @@ -27,7 +27,7 @@ export let maxRetries: number | undefined = __config.getObject("maxRetri /** * The profile for API operations. If not set, the default profile created with `aws configure` will be used. */ -export let profile: string | undefined = __config.get("profile"); +export let profile: string | undefined = __config.get("profile") || utilities.getEnv("AWS_PROFILE"); /** * The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. */ diff --git a/sdk/nodejs/provider.ts b/sdk/nodejs/provider.ts index a22e61a8738..e5c4232e7c2 100644 --- a/sdk/nodejs/provider.ts +++ b/sdk/nodejs/provider.ts @@ -31,7 +31,7 @@ export class Provider extends pulumi.ProviderResource { inputs["forbiddenAccountIds"] = pulumi.output(args ? args.forbiddenAccountIds : undefined).apply(JSON.stringify); inputs["insecure"] = pulumi.output(args ? args.insecure : undefined).apply(JSON.stringify); inputs["maxRetries"] = pulumi.output(args ? args.maxRetries : undefined).apply(JSON.stringify); - inputs["profile"] = args ? args.profile : undefined; + 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; diff --git a/sdk/python/pulumi_aws/config/vars.py b/sdk/python/pulumi_aws/config/vars.py index 4ea10f06ee8..0cebab7e195 100644 --- a/sdk/python/pulumi_aws/config/vars.py +++ b/sdk/python/pulumi_aws/config/vars.py @@ -33,7 +33,7 @@ The maximum number of times an AWS API request is being executed. If the API request still fails, an error is thrown. """ -profile = __config__.get('profile') +profile = __config__.get('profile') or utilities.get_env('AWS_PROFILE') """ The profile for API operations. If not set, the default profile created with `aws configure` will be used. """ diff --git a/sdk/python/pulumi_aws/provider.py b/sdk/python/pulumi_aws/provider.py index d98e317c8d3..e35e0ab9651 100644 --- a/sdk/python/pulumi_aws/provider.py +++ b/sdk/python/pulumi_aws/provider.py @@ -48,6 +48,8 @@ def __init__(__self__, resource_name, opts=None, access_key=None, allowed_accoun __props__['max_retries'] = pulumi.Output.from_input(max_retries).apply(json.dumps) if max_retries is not None else None + if profile is None: + profile = utilities.get_env('AWS_PROFILE') __props__['profile'] = profile if region is None: