-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds google_kms_secret data source (#741)
* Create google_kms_secret datasource * Create google_kms_secret datasource documentation * Remove duplicated code * Create acceptance test * Fix indentation * Add documentation to sidebar * Update Cloud SDK link in docs * Oxford comma * Rename variable to make it clear which resource is under test * Update test to use utils from provider_test
- Loading branch information
Showing
5 changed files
with
260 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package google | ||
|
||
import ( | ||
"google.golang.org/api/cloudkms/v1" | ||
|
||
"encoding/base64" | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"log" | ||
"time" | ||
) | ||
|
||
func dataSourceGoogleKmsSecret() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceGoogleKmsSecretRead, | ||
Schema: map[string]*schema.Schema{ | ||
"crypto_key": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"ciphertext": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"plaintext": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Sensitive: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceGoogleKmsSecretRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
cryptoKeyId, err := parseKmsCryptoKeyId(d.Get("crypto_key").(string), config) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
ciphertext := d.Get("ciphertext").(string) | ||
|
||
kmsDecryptRequest := &cloudkms.DecryptRequest{ | ||
Ciphertext: ciphertext, | ||
} | ||
|
||
decryptResponse, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Decrypt(cryptoKeyId.cryptoKeyId(), kmsDecryptRequest).Do() | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error decrypting ciphertext: %s", err) | ||
} | ||
|
||
plaintext, err := base64.StdEncoding.DecodeString(decryptResponse.Plaintext) | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error decoding base64 response: %s", err) | ||
} | ||
|
||
log.Printf("[INFO] Successfully decrypted ciphertext: %s", ciphertext) | ||
|
||
d.Set("plaintext", string(plaintext[:])) | ||
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,96 @@ | ||
package google | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"google.golang.org/api/cloudkms/v1" | ||
"log" | ||
) | ||
|
||
func TestAccGoogleKmsSecret_basic(t *testing.T) { | ||
t.Parallel() | ||
|
||
projectOrg := getTestOrgFromEnv(t) | ||
projectBillingAccount := getTestBillingAccountFromEnv(t) | ||
|
||
projectId := "terraform-" + acctest.RandString(10) | ||
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) | ||
cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) | ||
|
||
plaintext := fmt.Sprintf("secret-%s", acctest.RandString(10)) | ||
|
||
// The first test creates resources needed to encrypt plaintext and produce ciphertext | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), | ||
Check: func(s *terraform.State) error { | ||
ciphertext, cryptoKeyId, err := testAccEncryptSecretDataWithCryptoKey(s, "google_kms_crypto_key.crypto_key", plaintext) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
// The second test asserts that the data source has the correct plaintext, given the created ciphertext | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testGoogleKmsSecret_datasource(cryptoKeyId.terraformId(), ciphertext), | ||
Check: resource.TestCheckResourceAttr("data.google_kms_secret.acceptance", "plaintext", plaintext), | ||
}, | ||
}, | ||
}) | ||
|
||
return nil | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccEncryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyResourceName, plaintext string) (string, *kmsCryptoKeyId, error) { | ||
config := testAccProvider.Meta().(*Config) | ||
|
||
rs, ok := s.RootModule().Resources[cryptoKeyResourceName] | ||
if !ok { | ||
return "", nil, fmt.Errorf("Resource not found: %s", cryptoKeyResourceName) | ||
} | ||
|
||
cryptoKeyId, err := parseKmsCryptoKeyId(rs.Primary.Attributes["id"], config) | ||
|
||
if err != nil { | ||
return "", nil, err | ||
} | ||
|
||
kmsEncryptRequest := &cloudkms.EncryptRequest{ | ||
Plaintext: base64.StdEncoding.EncodeToString([]byte(plaintext)), | ||
} | ||
|
||
encryptResponse, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Encrypt(cryptoKeyId.cryptoKeyId(), kmsEncryptRequest).Do() | ||
|
||
if err != nil { | ||
return "", nil, fmt.Errorf("Error encrypting plaintext: %s", err) | ||
} | ||
|
||
log.Printf("[INFO] Successfully encrypted plaintext and got ciphertext: %s", encryptResponse.Ciphertext) | ||
|
||
return encryptResponse.Ciphertext, cryptoKeyId, nil | ||
} | ||
|
||
func testGoogleKmsSecret_datasource(cryptoKeyTerraformId, ciphertext string) string { | ||
return fmt.Sprintf(` | ||
data "google_kms_secret" "acceptance" { | ||
crypto_key = "%s" | ||
ciphertext = "%s" | ||
} | ||
`, cryptoKeyTerraformId, ciphertext) | ||
} |
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,93 @@ | ||
--- | ||
layout: "google" | ||
page_title: "Google: google_kms_secret" | ||
sidebar_current: "docs-google-kms-secret" | ||
description: |- | ||
Provides access to secret data encrypted with Google Cloud KMS | ||
--- | ||
|
||
# google\_kms\_secret | ||
|
||
This data source allows you to use data encrypted with Google Cloud KMS | ||
within your resource definitions. | ||
|
||
For more information see | ||
[the official documentation](https://cloud.google.com/kms/docs/encrypt-decrypt). | ||
|
||
~> **NOTE**: Using this data provider will allow you to conceal secret data within your | ||
resource definitions, but it 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, create a KMS KeyRing and CryptoKey using the resource definitions: | ||
|
||
```hcl | ||
resource "google_kms_key_ring" "my_key_ring" { | ||
project = "my-project" | ||
name = "my-key-ring" | ||
location = "us-central1" | ||
} | ||
resource "google_kms_crypto_key" "my_crypto_key" { | ||
name = "my-crypto-key" | ||
key_ring = "${google_kms_key_ring.my_key_ring.id}" | ||
} | ||
``` | ||
|
||
Next, use the [Cloud SDK](https://cloud.google.com/sdk/gcloud/reference/kms/encrypt) to encrypt some | ||
sensitive information: | ||
|
||
```bash | ||
$ echo -n my-secret-password | gcloud kms encrypt \ | ||
> --project my-project \ | ||
> --location us-central1 \ | ||
> --keyring my-key-ring \ | ||
> --key my-crypto-key \ | ||
> --plaintext-file - \ | ||
> --ciphertext-file - \ | ||
> | base64 | ||
CiQAqD+xX4SXOSziF4a8JYvq4spfAuWhhYSNul33H85HnVtNQW4SOgDu2UZ46dQCRFl5MF6ekabviN8xq+F+2035ZJ85B+xTYXqNf4mZs0RJitnWWuXlYQh6axnnJYu3kDU= | ||
``` | ||
|
||
Finally, reference the encrypted ciphertext in your resource definitions: | ||
|
||
```hcl | ||
data "google_kms_secret" "sql_user_password" { | ||
crypto_key = "${google_kms_crypto_key.my_crypto_key.id}" | ||
ciphertext = "CiQAqD+xX4SXOSziF4a8JYvq4spfAuWhhYSNul33H85HnVtNQW4SOgDu2UZ46dQCRFl5MF6ekabviN8xq+F+2035ZJ85B+xTYXqNf4mZs0RJitnWWuXlYQh6axnnJYu3kDU=" | ||
} | ||
resource "google_sql_database_instance" "master" { | ||
name = "master-instance" | ||
settings { | ||
tier = "D0" | ||
} | ||
} | ||
resource "google_sql_user" "users" { | ||
name = "me" | ||
instance = "${google_sql_database_instance.master.name}" | ||
host = "me.com" | ||
password = "${data.google_kms_secret.sql_user_password.plaintext}" | ||
} | ||
``` | ||
|
||
This will result in a Cloud SQL user being created with password `my-secret-password`. | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `ciphertext` (Required) - The ciphertext to be decrypted, encoded in base64 | ||
* `crypto_key` (Required) - The id of the CryptoKey that will be used to | ||
decrypt the provided ciphertext. This is represented by the format | ||
`{projectId}/{location}/{keyRingName}/{cryptoKeyName}`. | ||
|
||
## Attributes Reference | ||
|
||
The following attribute is exported: | ||
|
||
* `plaintext` - Contains the result of decrypting the provided ciphertext. |
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