Skip to content

Commit

Permalink
Add authoritative IAM policy binding for KMS Crypto Keys (#2879)
Browse files Browse the repository at this point in the history
Merged PR #2879.
  • Loading branch information
danawillow authored and modular-magician committed Dec 20, 2019
1 parent dcc8300 commit 9c8d732
Show file tree
Hide file tree
Showing 10 changed files with 429 additions and 259 deletions.
2 changes: 1 addition & 1 deletion build/terraform
2 changes: 1 addition & 1 deletion build/terraform-beta
219 changes: 219 additions & 0 deletions third_party/terraform/tests/resource_kms_crypto_key_iam_test.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,80 @@ func TestAccKmsCryptoKeyIamMember_withCondition(t *testing.T) {
}
<% end -%>

func TestAccKmsCryptoKeyIamPolicy(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))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccKmsCryptoKeyIamPolicy_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId),
Check: testAccCheckGoogleCryptoKmsKeyIam("foo", roleId, []string{
fmt.Sprintf("serviceAccount:%s@%s.iam.gserviceaccount.com", account, projectId),
}),
},
{
ResourceName: "google_kms_crypto_key_iam_policy.foo",
ImportStateId: fmt.Sprintf("%s/%s", keyRingId.terraformId(), cryptoKeyName),
ImportState: true,
ImportStateVerify: true,
},
},
})
}

<% unless version == 'ga' -%>
func TestAccKmsCryptoKeyIamPolicy_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: testAccKmsCryptoKeyIamPolicy_withCondition(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle),
},
{
ResourceName: "google_kms_crypto_key_iam_policy.foo",
ImportStateId: fmt.Sprintf("%s/%s", keyRingId.terraformId(), cryptoKeyName),
ImportState: true,
ImportStateVerify: true,
},
},
})
}
<% end -%>

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)]
Expand Down Expand Up @@ -243,6 +317,44 @@ func testAccCheckGoogleKmsCryptoKeyIamMemberExists(n, role, member string) resou
}
}

func testAccCheckGoogleCryptoKmsKeyIam(n, role string, members []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources["google_kms_crypto_key_iam_policy."+n]
if !ok {
return fmt.Errorf("IAM policy resource not found")
}

config := testAccProvider.Meta().(*Config)
cryptoKeyId, err := parseKmsCryptoKeyId(rs.Primary.Attributes["crypto_key_id"], config)

if err != nil {
return err
}

p, err := config.clientKms.Projects.Locations.KeyRings.GetIamPolicy(cryptoKeyId.cryptoKeyId()).Do()
if err != nil {
return err
}

for _, binding := range p.Bindings {
if binding.Role == role {
sort.Strings(members)
sort.Strings(binding.Members)

if reflect.DeepEqual(members, binding.Members) {
return nil
}

return fmt.Errorf("Binding found but expected members is %v, got %v", members, binding.Members)
} else {
return fmt.Errorf("Binding found but not expected for role: %v", binding.Role)
}
}

return fmt.Errorf("No binding for role %q", role)
}
}

// We are using a custom role since iam_binding is authoritative on the member list and
// we want to avoid removing members from an existing role to prevent unwanted side effects.
func testAccKmsCryptoKeyIamBinding_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId string) string {
Expand Down Expand Up @@ -487,3 +599,110 @@ resource "google_kms_crypto_key_iam_member" "foo" {
`, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle)
}
<% end -%>

func testAccKmsCryptoKeyIamPolicy_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId 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"
}

data "google_iam_policy" "foo" {
binding {
role = "%s"
members = ["serviceAccount:${google_service_account.test_account.email}"]
}
}

resource "google_kms_crypto_key_iam_policy" "foo" {
crypto_key_id = google_kms_crypto_key.crypto_key.id
policy_data = data.google_iam_policy.foo.policy_data
}
`, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId)
}

<% unless version == 'ga' -%>
func testAccKmsCryptoKeyIamPolicy_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"
}

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_crypto_key_iam_policy" "foo" {
crypto_key_id = google_kms_crypto_key.crypto_key.id
policy_data = data.google_iam_policy.foo.policy_data
}
`, projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId, conditionTitle)
}
<% end -%>
1 change: 1 addition & 0 deletions third_party/terraform/utils/provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ end # products.each do
"google_kms_key_ring_iam_policy": ResourceIamPolicy(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_kms_crypto_key_iam_binding": ResourceIamBinding(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_kms_crypto_key_iam_member": ResourceIamMember(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_kms_crypto_key_iam_policy": ResourceIamPolicy(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_service_networking_connection": resourceServiceNetworkingConnection(),
"google_spanner_instance_iam_binding": ResourceIamBinding(IamSpannerInstanceSchema, NewSpannerInstanceIamUpdater, SpannerInstanceIdParseFunc),
"google_spanner_instance_iam_member": ResourceIamMember(IamSpannerInstanceSchema, NewSpannerInstanceIamUpdater, SpannerInstanceIdParseFunc),
Expand Down
11 changes: 7 additions & 4 deletions third_party/terraform/website-compiled/google.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1003,11 +1003,14 @@
<li<%%= sidebar_current("docs-google-kms-crypto-key-x") %>>
<a href="/docs/providers/google/r/kms_crypto_key.html">google_kms_crypto_key</a>
</li>
<li<%%= sidebar_current("docs-google-kms-crypto-key-iam-binding") %>>
<a href="/docs/providers/google/r/google_kms_crypto_key_iam_binding.html">google_kms_crypto_key_iam_binding</a>
<li<%%= sidebar_current("docs-google-kms-crypto-key-iam") %>>
<a href="/docs/providers/google/r/google_kms_crypto_key_iam.html">google_kms_crypto_key_iam_binding</a>
</li>
<li<%%= sidebar_current("docs-google-kms-crypto-key-iam-member") %>>
<a href="/docs/providers/google/r/google_kms_crypto_key_iam_member.html">google_kms_crypto_key_iam_member</a>
<li<%%= sidebar_current("docs-google-kms-crypto-key-iam") %>>
<a href="/docs/providers/google/r/google_kms_crypto_key_iam.html">google_kms_crypto_key_iam_member</a>
</li>
<li<%%= sidebar_current("docs-google-kms-crypto-key-iam") %>>
<a href="/docs/providers/google/r/google_kms_crypto_key_iam.html">google_kms_crypto_key_iam_policy</a>
</li>
<li<%%= sidebar_current("docs-google-kms-key-ring-x") %>>
<a href="/docs/providers/google/r/kms_key_ring.html">google_kms_key_ring</a>
Expand Down
Loading

0 comments on commit 9c8d732

Please sign in to comment.