Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional Authenticated Data AAD for Cloud KMS secrets #3271

Merged
merged 4 commits into from
Mar 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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