From edee0ced88155229fb9d412f3f40d293613efd38 Mon Sep 17 00:00:00 2001 From: Dana Hoffman Date: Tue, 17 Dec 2019 21:55:32 +0000 Subject: [PATCH] add conditions to kms iam Signed-off-by: Modular Magician --- google-beta/iam_kms_crypto_key.go | 2 +- google-beta/iam_kms_key_ring.go | 2 +- google-beta/resource_iam_policy.go | 1 + .../resource_kms_crypto_key_iam_test.go | 166 ++++++++++++ google-beta/resource_kms_key_ring_iam_test.go | 241 ++++++++++++++++++ ...e_kms_crypto_key_iam_binding.html.markdown | 72 +++++- ...le_kms_crypto_key_iam_member.html.markdown | 70 ++++- .../r/google_kms_key_ring_iam.html.markdown | 92 ++++++- 8 files changed, 639 insertions(+), 7 deletions(-) diff --git a/google-beta/iam_kms_crypto_key.go b/google-beta/iam_kms_crypto_key.go index d52e3e4118..0fe37cfd39 100644 --- a/google-beta/iam_kms_crypto_key.go +++ b/google-beta/iam_kms_crypto_key.go @@ -47,7 +47,7 @@ func CryptoIdParseFunc(d *schema.ResourceData, config *Config) error { } func (u *KmsCryptoKeyIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { - p, err := u.Config.clientKms.Projects.Locations.KeyRings.CryptoKeys.GetIamPolicy(u.resourceId).Do() + p, err := u.Config.clientKms.Projects.Locations.KeyRings.CryptoKeys.GetIamPolicy(u.resourceId).OptionsRequestedPolicyVersion(iamPolicyVersion).Do() if err != nil { return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err) diff --git a/google-beta/iam_kms_key_ring.go b/google-beta/iam_kms_key_ring.go index 795dd28ca4..2da459be9d 100644 --- a/google-beta/iam_kms_key_ring.go +++ b/google-beta/iam_kms_key_ring.go @@ -48,7 +48,7 @@ func KeyRingIdParseFunc(d *schema.ResourceData, config *Config) error { } func (u *KmsKeyRingIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { - p, err := u.Config.clientKms.Projects.Locations.KeyRings.GetIamPolicy(u.resourceId).Do() + p, err := u.Config.clientKms.Projects.Locations.KeyRings.GetIamPolicy(u.resourceId).OptionsRequestedPolicyVersion(iamPolicyVersion).Do() if err != nil { return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err) diff --git a/google-beta/resource_iam_policy.go b/google-beta/resource_iam_policy.go index b4c0869f02..e0ceb6beea 100644 --- a/google-beta/resource_iam_policy.go +++ b/google-beta/resource_iam_policy.go @@ -119,6 +119,7 @@ func ResourceIamPolicyDelete(newUpdaterFunc newResourceIamUpdaterFunc) schema.De if v, ok := d.GetOk("etag"); ok { pol.Etag = v.(string) } + pol.Version = iamPolicyVersion err = updater.SetResourceIamPolicy(pol) if err != nil { return err diff --git a/google-beta/resource_kms_crypto_key_iam_test.go b/google-beta/resource_kms_crypto_key_iam_test.go index dcfbf9724a..50d203aad9 100644 --- a/google-beta/resource_kms_crypto_key_iam_test.go +++ b/google-beta/resource_kms_crypto_key_iam_test.go @@ -62,6 +62,40 @@ func TestAccKmsCryptoKeyIamBinding(t *testing.T) { }) } +func TestAccKmsCryptoKeyIamBinding_withCondition(t *testing.T) { + t.Parallel() + + orgId := getTestOrgFromEnv(t) + projectId := acctest.RandomWithPrefix("tf-test") + billingAccount := getTestBillingAccountFromEnv(t) + account := acctest.RandomWithPrefix("tf-test") + roleId := "roles/cloudkms.cryptoKeyDecrypter" + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + keyRingId := &kmsKeyRingId{ + Project: projectId, + Location: DEFAULT_KMS_TEST_LOCATION, + Name: keyRingName, + } + cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + conditionTitle := "expires_after_2019_12_31" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKmsCryptoKeyIamBinding_withCondition(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle), + }, + { + ResourceName: "google_kms_crypto_key_iam_binding.foo", + ImportStateId: fmt.Sprintf("%s/%s %s %s", keyRingId.terraformId(), cryptoKeyName, roleId, conditionTitle), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccKmsCryptoKeyIamMember(t *testing.T) { t.Parallel() @@ -99,6 +133,40 @@ func TestAccKmsCryptoKeyIamMember(t *testing.T) { }) } +func TestAccKmsCryptoKeyIamMember_withCondition(t *testing.T) { + t.Parallel() + + orgId := getTestOrgFromEnv(t) + projectId := acctest.RandomWithPrefix("tf-test") + billingAccount := getTestBillingAccountFromEnv(t) + account := acctest.RandomWithPrefix("tf-test") + roleId := "roles/cloudkms.cryptoKeyEncrypter" + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + keyRingId := &kmsKeyRingId{ + Project: projectId, + Location: DEFAULT_KMS_TEST_LOCATION, + Name: keyRingName, + } + cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + conditionTitle := "expires_after_2019_12_31" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKmsCryptoKeyIamMember_withCondition(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle), + }, + { + ResourceName: "google_kms_crypto_key_iam_member.foo", + ImportStateId: fmt.Sprintf("%s/%s %s serviceAccount:%s@%s.iam.gserviceaccount.com %s", keyRingId.terraformId(), cryptoKeyName, roleId, account, projectId, conditionTitle), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckGoogleKmsCryptoKeyIamBindingExists(bindingResourceName, roleId string, members []string) resource.TestCheckFunc { return func(s *terraform.State) error { bindingRs, ok := s.RootModule().Resources[fmt.Sprintf("google_kms_crypto_key_iam_binding.%s", bindingResourceName)] @@ -269,6 +337,55 @@ resource "google_kms_crypto_key_iam_binding" "foo" { `, projectId, orgId, billingAccount, account, account, keyRingName, cryptoKeyName, roleId) } +func testAccKmsCryptoKeyIamBinding_withCondition(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle string) string { + return fmt.Sprintf(` +resource "google_project" "test_project" { + name = "Test project" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "kms" { + project = google_project.test_project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_project_service" "iam" { + project = google_project_service.kms.project + service = "iam.googleapis.com" +} + +resource "google_service_account" "test_account" { + project = google_project_service.iam.project + account_id = "%s" + display_name = "Kms Crypto Key Iam Testing Account" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.iam.project + location = "us-central1" + name = "%s" +} + +resource "google_kms_crypto_key" "crypto_key" { + key_ring = google_kms_key_ring.key_ring.id + name = "%s" +} + +resource "google_kms_crypto_key_iam_binding" "foo" { + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "%s" + members = ["serviceAccount:${google_service_account.test_account.email}"] + condition { + title = "%s" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +`, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle) +} + func testAccKmsCryptoKeyIamMember_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId string) string { return fmt.Sprintf(` resource "google_project" "test_project" { @@ -312,3 +429,52 @@ resource "google_kms_crypto_key_iam_member" "foo" { } `, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId) } + +func testAccKmsCryptoKeyIamMember_withCondition(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle string) string { + return fmt.Sprintf(` +resource "google_project" "test_project" { + name = "Test project" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "kms" { + project = google_project.test_project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_project_service" "iam" { + project = google_project_service.kms.project + service = "iam.googleapis.com" +} + +resource "google_service_account" "test_account" { + project = google_project_service.iam.project + account_id = "%s" + display_name = "Kms Crypto Key Iam Testing Account" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.iam.project + location = "us-central1" + name = "%s" +} + +resource "google_kms_crypto_key" "crypto_key" { + key_ring = google_kms_key_ring.key_ring.id + name = "%s" +} + +resource "google_kms_crypto_key_iam_member" "foo" { + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "%s" + member = "serviceAccount:${google_service_account.test_account.email}" + condition { + title = "%s" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +`, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle) +} diff --git a/google-beta/resource_kms_key_ring_iam_test.go b/google-beta/resource_kms_key_ring_iam_test.go index e80add2c08..14c1257b87 100644 --- a/google-beta/resource_kms_key_ring_iam_test.go +++ b/google-beta/resource_kms_key_ring_iam_test.go @@ -64,6 +64,40 @@ func TestAccKmsKeyRingIamBinding(t *testing.T) { }) } +func TestAccKmsKeyRingIamBinding_withCondition(t *testing.T) { + t.Parallel() + + orgId := getTestOrgFromEnv(t) + projectId := acctest.RandomWithPrefix("tf-test") + billingAccount := getTestBillingAccountFromEnv(t) + account := acctest.RandomWithPrefix("tf-test") + roleId := "roles/cloudkms.cryptoKeyDecrypter" + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + conditionTitle := "expires_after_2019_12_31" + + keyRingId := &kmsKeyRingId{ + Project: projectId, + Location: DEFAULT_KMS_TEST_LOCATION, + Name: keyRingName, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKmsKeyRingIamBinding_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle), + }, + { + ResourceName: "google_kms_key_ring_iam_binding.foo", + ImportStateId: fmt.Sprintf("%s %s %s", keyRingId.terraformId(), roleId, conditionTitle), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccKmsKeyRingIamMember(t *testing.T) { t.Parallel() @@ -101,6 +135,40 @@ func TestAccKmsKeyRingIamMember(t *testing.T) { }) } +func TestAccKmsKeyRingIamMember_withCondition(t *testing.T) { + t.Parallel() + + orgId := getTestOrgFromEnv(t) + projectId := acctest.RandomWithPrefix("tf-test") + billingAccount := getTestBillingAccountFromEnv(t) + account := acctest.RandomWithPrefix("tf-test") + roleId := "roles/cloudkms.cryptoKeyEncrypter" + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + conditionTitle := "expires_after_2019_12_31" + + keyRingId := &kmsKeyRingId{ + Project: projectId, + Location: DEFAULT_KMS_TEST_LOCATION, + Name: keyRingName, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKmsKeyRingIamMember_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle), + }, + { + ResourceName: "google_kms_key_ring_iam_member.foo", + ImportStateId: fmt.Sprintf("%s %s serviceAccount:%s@%s.iam.gserviceaccount.com %s", keyRingId.terraformId(), roleId, account, projectId, conditionTitle), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccKmsKeyRingIamPolicy(t *testing.T) { t.Parallel() @@ -137,6 +205,40 @@ func TestAccKmsKeyRingIamPolicy(t *testing.T) { }) } +func TestAccKmsKeyRingIamPolicy_withCondition(t *testing.T) { + t.Parallel() + + orgId := getTestOrgFromEnv(t) + projectId := acctest.RandomWithPrefix("tf-test") + billingAccount := getTestBillingAccountFromEnv(t) + account := acctest.RandomWithPrefix("tf-test") + roleId := "roles/cloudkms.cryptoKeyEncrypter" + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + conditionTitle := "expires_after_2019_12_31" + + keyRingId := &kmsKeyRingId{ + Project: projectId, + Location: DEFAULT_KMS_TEST_LOCATION, + Name: keyRingName, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKmsKeyRingIamPolicy_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle), + }, + { + ResourceName: "google_kms_key_ring_iam_policy.foo", + ImportStateId: keyRingId.terraformId(), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckGoogleKmsKeyRingIam(keyRingId, role string, members []string) resource.TestCheckFunc { return func(s *terraform.State) error { config := testAccProvider.Meta().(*Config) @@ -251,6 +353,50 @@ resource "google_kms_key_ring_iam_binding" "foo" { `, projectId, orgId, billingAccount, account, account, DEFAULT_KMS_TEST_LOCATION, keyRingName, roleId) } +func testAccKmsKeyRingIamBinding_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle string) string { + return fmt.Sprintf(` +resource "google_project" "test_project" { + name = "Test project" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "kms" { + project = google_project.test_project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_project_service" "iam" { + project = google_project_service.kms.project + service = "iam.googleapis.com" +} + +resource "google_service_account" "test_account" { + project = google_project_service.iam.project + account_id = "%s" + display_name = "Kms Key Ring Iam Testing Account" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.iam.project + location = "us-central1" + name = "%s" +} + +resource "google_kms_key_ring_iam_binding" "foo" { + key_ring_id = google_kms_key_ring.key_ring.id + role = "%s" + members = ["serviceAccount:${google_service_account.test_account.email}"] + condition { + title = "%s" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +`, projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle) +} + func testAccKmsKeyRingIamMember_basic(projectId, orgId, billingAccount, account, keyRingName, roleId string) string { return fmt.Sprintf(` resource "google_project" "test_project" { @@ -290,6 +436,50 @@ resource "google_kms_key_ring_iam_member" "foo" { `, projectId, orgId, billingAccount, account, DEFAULT_KMS_TEST_LOCATION, keyRingName, roleId) } +func testAccKmsKeyRingIamMember_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle string) string { + return fmt.Sprintf(` +resource "google_project" "test_project" { + name = "Test project" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "kms" { + project = google_project.test_project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_project_service" "iam" { + project = google_project_service.kms.project + service = "iam.googleapis.com" +} + +resource "google_service_account" "test_account" { + project = google_project_service.iam.project + account_id = "%s" + display_name = "Kms Key Ring Iam Testing Account" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.iam.project + location = "%s" + name = "%s" +} + +resource "google_kms_key_ring_iam_member" "foo" { + key_ring_id = google_kms_key_ring.key_ring.id + role = "%s" + member = "serviceAccount:${google_service_account.test_account.email}" + condition { + title = "%s" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +`, projectId, orgId, billingAccount, account, DEFAULT_KMS_TEST_LOCATION, keyRingName, roleId, conditionTitle) +} + func testAccKmsKeyRingIamPolicy_basic(projectId, orgId, billingAccount, account, keyRingName, roleId string) string { return fmt.Sprintf(` resource "google_project" "test_project" { @@ -335,3 +525,54 @@ resource "google_kms_key_ring_iam_policy" "foo" { } `, projectId, orgId, billingAccount, account, DEFAULT_KMS_TEST_LOCATION, keyRingName, roleId) } + +func testAccKmsKeyRingIamPolicy_withCondition(projectId, orgId, billingAccount, account, keyRingName, roleId, conditionTitle string) string { + return fmt.Sprintf(` +resource "google_project" "test_project" { + name = "Test project" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "kms" { + project = google_project.test_project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_project_service" "iam" { + project = google_project_service.kms.project + service = "iam.googleapis.com" +} + +resource "google_service_account" "test_account" { + project = google_project_service.iam.project + account_id = "%s" + display_name = "Kms Key Ring Iam Testing Account" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.iam.project + location = "%s" + name = "%s" +} + +data "google_iam_policy" "foo" { + binding { + role = "%s" + + members = ["serviceAccount:${google_service_account.test_account.email}"] + condition { + title = "%s" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } + } +} + +resource "google_kms_key_ring_iam_policy" "foo" { + key_ring_id = google_kms_key_ring.key_ring.id + policy_data = data.google_iam_policy.foo.policy_data +} +`, projectId, orgId, billingAccount, account, DEFAULT_KMS_TEST_LOCATION, keyRingName, roleId, conditionTitle) +} diff --git a/website/docs/r/google_kms_crypto_key_iam_binding.html.markdown b/website/docs/r/google_kms_crypto_key_iam_binding.html.markdown index 5d5ebf4635..23b020300a 100644 --- a/website/docs/r/google_kms_crypto_key_iam_binding.html.markdown +++ b/website/docs/r/google_kms_crypto_key_iam_binding.html.markdown @@ -19,9 +19,24 @@ an existing Google Cloud KMS crypto key. ## Example Usage ```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + +resource "google_kms_crypto_key" "key" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "100000s" + + lifecycle { + prevent_destroy = true + } +} + resource "google_kms_crypto_key_iam_binding" "crypto_key" { - crypto_key_id = "my-gcp-project/us-central1/my-key-ring/my-crypto-key" - role = "roles/editor" + crypto_key_id = "google_kms_crypto_key.key.id" + role = "roles/cloudkms.cryptoKeyEncrypter" members = [ "user:alice@gmail.com", @@ -29,6 +44,39 @@ resource "google_kms_crypto_key_iam_binding" "crypto_key" { } ``` +With IAM Conditions ([beta](https://terraform.io/docs/providers/google/provider_versions.html)): +```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + +resource "google_kms_crypto_key" "key" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "100000s" + + lifecycle { + prevent_destroy = true + } +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = "google_kms_crypto_key.key.id" + role = "roles/cloudkms.cryptoKeyEncrypter" + + members = [ + "user:alice@gmail.com", + ] + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -44,6 +92,23 @@ The following arguments are supported: `{location_name}/{key_ring_name}/{crypto_key_name}`. In the second form, the provider's project setting will be used as a fallback. +* `condition` - (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. + Structure is documented below. + +--- + +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +~> **Warning:** Terraform considers the `role` and condition contents (`title`+`description`+`expression`) as the + identifier for the binding. This means that if any part of the condition is changed out-of-band, Terraform will + consider it to be an entirely different resource and will treat it as such. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are @@ -58,3 +123,6 @@ IAM binding imports use space-delimited identifiers; first the resource in quest ``` $ terraform import google_kms_crypto_key_iam_binding.crypto_key "my-gcp-project/us-central1/my-key-ring/my-crypto-key roles/editor" ``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource. diff --git a/website/docs/r/google_kms_crypto_key_iam_member.html.markdown b/website/docs/r/google_kms_crypto_key_iam_member.html.markdown index 70889afd9e..5c9b1fb066 100644 --- a/website/docs/r/google_kms_crypto_key_iam_member.html.markdown +++ b/website/docs/r/google_kms_crypto_key_iam_member.html.markdown @@ -20,13 +20,58 @@ the IAM policy for an existing Google Cloud KMS crypto key. ## Example Usage ```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + +resource "google_kms_crypto_key" "key" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "100000s" + + lifecycle { + prevent_destroy = true + } +} + resource "google_kms_crypto_key_iam_member" "crypto_key" { - crypto_key_id = "your-crypto-key-id" - role = "roles/editor" + crypto_key_id = "google_kms_crypto_key.key.id" + role = "roles/cloudkms.cryptoKeyEncrypter" member = "user:alice@gmail.com" } ``` +With IAM Conditions ([beta](https://terraform.io/docs/providers/google/provider_versions.html)): +```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + +resource "google_kms_crypto_key" "key" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "100000s" + + lifecycle { + prevent_destroy = true + } +} + +resource "google_kms_crypto_key_iam_member" "crypto_key" { + crypto_key_id = "google_kms_crypto_key.key.id" + role = "roles/cloudkms.cryptoKeyEncrypter" + member = "user:alice@gmail.com" + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -41,6 +86,24 @@ The following arguments are supported: `{location_name}/{key_ring_name}/{crypto_key_name}`. In the second form, the provider's project setting will be used as a fallback. +* `condition` - (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. + Structure is documented below. + +--- + +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +~> **Warning:** Terraform considers the `role` and condition contents (`title`+`description`+`expression`) as the + identifier for the binding. This means that if any part of the condition is changed out-of-band, Terraform will + consider it to be an entirely different resource and will treat it as such. + + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are @@ -55,3 +118,6 @@ IAM member imports use space-delimited identifiers; the resource in question, th ``` $ terraform import google_kms_crypto_key_iam_member.member "your-project-id/location-name/key-ring-name/key-name roles/viewer user:foo@example.com" ``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource. diff --git a/website/docs/r/google_kms_key_ring_iam.html.markdown b/website/docs/r/google_kms_key_ring_iam.html.markdown index b06a0bb48c..030fa6b8a0 100644 --- a/website/docs/r/google_kms_key_ring_iam.html.markdown +++ b/website/docs/r/google_kms_key_ring_iam.html.markdown @@ -22,6 +22,11 @@ Three different resources help you manage your IAM policy for KMS key ring. Each ## google\_kms\_key\_ring\_iam\_policy ```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + data "google_iam_policy" "admin" { binding { role = "roles/editor" @@ -33,7 +38,37 @@ data "google_iam_policy" "admin" { } resource "google_kms_key_ring_iam_policy" "key_ring" { - key_ring_id = "your-key-ring-id" + key_ring_id = google_kms_key_ring.keyring.id + policy_data = data.google_iam_policy.admin.policy_data +} +``` + +With IAM Conditions ([beta](https://terraform.io/docs/providers/google/provider_versions.html)): + +```hcl +resource "google_kms_key_ring" "keyring" { + name = "keyring-example" + location = "global" +} + +data "google_iam_policy" "admin" { + binding { + role = "roles/editor" + + members = [ + "user:jane@example.com", + ] + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } + } +} + +resource "google_kms_key_ring_iam_policy" "key_ring" { + key_ring_id = google_kms_key_ring.keyring.id policy_data = data.google_iam_policy.admin.policy_data } ``` @@ -51,6 +86,25 @@ resource "google_kms_key_ring_iam_binding" "key_ring" { } ``` +With IAM Conditions ([beta](https://terraform.io/docs/providers/google/provider_versions.html)): + +```hcl +resource "google_kms_key_ring_iam_binding" "key_ring" { + key_ring_id = "your-key-ring-id" + role = "roles/editor" + + members = [ + "user:jane@example.com", + ] + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` + ## google\_kms\_key\_ring\_iam\_member ```hcl @@ -61,6 +115,22 @@ resource "google_kms_key_ring_iam_member" "key_ring" { } ``` +With IAM Conditions ([beta](https://terraform.io/docs/providers/google/provider_versions.html)): + +```hcl +resource "google_kms_key_ring_iam_member" "key_ring" { + key_ring_id = "your-key-ring-id" + role = "roles/editor" + member = "user:jane@example.com" + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -86,6 +156,23 @@ The following arguments are supported: * `policy_data` - (Required only by `google_kms_key_ring_iam_policy`) The policy data generated by a `google_iam_policy` data source. +* `condition` - (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. + Structure is documented below. + +--- + +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +~> **Warning:** Terraform considers the `role` and condition contents (`title`+`description`+`expression`) as the + identifier for the binding. This means that if any part of the condition is changed out-of-band, Terraform will + consider it to be an entirely different resource and will treat it as such. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are @@ -112,3 +199,6 @@ IAM policy imports use the identifier of the resource in question. This policy ``` $ terraform import google_kms_key_ring_iam_policy.key_ring_iam your-project-id/location-name/key-ring-name ``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource.