Skip to content

Commit

Permalink
Additional Authenticated Data AAD for Cloud KMS secrets (#3271)
Browse files Browse the repository at this point in the history
* AAD for KMS secrets

* add test for decryption

* update datasource docs for google_kms_secret (decrypt)

* add test for encryption with aad
  • Loading branch information
chrissng authored Mar 24, 2020
1 parent 36062b0 commit 54c8b06
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 5 deletions.
4 changes: 4 additions & 0 deletions products/kms/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ objects:
description: |
The plaintext to be encrypted.
required: true
- !ruby/object:Api::Type::String
name: 'additionalAuthenticatedData'
description: |
The additional authenticated data used for integrity checks during encryption and decryption.
- !ruby/object:Api::Type::String
name: 'ciphertext'
description: |
Expand Down
4 changes: 4 additions & 0 deletions products/kms/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ overrides: !ruby/object:Overrides::ResourceOverrides
ignore_read: true
sensitive: true
custom_expand: templates/terraform/custom_expand/base64.go.erb
additionalAuthenticatedData: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
sensitive: true
custom_expand: templates/terraform/custom_expand/base64.go.erb
ciphertext: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func dataSourceGoogleKmsSecret() *schema.Resource {
Computed: true,
Sensitive: true,
},
"additional_authenticated_data": {
Type: schema.TypeString,
Optional: true,
},
},
}
}
Expand All @@ -46,6 +50,10 @@ func dataSourceGoogleKmsSecretRead(d *schema.ResourceData, meta interface{}) err
Ciphertext: ciphertext,
}

if aad, ok := d.GetOk("additional_authenticated_data"); ok {
kmsDecryptRequest.AdditionalAuthenticatedData = aad.(string)
}

decryptResponse, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Decrypt(cryptoKeyId.cryptoKeyId(), kmsDecryptRequest).Do()

if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestAccDataKmsSecretCiphertext_basic(t *testing.T) {
{
Config: testGoogleKmsSecretCiphertext_datasource(kms.CryptoKey.Name, plaintext),
Check: func(s *terraform.State) error {
plaintext, err := testAccDecryptSecretDataWithCryptoKey(s, kms.CryptoKey.Name, "data.google_kms_secret_ciphertext.acceptance")
plaintext, err := testAccDecryptSecretDataWithCryptoKey(s, kms.CryptoKey.Name, "data.google_kms_secret_ciphertext.acceptance", "")

if err != nil {
return err
Expand Down
44 changes: 42 additions & 2 deletions third_party/terraform/tests/data_source_google_kms_secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestAccKmsSecret_basic(t *testing.T) {
cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))

plaintext := fmt.Sprintf("secret-%s", acctest.RandString(10))
aad := "plainaad"

// The first test creates resources needed to encrypt plaintext and produce ciphertext
resource.Test(t, resource.TestCase{
Expand All @@ -32,7 +33,7 @@ func TestAccKmsSecret_basic(t *testing.T) {
{
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)
ciphertext, cryptoKeyId, err := testAccEncryptSecretDataWithCryptoKey(s, "google_kms_crypto_key.crypto_key", plaintext, "")

if err != nil {
return err
Expand All @@ -50,14 +51,39 @@ func TestAccKmsSecret_basic(t *testing.T) {
},
})

return nil
},
},
// With AAD
{
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, aad)

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{
{
Config: testGoogleKmsSecret_aadDatasource(cryptoKeyId.terraformId(), ciphertext, base64.StdEncoding.EncodeToString([]byte(aad))),
Check: resource.TestCheckResourceAttr("data.google_kms_secret.acceptance", "plaintext", plaintext),
},
},
})

return nil
},
},
},
})
}

func testAccEncryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyResourceName, plaintext string) (string, *kmsCryptoKeyId, error) {
func testAccEncryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyResourceName, plaintext, aad string) (string, *kmsCryptoKeyId, error) {
config := testAccProvider.Meta().(*Config)

rs, ok := s.RootModule().Resources[cryptoKeyResourceName]
Expand All @@ -75,6 +101,10 @@ func testAccEncryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyResource
Plaintext: base64.StdEncoding.EncodeToString([]byte(plaintext)),
}

if aad != "" {
kmsEncryptRequest.AdditionalAuthenticatedData = base64.StdEncoding.EncodeToString([]byte(aad))
}

encryptResponse, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Encrypt(cryptoKeyId.cryptoKeyId(), kmsEncryptRequest).Do()

if err != nil {
Expand All @@ -94,3 +124,13 @@ data "google_kms_secret" "acceptance" {
}
`, cryptoKeyTerraformId, ciphertext)
}

func testGoogleKmsSecret_aadDatasource(cryptoKeyTerraformId, ciphertext, aad string) string {
return fmt.Sprintf(`
data "google_kms_secret" "acceptance" {
crypto_key = "%s"
ciphertext = "%s"
additional_authenticated_data = "%s"
}
`, cryptoKeyTerraformId, ciphertext, aad)
}
32 changes: 30 additions & 2 deletions third_party/terraform/tests/resource_kms_secret_ciphertext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func TestAccKmsSecretCiphertext_basic(t *testing.T) {
kms := BootstrapKMSKey(t)

plaintext := fmt.Sprintf("secret-%s", acctest.RandString(10))
aad := "plainaad"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand All @@ -26,7 +27,20 @@ func TestAccKmsSecretCiphertext_basic(t *testing.T) {
{
Config: testGoogleKmsSecretCiphertext(kms.CryptoKey.Name, plaintext),
Check: func(s *terraform.State) error {
plaintext, err := testAccDecryptSecretDataWithCryptoKey(s, kms.CryptoKey.Name, "google_kms_secret_ciphertext.acceptance")
plaintext, err := testAccDecryptSecretDataWithCryptoKey(s, kms.CryptoKey.Name, "google_kms_secret_ciphertext.acceptance", "")

if err != nil {
return err
}

return resource.TestCheckResourceAttr("google_kms_secret_ciphertext.acceptance", "plaintext", plaintext)(s)
},
},
// With AAD
{
Config: testGoogleKmsSecretCiphertext_withAAD(kms.CryptoKey.Name, plaintext, aad),
Check: func(s *terraform.State) error {
plaintext, err := testAccDecryptSecretDataWithCryptoKey(s, kms.CryptoKey.Name, "google_kms_secret_ciphertext.acceptance", aad)

if err != nil {
return err
Expand All @@ -39,7 +53,7 @@ func TestAccKmsSecretCiphertext_basic(t *testing.T) {
})
}

func testAccDecryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyId string, secretCiphertextResourceName string) (string, error) {
func testAccDecryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyId string, secretCiphertextResourceName, aad string) (string, error) {
config := testAccProvider.Meta().(*Config)
rs, ok := s.RootModule().Resources[secretCiphertextResourceName]
if !ok {
Expand All @@ -54,6 +68,10 @@ func testAccDecryptSecretDataWithCryptoKey(s *terraform.State, cryptoKeyId strin
Ciphertext: ciphertext,
}

if aad != "" {
kmsDecryptRequest.AdditionalAuthenticatedData = base64.StdEncoding.EncodeToString([]byte(aad))
}

decryptResponse, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Decrypt(cryptoKeyId, kmsDecryptRequest).Do()

if err != nil {
Expand All @@ -80,3 +98,13 @@ resource "google_kms_secret_ciphertext" "acceptance" {
}
`, cryptoKeyTerraformId, plaintext)
}

func testGoogleKmsSecretCiphertext_withAAD(cryptoKeyTerraformId, plaintext, aad string) string {
return fmt.Sprintf(`
resource "google_kms_secret_ciphertext" "acceptance" {
crypto_key = "%s"
plaintext = "%s"
additional_authenticated_data = "%s"
}
`, cryptoKeyTerraformId, plaintext, aad)
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ The following arguments are supported:
* `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}`.
* `additional_authenticated_data` (Optional) - The [additional authenticated data](https://cloud.google.com/kms/docs/additional-authenticated-data) used for integrity checks during encryption and decryption.

## Attributes Reference

Expand Down

0 comments on commit 54c8b06

Please sign in to comment.