diff --git a/google-beta/services/secretmanager/iam_secret_manager_secret.go b/google-beta/services/secretmanager/iam_secret_manager_secret.go index 4bc601bfe2..f0b58d4bb9 100644 --- a/google-beta/services/secretmanager/iam_secret_manager_secret.go +++ b/google-beta/services/secretmanager/iam_secret_manager_secret.go @@ -133,6 +133,10 @@ func (u *SecretManagerSecretIamUpdater) GetResourceIamPolicy() (*cloudresourcema return nil, err } var obj map[string]interface{} + url, err = transport_tpg.AddQueryParams(url, map[string]string{"options.requestedPolicyVersion": fmt.Sprintf("%d", tpgiamresource.IamPolicyVersion)}) + if err != nil { + return nil, err + } userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) if err != nil { diff --git a/google-beta/services/secretmanager/iam_secret_manager_secret_generated_test.go b/google-beta/services/secretmanager/iam_secret_manager_secret_generated_test.go index d40e6e4e01..494d5d95b8 100644 --- a/google-beta/services/secretmanager/iam_secret_manager_secret_generated_test.go +++ b/google-beta/services/secretmanager/iam_secret_manager_secret_generated_test.go @@ -19,20 +19,27 @@ package secretmanager_test import ( "fmt" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" ) func TestAccSecretManagerSecretIamBindingGenerated(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "role": "roles/secretmanager.secretAccessor", + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, } acctest.VcrTest(t, resource.TestCase{ @@ -66,8 +73,13 @@ func TestAccSecretManagerSecretIamMemberGenerated(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "role": "roles/secretmanager.secretAccessor", + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, } acctest.VcrTest(t, resource.TestCase{ @@ -92,8 +104,13 @@ func TestAccSecretManagerSecretIamPolicyGenerated(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "role": "roles/secretmanager.secretAccessor", + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, } acctest.VcrTest(t, resource.TestCase{ @@ -123,6 +140,194 @@ func TestAccSecretManagerSecretIamPolicyGenerated(t *testing.T) { }) } +func TestAccSecretManagerSecretIamBindingGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIamBinding_withConditionGenerated(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecretManagerSecretIamBindingGenerated_withAndWithoutCondition(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIamBinding_withAndWithoutConditionGenerated(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_secret_manager_secret_iam_binding.foo2", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_secret_manager_secret_iam_binding.foo3", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title_no_desc"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecretManagerSecretIamMemberGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIamMember_withConditionGenerated(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecretManagerSecretIamMemberGenerated_withAndWithoutCondition(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIamMember_withAndWithoutConditionGenerated(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor user:admin@hashicorptest.com", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_secret_manager_secret_iam_member.foo2", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_secret_manager_secret_iam_member.foo3", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s roles/secretmanager.secretAccessor user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"]), context["condition_title_no_desc"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecretManagerSecretIamPolicyGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + // Test should have 2 bindings: one with a description and one without. Any < chars are converted to a unicode character by the API. + expectedPolicyData := acctest.Nprintf(`{"bindings":[{"condition":{"description":"%{condition_desc}","expression":"%{condition_expr}","title":"%{condition_title}"},"members":["user:admin@hashicorptest.com"],"role":"%{role}"},{"condition":{"expression":"%{condition_expr}","title":"%{condition_title}-no-description"},"members":["user:admin@hashicorptest.com"],"role":"%{role}"}]}`, context) + expectedPolicyData = strings.Replace(expectedPolicyData, "<", "\\u003c", -1) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIamPolicy_withConditionGenerated(context), + Check: resource.ComposeAggregateTestCheckFunc( + // TODO(SarahFrench) - uncomment once https://github.com/GoogleCloudPlatform/magic-modules/pull/6466 merged + // resource.TestCheckResourceAttr("data.google_iam_policy.foo", "policy_data", expectedPolicyData), + resource.TestCheckResourceAttr("google_secret_manager_secret_iam_policy.foo", "policy_data", expectedPolicyData), + resource.TestCheckResourceAttrWith("data.google_iam_policy.foo", "policy_data", tpgresource.CheckGoogleIamPolicy), + ), + }, + { + ResourceName: "google_secret_manager_secret_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("secret%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccSecretManagerSecretIamMember_basicGenerated(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_secret_manager_secret" "secret-basic" { @@ -288,3 +493,234 @@ resource "google_secret_manager_secret_iam_binding" "foo" { } `, context) } + +func testAccSecretManagerSecretIamBinding_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "secret%{random_suffix}" + + labels = { + label = "my-label" + } + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_binding" "foo" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} +`, context) +} + +func testAccSecretManagerSecretIamBinding_withAndWithoutConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "secret%{random_suffix}" + + labels = { + label = "my-label" + } + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_binding" "foo" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] +} + +resource "google_secret_manager_secret_iam_binding" "foo2" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} + +resource "google_secret_manager_secret_iam_binding" "foo3" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } +} +`, context) +} + +func testAccSecretManagerSecretIamMember_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "secret%{random_suffix}" + + labels = { + label = "my-label" + } + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_member" "foo" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} +`, context) +} + +func testAccSecretManagerSecretIamMember_withAndWithoutConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "secret%{random_suffix}" + + labels = { + label = "my-label" + } + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_member" "foo" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + member = "user:admin@hashicorptest.com" +} + +resource "google_secret_manager_secret_iam_member" "foo2" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} + +resource "google_secret_manager_secret_iam_member" "foo3" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } +} +`, context) +} + +func testAccSecretManagerSecretIamPolicy_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "secret%{random_suffix}" + + labels = { + label = "my-label" + } + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +data "google_iam_policy" "foo" { + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } + } + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } + } +} + +resource "google_secret_manager_secret_iam_policy" "foo" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} diff --git a/google-beta/services/secretmanager/iam_secret_manager_secret_test.go b/google-beta/services/secretmanager/iam_secret_manager_secret_test.go new file mode 100644 index 0000000000..59d05d6b0c --- /dev/null +++ b/google-beta/services/secretmanager/iam_secret_manager_secret_test.go @@ -0,0 +1,120 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package secretmanager_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" +) + +func TestAccSecretManagerSecretIam_iamMemberConditionUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/secretmanager.secretAccessor", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecretIam_iamMemberCondition_basic(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_member.default", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s %s serviceAccount:%s %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("tf-test-secret-%s", context["random_suffix"]), context["role"], fmt.Sprintf("tf-test-sa-%s@%s.iam.gserviceaccount.com", context["random_suffix"], envvar.GetTestProjectFromEnv()), fmt.Sprintf("tf-test-condition-%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccSecretManagerSecretIam_iamMemberCondition_update(context), + }, + { + ResourceName: "google_secret_manager_secret_iam_member.default", + ImportStateId: fmt.Sprintf("projects/%s/secrets/%s %s serviceAccount:%s %s", envvar.GetTestProjectFromEnv(), fmt.Sprintf("tf-test-secret-%s", context["random_suffix"]), context["role"], fmt.Sprintf("tf-test-sa-%s@%s.iam.gserviceaccount.com", context["random_suffix"], envvar.GetTestProjectFromEnv()), fmt.Sprintf("tf-test-condition-new-%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccSecretManagerSecretIam_iamMemberCondition_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_service_account" "default" { + account_id = "tf-test-sa-%{random_suffix}" + display_name = "Secret manager IAM testing account" +} + +resource "google_secret_manager_secret" "default" { + secret_id = "tf-test-secret-%{random_suffix}" + ttl = "3600s" + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_member" "default" { + secret_id = google_secret_manager_secret.default.id + role = "%{role}" + member = "serviceAccount:${google_service_account.default.email}" + condition { + title = "tf-test-condition-%{random_suffix}" + description = "test condition" + expression = "request.time < timestamp(\"2022-03-01T00:00:00Z\")" + } +} +`, context) +} + +func testAccSecretManagerSecretIam_iamMemberCondition_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_service_account" "default" { + account_id = "tf-test-sa-%{random_suffix}" + display_name = "Secret manager IAM testing account" +} + +resource "google_secret_manager_secret" "default" { + secret_id = "tf-test-secret-%{random_suffix}" + ttl = "3600s" + + replication { + user_managed { + replicas { + location = "us-central1" + } + replicas { + location = "us-east1" + } + } + } +} + +resource "google_secret_manager_secret_iam_member" "default" { + secret_id = google_secret_manager_secret.default.id + role = "%{role}" + member = "serviceAccount:${google_service_account.default.email}" + condition { + title = "tf-test-condition-new-%{random_suffix}" + description = "test new condition" + expression = "request.time < timestamp(\"2024-03-01T00:00:00Z\")" + } +} +`, context) +} diff --git a/website/docs/r/secret_manager_secret_iam.html.markdown b/website/docs/r/secret_manager_secret_iam.html.markdown index 52ea09c61c..1f9b2b89ce 100644 --- a/website/docs/r/secret_manager_secret_iam.html.markdown +++ b/website/docs/r/secret_manager_secret_iam.html.markdown @@ -32,6 +32,7 @@ A data source can be used to retrieve policy data in advent you do not need crea ~> **Note:** `google_secret_manager_secret_iam_binding` resources **can be** used in conjunction with `google_secret_manager_secret_iam_member` resources **only if** they do not grant privilege to the same role. +~> **Note:** This resource supports IAM Conditions but they have some known limitations which can be found [here](https://cloud.google.com/iam/docs/conditions-overview#limitations). Please review this article if you are having issues with IAM Conditions. ## google_secret_manager_secret_iam_policy @@ -53,6 +54,30 @@ resource "google_secret_manager_secret_iam_policy" "policy" { } ``` +With IAM Conditions: + +```hcl +data "google_iam_policy" "admin" { + binding { + role = "roles/secretmanager.secretAccessor" + 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_secret_manager_secret_iam_policy" "policy" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + policy_data = data.google_iam_policy.admin.policy_data +} +``` ## google_secret_manager_secret_iam_binding ```hcl @@ -66,6 +91,24 @@ resource "google_secret_manager_secret_iam_binding" "binding" { } ``` +With IAM Conditions: + +```hcl +resource "google_secret_manager_secret_iam_binding" "binding" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "roles/secretmanager.secretAccessor" + 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_secret_manager_secret_iam_member ```hcl @@ -77,6 +120,22 @@ resource "google_secret_manager_secret_iam_member" "member" { } ``` +With IAM Conditions: + +```hcl +resource "google_secret_manager_secret_iam_member" "member" { + project = google_secret_manager_secret.secret-basic.project + secret_id = google_secret_manager_secret.secret-basic.secret_id + role = "roles/secretmanager.secretAccessor" + 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 @@ -105,6 +164,22 @@ The following arguments are supported: * `policy_data` - (Required only by `google_secret_manager_secret_iam_policy`) The policy data generated by a `google_iam_policy` data source. +* `condition` - (Optional) 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