From ddde6902a7bf394d0191b1845adc43db647a7f6c Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 22 Feb 2019 19:05:24 -0500 Subject: [PATCH] data-source/aws_kms_secret: Soft remove data source type with removal message References: * https://github.com/terraform-providers/terraform-provider-aws/issues/5144 * https://github.com/terraform-providers/terraform-provider-aws/pull/5195 The `aws_kms_secret` data source uses dynamic attribute functionality which is not supported in Terraform 0.12 and later. Available since Terraform AWS Provider version 1.29.0, operators should migrate to the `aws_kms_secrets` data source, which uses a `plaintext` map attribute. Additional information can be found in the Version 2 Upgrade Guide: https://www.terraform.io/docs/providers/aws/guides/version-2-upgrade.html#data-source-aws_kms_secret Output from Terraform 0.11 attempted usage: ``` terraform apply data.aws_kms_secret.testing: Refreshing state... Error: Error refreshing state: 1 error(s) occurred: * data.aws_kms_secret.testing: 1 error(s) occurred: * data.aws_kms_secret.testing: data.aws_kms_secret.testing: This data source has been replaced with the `aws_kms_secrets` data source. Upgrade information is available at: https://www.terraform.io/docs/providers/aws/guides/version-2-upgrade.html#data-source-aws_kms_secret ``` Output from Terraform 0.12 attempted usage (we cannot return the proper error message if there are references, however capturing the output here in case some one is searching for this in the future): ``` $ terraform apply Error: Unsupported block type on main.tf line 10, in data "aws_kms_secret" "testing": 10: context { Blocks of type "context" are not expected here. Did you mean to define argument "context"? If so, use the equals sign to assign it a value. $ terraform 0.12upgrade -yes $ terraform apply Error: Unsupported attribute on main.tf line 17, in output "testing": 17: value = data.aws_kms_secret.testing.secret_name This object has no argument, nested block, or exported attribute named "secret_name". ``` Output from Terraform 0.11 acceptance testing: ``` --- PASS: TestAccAWSKmsSecretDataSource_removed (2.05s) ``` Output from Terraform 0.12 acceptance testing: ``` --- PASS: TestAccAWSKmsSecretDataSource_removed (2.18s) ``` --- aws/data_source_aws_kms_secret.go | 65 ++---------------- aws/data_source_aws_kms_secret_test.go | 86 ++++------------------- website/aws.erb | 3 - website/docs/d/kms_secret.html.markdown | 91 ------------------------- 4 files changed, 18 insertions(+), 227 deletions(-) delete mode 100644 website/docs/d/kms_secret.html.markdown diff --git a/aws/data_source_aws_kms_secret.go b/aws/data_source_aws_kms_secret.go index 16772633e52..c66494e39c0 100644 --- a/aws/data_source_aws_kms_secret.go +++ b/aws/data_source_aws_kms_secret.go @@ -1,20 +1,18 @@ package aws import ( - "encoding/base64" - "fmt" - "log" - "time" + "errors" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/kms" "github.com/hashicorp/terraform/helper/schema" ) +const dataSourceAwsKmsSecretRemovedMessage = "This data source has been replaced with the `aws_kms_secrets` data source. Upgrade information is available at: https://www.terraform.io/docs/providers/aws/guides/version-2-upgrade.html#data-source-aws_kms_secret" + func dataSourceAwsKmsSecret() *schema.Resource { return &schema.Resource{ - DeprecationMessage: "This data source will be removed in Terraform AWS provider version 2.0. Please see migration information available in: https://www.terraform.io/docs/providers/aws/guides/version-2-upgrade.html#data-source-aws_kms_secret", - Read: dataSourceAwsKmsSecretRead, + Read: func(d *schema.ResourceData, meta interface{}) error { + return errors.New(dataSourceAwsKmsSecretRemovedMessage) + }, Schema: map[string]*schema.Schema{ "secret": { @@ -44,57 +42,6 @@ func dataSourceAwsKmsSecret() *schema.Resource { }, }, }, - "__has_dynamic_attributes": { - Type: schema.TypeString, - Optional: true, - }, }, } } - -// dataSourceAwsKmsSecretRead decrypts the specified secrets -func dataSourceAwsKmsSecretRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).kmsconn - secrets := d.Get("secret").(*schema.Set) - - d.SetId(time.Now().UTC().String()) - - 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: 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)) - d.UnsafeSetFieldRaw(secret["name"].(string), string(resp.Plaintext)) - } - - return nil -} diff --git a/aws/data_source_aws_kms_secret_test.go b/aws/data_source_aws_kms_secret_test.go index 4d0bf139e7d..a2142c6791a 100644 --- a/aws/data_source_aws_kms_secret_test.go +++ b/aws/data_source_aws_kms_secret_test.go @@ -1,96 +1,34 @@ package aws import ( - "encoding/base64" - "fmt" + "regexp" "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 TestAccAWSKmsSecretDataSource_basic(t *testing.T) { - // Run a resource test to setup our KMS key - resource.Test(t, resource.TestCase{ +func TestAccAWSKmsSecretDataSource_removed(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccCheckAwsKmsSecretDataSourceKey, - Check: func(s *terraform.State) error { - encryptedPayload, err := testAccCheckAwsKmsSecretDataSourceCheckKeySetup(s) - if err != nil { - return err - } - - // We run the actual test on our data source nested in the - // Check function of the KMS key so we can access the - // encrypted output, above, and so that the key will be - // deleted at the end of the test - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - Steps: []resource.TestStep{ - { - Config: fmt.Sprintf(testAccCheckAwsKmsSecretDataSourceSecret, encryptedPayload), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.aws_kms_secret.testing", "secret_name", "PAYLOAD"), - ), - }, - }, - }) - - return nil - }, + Config: testAccAwsKmsSecretDataSourceConfig, + ExpectError: regexp.MustCompile(dataSourceAwsKmsSecretRemovedMessage), }, }, }) - } -func testAccCheckAwsKmsSecretDataSourceCheckKeySetup(s *terraform.State) (string, error) { - rs, ok := s.RootModule().Resources["aws_kms_key.terraform_data_source_testing"] - if !ok { - return "", fmt.Errorf("Failed to setup a KMS key for data source testing!") - } - - // Now that the key is setup encrypt a string using it - // XXX TODO: Set up and test with grants - params := &kms.EncryptInput{ - KeyId: aws.String(rs.Primary.Attributes["arn"]), - Plaintext: []byte("PAYLOAD"), - EncryptionContext: map[string]*string{ - "name": aws.String("value"), - }, - } - - kmsconn := testAccProvider.Meta().(*AWSClient).kmsconn - resp, err := kmsconn.Encrypt(params) - if err != nil { - return "", fmt.Errorf("Failed encrypting string with KMS for data source testing: %s", err) - } - - return base64.StdEncoding.EncodeToString(resp.CiphertextBlob), nil -} - -const testAccCheckAwsKmsSecretDataSourceKey = ` -resource "aws_kms_key" "terraform_data_source_testing" { - description = "Testing the Terraform AWS KMS Secret data_source" -} -` - -const testAccCheckAwsKmsSecretDataSourceSecret = ` +const testAccAwsKmsSecretDataSourceConfig = ` data "aws_kms_secret" "testing" { - secret { - name = "secret_name" - payload = "%s" + secret { + name = "secret_name" + payload = "data-source-removed" - context { - name = "value" - } + context = { + name = "value" } + } } ` diff --git a/website/aws.erb b/website/aws.erb index 7e8eadb23b8..296a2cdf81a 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -263,9 +263,6 @@ > aws_kms_key - > - aws_kms_secret - > aws_kms_secrets diff --git a/website/docs/d/kms_secret.html.markdown b/website/docs/d/kms_secret.html.markdown deleted file mode 100644 index 09d82d72baf..00000000000 --- a/website/docs/d/kms_secret.html.markdown +++ /dev/null @@ -1,91 +0,0 @@ ---- -layout: "aws" -page_title: "AWS: aws_kms_secret" -sidebar_current: "docs-aws-datasource-kms-secret-x" -description: |- - Provides secret data encrypted with the KMS service ---- - -# Data Source: aws_kms_secret - -!> **WARNING:** This data source is deprecated and will be removed in the next major version. You can migrate existing configurations to the [`aws_kms_secrets` data source](/docs/providers/aws/d/kms_secrets.html) following instructions available in the [Version 2 Upgrade Guide](/docs/providers/aws/guides/version-2-upgrade.html#data-source-aws_kms_secret). - -The KMS secret data source allows you to use data encrypted with the AWS KMS -service within your resource definitions. - -~> **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 the -logging output, plan output or state output. - -Please take care to secure your secret data outside of resource definitions. - -## Example Usage - -First, let's encrypt a password with KMS using the [AWS CLI -tools](http://docs.aws.amazon.com/cli/latest/reference/kms/encrypt.html). This -requires you to have your AWS CLI setup correctly, and you would replace the -key-id with your own. If you have a newline character at the end of your file, -secrets 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. -Alternatively you can use `--plaintext 'password'` instead of reading from a file. - -``` -$ 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== -``` - -Now, take that output and add it to your resource definitions. - -```hcl -data "aws_kms_secret" "db" { - secret { - name = "master_password" - payload = "AQECAHgaPa0J8WadplGCqqVAr4HNvDaFSQ+NaiwIBhmm6qDSFwAAAGIwYAYJKoZIhvcNAQcGoFMwUQIBADBMBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDI+LoLdvYv8l41OhAAIBEIAfx49FFJCLeYrkfMfAw6XlnxP23MmDBdqP8dPp28OoAQ==" - - context { - foo = "bar" - } - } -} - -resource "aws_rds_cluster" "rds" { - master_username = "root" - master_password = "${data.aws_kms_secret.db.master_password}" - - # ... -} -``` - -And your RDS cluster would have the root password set to "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 definition 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 - opertation. -* `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](http://docs.aws.amazon.com/kms/latest/developerguide/concepts.html) - -## Attributes Reference - -Each `secret` defined is exported under its `name` as a top-level attribute.