From c5788d034414e4e3821db1918e40201066194017 Mon Sep 17 00:00:00 2001 From: Arthur de Lapertosa Lisboa Date: Fri, 20 Sep 2024 13:46:56 -0300 Subject: [PATCH] feat: add org policies to confidential computing example (#427) --- examples/confidential_computing/README.md | 7 ++- .../confidential_computing/org_policies.tf | 51 +++++++++++++++++++ .../confidential_compute_instance_test.go | 18 ++++++- test/setup/iam.tf | 6 +++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 examples/confidential_computing/org_policies.tf diff --git a/examples/confidential_computing/README.md b/examples/confidential_computing/README.md index ca5b2a77..629c748e 100644 --- a/examples/confidential_computing/README.md +++ b/examples/confidential_computing/README.md @@ -2,7 +2,12 @@ This is an example of a vm creation with confidential computing, encrypted disk using a multiregion (US by default) Cloud HSM key -and a custom service account with cloud-platform scope. +and a custom service account with cloud-platform scope. It also +creates org policies enforcing the use of CMEK encrypted instances +and confidential computing to all newly created VMs within the project. +Also, an additional org policy constraint is created, which only allows +Cloud KMS keys (used for CMEK protection) that come from the provided input project. +Note: existing VM instances won't be affected by the new org policy. ## Inputs diff --git a/examples/confidential_computing/org_policies.tf b/examples/confidential_computing/org_policies.tf new file mode 100644 index 00000000..3c9ad5f4 --- /dev/null +++ b/examples/confidential_computing/org_policies.tf @@ -0,0 +1,51 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module "confidential-computing-org-policy" { + source = "terraform-google-modules/org-policy/google" + version = "~> 5.3" + + project_id = var.project_id + policy_for = "project" + constraint = "constraints/compute.restrictNonConfidentialComputing" + policy_type = "list" + deny = ["compute.googleapis.com"] + deny_list_length = 1 +} + +module "enforce-cmek-org-policy" { + source = "terraform-google-modules/org-policy/google" + version = "~> 5.3" + + project_id = var.project_id + policy_for = "project" + constraint = "constraints/gcp.restrictNonCmekServices" + policy_type = "list" + deny = ["compute.googleapis.com"] + deny_list_length = 1 +} + +module "restrict-cmek-cryptokey-projects-policy" { + source = "terraform-google-modules/org-policy/google" + version = "~> 5.3" + + project_id = var.project_id + policy_for = "project" + constraint = "constraints/gcp.restrictCmekCryptoKeyProjects" + policy_type = "list" + allow = ["projects/${var.project_id}"] + allow_list_length = 1 +} diff --git a/test/integration/confidential_compute_instance/confidential_compute_instance_test.go b/test/integration/confidential_compute_instance/confidential_compute_instance_test.go index d36d255c..8d7fd6cc 100644 --- a/test/integration/confidential_compute_instance/confidential_compute_instance_test.go +++ b/test/integration/confidential_compute_instance/confidential_compute_instance_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestConfidentialInstanceTemplate(t *testing.T) { +func TestConfidentialComputeInstance(t *testing.T) { const instanceNamePrefix = "confidential-encrypted-instance" confCompInst := tft.NewTFBlueprintTest(t) @@ -49,6 +49,22 @@ func TestConfidentialInstanceTemplate(t *testing.T) { assert.Len(disks, 1) defaultSuffix := confCompInst.GetStringOutput("suffix") assert.Equal(fmt.Sprintf("projects/%s/locations/us/keyRings/key-ring-test-%s/cryptoKeys/key-test-%s/cryptoKeyVersions/1", projectId, defaultSuffix, defaultSuffix), disks[0].Get("diskEncryptionKey").Get("kmsKeyName").String()) + + org_policy_cmek_constraint := gcloud.Runf(t, "resource-manager org-policies list --project=%s --format=json --filter constraint='constraints/gcp.restrictNonCmekServices'", projectId).Array() + assert.Len(org_policy_cmek_constraint, 1) + cmek_denied_values_list := org_policy_cmek_constraint[0].Get("listPolicy.deniedValues").Array() + assert.Len(cmek_denied_values_list, 1) + assert.Equal("compute.googleapis.com", cmek_denied_values_list[0].String()) + org_policy_cmek_projects := gcloud.Runf(t, "resource-manager org-policies list --project=%s --format=json --filter constraint='constraints/gcp.restrictCmekCryptoKeyProjects'", projectId).Array() + assert.Len(org_policy_cmek_projects, 1) + cmek_allowed_projects := org_policy_cmek_projects[0].Get("listPolicy.allowedValues").Array() + assert.Len(cmek_allowed_projects, 1) + assert.Equal(fmt.Sprintf("projects/%s", projectId), cmek_allowed_projects[0].String()) + org_policy_confidential_constraint := gcloud.Runf(t, "resource-manager org-policies list --project=%s --format=json --filter constraint='constraints/compute.restrictNonConfidentialComputing'", projectId).Array() + assert.Len(org_policy_confidential_constraint, 1) + cc_denied_values_list := org_policy_confidential_constraint[0].Get("listPolicy.deniedValues").Array() + assert.Len(cc_denied_values_list, 1) + assert.Equal("compute.googleapis.com", cc_denied_values_list[0].String()) }) confCompInst.Test() } diff --git a/test/setup/iam.tf b/test/setup/iam.tf index 3b1ed4ca..e37f7575 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -38,6 +38,12 @@ resource "google_project_iam_member" "ci_vm_account" { member = "serviceAccount:${google_service_account.ci_vm_account.email}" } +resource "google_organization_iam_member" "ci_vm_account_organization" { + org_id = var.org_id + role = "roles/orgpolicy.policyAdmin" + member = "serviceAccount:${google_service_account.ci_vm_account.email}" +} + resource "google_service_account_key" "ci_vm_account" { service_account_id = google_service_account.ci_vm_account.id }