-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5195 from terraform-providers/td-aws_kms_secrets
New Data Source: aws_kms_secrets and add DeprecationMessage to aws_kms_secret data source
- Loading branch information
Showing
8 changed files
with
912 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package aws | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/kms" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func dataSourceAwsKmsSecrets() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceAwsKmsSecretsRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"secret": { | ||
Type: schema.TypeSet, | ||
Required: true, | ||
ForceNew: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"payload": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"context": { | ||
Type: schema.TypeMap, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
"grant_tokens": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"plaintext": { | ||
Type: schema.TypeMap, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
Sensitive: true, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceAwsKmsSecretsRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).kmsconn | ||
|
||
secrets := d.Get("secret").(*schema.Set) | ||
plaintext := make(map[string]string, len(secrets.List())) | ||
|
||
for _, v := range secrets.List() { | ||
secret := v.(map[string]interface{}) | ||
|
||
// base64 decode the payload | ||
payload, err := base64.StdEncoding.DecodeString(secret["payload"].(string)) | ||
if err != nil { | ||
return fmt.Errorf("Invalid base64 value for secret '%s': %v", secret["name"].(string), err) | ||
} | ||
|
||
// build the kms decrypt params | ||
params := &kms.DecryptInput{ | ||
CiphertextBlob: []byte(payload), | ||
} | ||
if context, exists := secret["context"]; exists { | ||
params.EncryptionContext = make(map[string]*string) | ||
for k, v := range context.(map[string]interface{}) { | ||
params.EncryptionContext[k] = aws.String(v.(string)) | ||
} | ||
} | ||
if grant_tokens, exists := secret["grant_tokens"]; exists { | ||
params.GrantTokens = make([]*string, 0) | ||
for _, v := range grant_tokens.([]interface{}) { | ||
params.GrantTokens = append(params.GrantTokens, aws.String(v.(string))) | ||
} | ||
} | ||
|
||
// decrypt | ||
resp, err := conn.Decrypt(params) | ||
if err != nil { | ||
return fmt.Errorf("Failed to decrypt '%s': %s", secret["name"].(string), err) | ||
} | ||
|
||
// Set the secret via the name | ||
log.Printf("[DEBUG] aws_kms_secret - successfully decrypted secret: %s", secret["name"].(string)) | ||
plaintext[secret["name"].(string)] = string(resp.Plaintext) | ||
} | ||
|
||
if err := d.Set("plaintext", plaintext); err != nil { | ||
return fmt.Errorf("error setting plaintext: %s", err) | ||
} | ||
|
||
d.SetId(time.Now().UTC().String()) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package aws | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/kms" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSKmsSecretsDataSource_basic(t *testing.T) { | ||
var encryptedPayload string | ||
var key kms.KeyMetadata | ||
|
||
plaintext := "my-plaintext-string" | ||
resourceName := "aws_kms_key.test" | ||
|
||
// Run a resource test to setup our KMS key | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckAwsKmsSecretsDataSourceKey, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSKmsKeyExists(resourceName, &key), | ||
testAccDataSourceAwsKmsSecretsEncrypt(&key, plaintext, &encryptedPayload), | ||
// We need to dereference the encryptedPayload in a test Terraform configuration | ||
testAccDataSourceAwsKmsSecretsDecrypt(t, plaintext, &encryptedPayload), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDataSourceAwsKmsSecretsEncrypt(key *kms.KeyMetadata, plaintext string, encryptedPayload *string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
kmsconn := testAccProvider.Meta().(*AWSClient).kmsconn | ||
|
||
input := &kms.EncryptInput{ | ||
KeyId: key.Arn, | ||
Plaintext: []byte(plaintext), | ||
EncryptionContext: map[string]*string{ | ||
"name": aws.String("value"), | ||
}, | ||
} | ||
|
||
resp, err := kmsconn.Encrypt(input) | ||
if err != nil { | ||
return fmt.Errorf("failed encrypting string: %s", err) | ||
} | ||
|
||
*encryptedPayload = base64.StdEncoding.EncodeToString(resp.CiphertextBlob) | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccDataSourceAwsKmsSecretsDecrypt(t *testing.T, plaintext string, encryptedPayload *string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
dataSourceName := "data.aws_kms_secrets.test" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckAwsKmsSecretsDataSourceSecret(*encryptedPayload), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(dataSourceName, "plaintext.%", "1"), | ||
resource.TestCheckResourceAttr(dataSourceName, "plaintext.secret1", plaintext), | ||
), | ||
}, | ||
}, | ||
}) | ||
|
||
return nil | ||
} | ||
} | ||
|
||
const testAccCheckAwsKmsSecretsDataSourceKey = ` | ||
resource "aws_kms_key" "test" { | ||
deletion_window_in_days = 7 | ||
description = "Testing the Terraform AWS KMS Secrets data_source" | ||
} | ||
` | ||
|
||
func testAccCheckAwsKmsSecretsDataSourceSecret(payload string) string { | ||
return testAccCheckAwsKmsSecretsDataSourceKey + fmt.Sprintf(` | ||
data "aws_kms_secrets" "test" { | ||
secret { | ||
name = "secret1" | ||
payload = %q | ||
context { | ||
name = "value" | ||
} | ||
} | ||
} | ||
`, payload) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_kms_secrets" | ||
sidebar_current: "docs-aws-datasource-kms-secrets" | ||
description: |- | ||
Decrypt multiple secrets from data encrypted with the AWS KMS service | ||
--- | ||
|
||
# Data Source: aws_kms_secrets | ||
|
||
Decrypt multiple secrets from data encrypted with the AWS KMS service. | ||
|
||
~> **NOTE**: Using this data provider will allow you to conceal secret data within your resource definitions but does not take care of protecting that data in all Terraform logging and state output. Please take care to secure your secret data beyond just the Terraform configuration. | ||
|
||
## Example Usage | ||
|
||
If you do not already have a `CiphertextBlob` from encrypting a KMS secret, you can use the below commands to obtain one using the [AWS CLI kms encrypt](https://docs.aws.amazon.com/cli/latest/reference/kms/encrypt.html) command. This requires you to have your AWS CLI setup correctly and replace the `--key-id` with your own. Alternatively you can use `--plaintext 'password'` instead of reading from a file. | ||
|
||
-> If you have a newline character at the end of your file, it will be decrypted with this newline character intact. For most use cases this is undesirable and leads to incorrect passwords or invalid values, as well as possible changes in the plan. Be sure to use `echo -n` if necessary. | ||
|
||
```sh | ||
$ echo -n 'master-password' > plaintext-password | ||
$ aws kms encrypt --key-id ab123456-c012-4567-890a-deadbeef123 --plaintext fileb://plaintext-password --encryption-context foo=bar --output text --query CiphertextBlob | ||
AQECAHgaPa0J8WadplGCqqVAr4HNvDaFSQ+NaiwIBhmm6qDSFwAAAGIwYAYJKoZIhvcNAQcGoFMwUQIBADBMBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDI+LoLdvYv8l41OhAAIBEIAfx49FFJCLeYrkfMfAw6XlnxP23MmDBdqP8dPp28OoAQ== | ||
``` | ||
|
||
That encrypted output can now be inserted into Terraform configurations without exposing the plaintext secret directly. | ||
|
||
```hcl | ||
data "aws_kms_secrets" "example" { | ||
secret { | ||
name = "master_password" | ||
payload = "AQECAHgaPa0J8WadplGCqqVAr4HNvDaFSQ+NaiwIBhmm6qDSFwAAAGIwYAYJKoZIhvcNAQcGoFMwUQIBADBMBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDI+LoLdvYv8l41OhAAIBEIAfx49FFJCLeYrkfMfAw6XlnxP23MmDBdqP8dPp28OoAQ==" | ||
context { | ||
foo = "bar" | ||
} | ||
} | ||
} | ||
resource "aws_rds_cluster" "example" { | ||
# ... other configuration ... | ||
master_password = "${data.aws_kms_secrets.example.plaintext["master_password"]}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `secret` - (Required) One or more encrypted payload definitions from the KMS service. See the Secret Definitions below. | ||
|
||
### Secret Definitions | ||
|
||
Each `secret` supports the following arguments: | ||
|
||
* `name` - (Required) The name to export this secret under in the attributes. | ||
* `payload` - (Required) Base64 encoded payload, as returned from a KMS encrypt operation. | ||
* `context` - (Optional) An optional mapping that makes up the Encryption Context for the secret. | ||
* `grant_tokens` (Optional) An optional list of Grant Tokens for the secret. | ||
|
||
For more information on `context` and `grant_tokens` see the [KMS | ||
Concepts](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html) | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `plaintext` - Map containing each `secret` `name` as the key with its decrypted plaintext value |
Oops, something went wrong.