Skip to content

Commit

Permalink
Add examples for secrets providers (pulumi#630)
Browse files Browse the repository at this point in the history
* Add examples for secrets providers

* Address feedback

Remove copy-paste errors from Azure README.md
Rename Azure project to use keyvault name
  • Loading branch information
jaxxstorm committed Apr 7, 2020
1 parent 90f6fa5 commit aefa9e5
Show file tree
Hide file tree
Showing 19 changed files with 534 additions and 0 deletions.
6 changes: 6 additions & 0 deletions secrets-provider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Setting up secrets providers for Pulumi

Pulumi supports [secrets-providers](https://www.pulumi.com/docs/intro/concepts/config/#configuring-secrets-encryption) which allow you to encrypt the secrets you store in the Pulumi statefile.

This example shows how to set up the secrets for each cloud and walks through initializing your stack using the different secrets providers.

3 changes: 3 additions & 0 deletions secrets-provider/aws/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/
/node_modules/
Pulumi.*.yaml
3 changes: 3 additions & 0 deletions secrets-provider/aws/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: pulumi-aws-kms
runtime: nodejs
description: Minimal config which shows how AWS encryption support works
108 changes: 108 additions & 0 deletions secrets-provider/aws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Pulumi AWS KMS Encryption

Pulumi allows you to use KMS encryption from your cloud provider to encrypt any secrets stored in the backend.

This example shows how this might be done for AWS KMS. It creates an S3 bucket with a single file that has a "secret" value.

# Getting Started

To use this example, perform the following steps. This examples assumes you have the pulumi-cli installed and the aws-cli installed.

You should also ensure you have the correct `AWS_PROFILE` set:

```bash
export AWS_PROFILE="myaccount"
```

## Create an AWS KMS Key

```bash
aws kms create-key --tags TagKey=Purpose,TagValue="Pulumi Secret Encryption" --description "Pulumi secret encryption Key"

# Optionally create an alias to this key
aws kms create-alias --alias-name alias/pulumi-encryption --target-key-id $MY_KEY_ID
```

_When creating your key, be sure to specify a sane key policy that restricts access to only those that need to use the key_

## Initialize your stack

Initialize your stack with Pulumi and ensure you set the `--secrets-provider` flag:

```bash
# Using your alias
pulumi stack init $PULUMI_ORG_NAME/$PULUMI_STACK_NAME --secrets-provider="awskms:https://alias/pulumi-encryption?region=us-west-2"

# Using your key id
pulumi stack init $PULUMI_ORG_NAME/$PULUMI_STACK_NAME --secrets-provider="awskms:https://1234abcd-12ab-34cd-56ef-1234567890ab?region=us-west-2"
```

## Verify your stack settings

If everything has worked as expected, you should be able to verify in your stack settings that the secretsprovider is set:

```bash
cat Pulumi.$PULUMI_STACK_NAME.yaml
secretsprovider: awskms:https://alias/pulumi-encryption?region=us-west-2
encryptedkey: AQICAHiGajWxHHTBJxo1FU9BOztzLzxEXpr02SgLetPNGfdfLAG7c5ylmHRJJRz5jtaj2LtzAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMT+iyFkgT4bmdja9WAgEQgDuVYN+iLr6sdyFNGXJS8GfjKiqMBXVvwmn9byd3ywCfJwMsuDnpqAWSmquV5eoLBdPEEOY1D/TuBQuCLQ==
```

## Set your configuration settings

```bash
pulumi config set aws:region us-west-2
# Set the bucketname & the secret contents
pulumi config set bucketName pulumi-lbriggs
pulumi config set --secret secretValue "correct-horse-battery-stable"
```

## Create the stack

```bash
# This will create the stack without prompting, be aware!
pulumi up --yes
Previewing update (aws-kms):
Type Name Plan
+ pulumi:pulumi:Stack pulumi-aws-kms-aws-kms create
+ ├─ aws:s3:Bucket bucket create
+ └─ aws:s3:BucketObject secret create

Resources:
+ 3 to create

Updating (aws-kms):
Type Name Status
+ pulumi:pulumi:Stack pulumi-aws-kms-aws-kms created
+ ├─ aws:s3:Bucket bucket created
+ └─ aws:s3:BucketObject secret created

Outputs:
bucketId: "pulumi-lbriggs"
secretId: "[secret]"

Resources:
+ 3 created

Duration: 8s

Permalink: <redacted>
```

You'll notice the secret value is also omitted from the output!

## Verify the encryption

A quick way to verify if the encryption is using the AWS KMS key is to remove your `AWS_PROFILE` setting:

```bash
unset AWS_PROFILE
pulumi up --yes
error: getting secrets manager: secrets (code=Unknown): InvalidSignatureException: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
status code: 400, request id: 35ff51c6-ef88-4c06-9146-361231b8fd4a
```






28 changes: 28 additions & 0 deletions secrets-provider/aws/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import { secret } from "@pulumi/pulumi";

// Import config
const config = new pulumi.Config();

// Make the bucketName configurable
const bucketName = config.require('bucketName');
const secretValue = config.requireSecret('secretValue');

// Create a private bucket
const bucket = new aws.s3.Bucket("bucket", {
bucket: bucketName,
acl: "private",
});

// Create an object from the secret value
const superSecretObject = new aws.s3.BucketObject("secret", {
bucket: bucket.id,
key: "secret",
content: secretValue,
})

// Export the name of the bucket and the secretValue
export const bucketId = bucket.id;
export const secretId = secretValue;
11 changes: 11 additions & 0 deletions secrets-provider/aws/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "pulumi-aws-kmstest",
"devDependencies": {
"@types/node": "^8.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^1.0.0",
"@pulumi/aws": "^1.0.0",
"@pulumi/awsx": "^0.18.10"
}
}
18 changes: 18 additions & 0 deletions secrets-provider/aws/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
2 changes: 2 additions & 0 deletions secrets-provider/azure/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
3 changes: 3 additions & 0 deletions secrets-provider/azure/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: pulumi-azure-keyvault
runtime: nodejs
description: Minimal config which shows how Azure encryption support works
109 changes: 109 additions & 0 deletions secrets-provider/azure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Pulumi Azure KMS Encryption

Pulumi allows you to use Azure Keyvault encryption from your cloud provider to encrypt any secrets stored in the backend.

This example shows how this might be done for Azure Keyvault. It creates a storage bucket with a single file that has a "secret" value.

# Getting Started

To use this example, perform the following steps. This examples assumes you have the pulumi-cli installed and the Azure CLI installed.

You should also ensure:

* You azure command line tool installed
* You are logging in via the `az` command line tool.
* You have created a resource-group
* You must have the environment variable `AZURE_KEYVAULT_AUTH_VIA_CLI` set to `true` eg: `export AZURE_KEYVAULT_AUTH_VIA_CLI=true`

## Create an Azure Keyvault Key

```bash
# First, create a keyvault
az keyvault create -l westus -n pulumi --resource-group $RESOURCE_GROUP_NAME

# Then, create a key
az keyvault key create --name pulumi-secret --vault-name pulumi

# Finally, set the relevant permissions on the keyvault
az keyvault set-policy --name pulumi --object-id $YOUR_OBJECT_ID --key-permissions decrypt get create delete list update import backup restore recover
```

_When creating your key, be sure to specify a permissions that restricts access to only those that need to use the key_

## Initialize your stack

Initialize your stack with Pulumi and ensure you set the `--secrets-provider` flag:

```bash
# Using your vault and key name
pulumi stack init $PULUMI_ORG_NAME/$PULUMI_STACK_NAME --secrets-provider="azurekeyvault:https://pulumi.vault.azure.net/keys/pulumi-secret"
```

## Verify your stack settings

If everything has worked as expected, you should be able to verify in your stack settings that the secretsprovider is set:

```bash
cat Pulumi.$PULUMI_STACK_NAME.yaml
secretsprovider: azurekeyvault:https://pulumi.vault.azure.net/keys/pulumi-secret/b636b47f2b474b2a8de3526561eae81b
encryptedkey: Q2U5a1ZuTWsxLXVWOFdhVEdfaGExdWR1SzhzTlVFMldhWGlxU3RJVVdUWFJBcmM4M1ZlYzZOVVlpU3J2dW1NX2RIelMwV1h4el9hSjFibjcwdjVXcEgxZVlFa2c1LTlGUTBwX2ZnamcyNXh0V2RnYXlKaUNWSzd0VmlhY0ZyT2NCNGJ2SG40NkE4OFR2d0NWVzVEOUZOaUpGNm03TTlLUEl4VC0tbG9fYUJSSUlrZDJuUmNxVTJ2cWxDUjYtdVJYYjJKUjFoTlRYYkNaaEVTUzY4dGtNajZNRXBOQ1k4OGc4d0RTeUVBVGhweEswbUVXc3RaaGUtdnpQdktVY2tFUGFCVkdOaHZHOU1SYU91RWJ6QVZnLUtVdExHYlFHd19vUU15T3I4d3ZvajdJQ0liS0QtUTNLY0h4Q0JsMGNjd1A5ZXNWRUNNQ0tQZGhPY1cySTJwU1BR

```

## Set your configuration settings

```bash
pulumi config set azure:location westus
# Set the bucketname & the secret contents
pulumi config set bucketName pulumilbriggs
pulumi config set --secret secretValue "correct-horse-battery-stable"
```

## Create the stack

```bash
# This will create the stack without prompting, be aware!
Previewing update (azure-keyvault):
Type Name Plan
pulumi:pulumi:Stack pulumi-azure-keyvault-azure-keyvault
+ ├─ azure:core:ResourceGroup resourceGroup create
+ ├─ azure:storage:Account storage create
+ ├─ azure:storage:Container container create
+ └─ azure:storage:Blob blob create

Outputs:
+ connectionString: output<string>

Resources:
+ 4 to create
1 unchanged

Updating (azure-keyvault):
Type Name Status
pulumi:pulumi:Stack pulumi-azure-keyvault-azure-keyvault
+ ├─ azure:core:ResourceGroup resourceGroup created
+ ├─ azure:storage:Account storage created
+ ├─ azure:storage:Container container created
+ └─ azure:storage:Blob blob created

Outputs:
+ connectionString: "DefaultEndpointsProtocol=https;AccountName=pulumilbriggs;AccountKey=Efa63L/xDstQgyvgsYHZqzl3oIlQA4scS4NeX/O1TeBI3mbwMcKxiHIkAGkwJj21EPzHebiuAUM09i7dVv3f/A==;EndpointSuffix=core.windows.net"

Resources:
+ 4 created
1 unchanged

Duration: 31s

Permalink: https://app.pulumi.com/jaxxstorm/pulumi-azure-keyvault/azure-keyvault/updates/3
```

You'll notice the secret value is also omitted from the output!

## Verify the encryption

A quick way to verify if the encryption is using the Azure Keyvault key is to remove your application credentials temporarily:

```
unset AZURE_KEYVAULT_AUTH_VIA_CLI
```
40 changes: 40 additions & 0 deletions secrets-provider/azure/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as pulumi from "@pulumi/pulumi";
import * as azure from "@pulumi/azure";

const config = new pulumi.Config();

// Make the bucketName configurable
const bucketName = config.require('bucketName');
const secretValue = config.requireSecret('secretValue');

// Create an Azure Resource Group
const resourceGroup = new azure.core.ResourceGroup("resourceGroup", {
name: "lbriggs-pulumi"
});

// Create an Azure resource (Storage Account)
const account = new azure.storage.Account("storage", {
name: bucketName,
// The location for the storage account will be derived automatically from the resource group.
resourceGroupName: resourceGroup.name,
accountTier: "Standard",
accountReplicationType: "LRS",
});

const container = new azure.storage.Container("container", {
name: bucketName,
storageAccountName: account.name,
})

const blob = new azure.storage.Blob("blob", {
storageAccountName: account.name,
storageContainerName: container.name,
sourceContent: secretValue,
type: "Block",
})


// Export the connection string for the storage account
export const connectionString = account.primaryConnectionString;


10 changes: 10 additions & 0 deletions secrets-provider/azure/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "pulumi-azure-keyvault",
"devDependencies": {
"@types/node": "^8.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^1.0.0",
"@pulumi/azure": "^2.0.0"
}
}
18 changes: 18 additions & 0 deletions secrets-provider/azure/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
2 changes: 2 additions & 0 deletions secrets-provider/gcloud/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
3 changes: 3 additions & 0 deletions secrets-provider/gcloud/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: pulumi-gcloud-kms
runtime: nodejs
description: Minimal config to check gcloud encryption support
Loading

0 comments on commit aefa9e5

Please sign in to comment.