diff --git a/1-org/envs/shared/README.md b/1-org/envs/shared/README.md index 8da1e2415..502720442 100644 --- a/1-org/envs/shared/README.md +++ b/1-org/envs/shared/README.md @@ -8,12 +8,13 @@ | create\_unique\_tag\_key | Creates unique organization-wide tag keys by adding a random suffix to each key. | `bool` | `false` | no | | domains\_to\_allow | The list of domains to allow users from in IAM. Used by Domain Restricted Sharing Organization Policy. Must include the domain of the organization you are deploying the foundation. To add other domains you must also grant access to these domains to the Terraform Service Account used in the deploy. | `list(string)` | n/a | yes | | enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | +| enable\_kms\_key\_usage\_tracking | Enable KMS centralized key usage tracking system. | `bool` | `true` | no | | enable\_scc\_resources\_in\_terraform | Create Security Command Center resources in Terraform. If your organization has newly enabled any preview features for SCC and get an error related to the v2 API, you must set this variable to false because the v2 API does not yet support Terraform resources. See [issue 1189](https://github.com/terraform-google-modules/terraform-example-foundation/issues/1189) for context. | `bool` | `false` | no | | enforce\_allowed\_worker\_pools | Whether to enforce the organization policy restriction on allowed worker pools for Cloud Build. | `bool` | `false` | no | | essential\_contacts\_domains\_to\_allow | The list of domains that email addresses added to Essential Contacts can have. | `list(string)` | n/a | yes | | essential\_contacts\_language | Essential Contacts preferred language for notifications, as a ISO 639-1 language code. See [Supported languages](https://cloud.google.com/resource-manager/docs/managing-notification-contacts#supported-languages) for a list of supported languages. | `string` | `"en"` | no | | folder\_deletion\_protection | Prevent Terraform from destroying or recreating the folder. | `string` | `true` | no | -| gcp\_groups | Groups to grant specific roles in the Organization.
platform\_viewer: Google Workspace or Cloud Identity group that have the ability to view resource information across the Google Cloud organization.
security\_reviewer: Google Workspace or Cloud Identity group that members are part of the security team responsible for reviewing cloud security
network\_viewer: Google Workspace or Cloud Identity group that members are part of the networking team and review network configurations.
scc\_admin: Google Workspace or Cloud Identity group that can administer Security Command Center.
audit\_viewer: Google Workspace or Cloud Identity group that members are part of an audit team and view audit logs in the logging project.
global\_secrets\_admin: Google Workspace or Cloud Identity group that members are responsible for putting secrets into Secrets Manage |
object({
audit_viewer = optional(string, null)
security_reviewer = optional(string, null)
network_viewer = optional(string, null)
scc_admin = optional(string, null)
global_secrets_admin = optional(string, null)
kms_admin = optional(string, null)
})
| `{}` | no | +| gcp\_groups | Groups to grant specific roles in the Organization.
platform\_viewer: Google Workspace or Cloud Identity group that have the ability to view resource information across the Google Cloud organization.
security\_reviewer: Google Workspace or Cloud Identity group that members are part of the security team responsible for reviewing cloud security
network\_viewer: Google Workspace or Cloud Identity group that members are part of the networking team and review network configurations.
scc\_admin: Google Workspace or Cloud Identity group that can administer Security Command Center.
audit\_viewer: Google Workspace or Cloud Identity group that members are part of an audit team and view audit logs in the logging project.
global\_secrets\_admin: Google Workspace or Cloud Identity group that members are responsible for putting secrets into Secrets Management. |
object({
audit_viewer = optional(string, null)
security_reviewer = optional(string, null)
network_viewer = optional(string, null)
scc_admin = optional(string, null)
global_secrets_admin = optional(string, null)
kms_admin = optional(string, null)
})
| `{}` | no | | log\_export\_storage\_force\_destroy | (Optional) If set to true, delete all contents when destroying the resource; otherwise, destroying the resource will fail if contents are present. | `bool` | `false` | no | | log\_export\_storage\_location | The location of the storage bucket used to export logs. | `string` | `null` | no | | log\_export\_storage\_retention\_policy | Configuration of the bucket's data retention policy for how long objects in the bucket should be retained. |
object({
is_locked = bool
retention_period_days = number
})
| `null` | no | diff --git a/1-org/envs/shared/iam.tf b/1-org/envs/shared/iam.tf index b5c627705..b5880493f 100644 --- a/1-org/envs/shared/iam.tf +++ b/1-org/envs/shared/iam.tf @@ -62,6 +62,34 @@ resource "google_organization_iam_member" "billing_viewer" { member = "group:${local.required_groups["billing_data_users"]}" } +/****************************************** + Enable KMS Usage Tracking +*****************************************/ + +module "create_kms_organization_service_agent" { + source = "terraform-google-modules/gcloud/google" + version = "~> 3.1" + upgrade = false + + create_cmd_triggers = { + org_id = local.org_id + } + + create_cmd_body = "beta services identity create --service cloudkms.googleapis.com --organization ${local.org_id}" +} + +resource "google_organization_iam_member" "kms_usage_tracking" { + count = var.enable_kms_key_usage_tracking ? 1 : 0 + + depends_on = [ + module.create_kms_organization_service_agent, + ] + + org_id = local.org_id + role = "roles/cloudkms.orgServiceAgent" + member = "serviceAccount:service-org-${local.org_id}@gcp-sa-cloudkms.iam.gserviceaccount.com" +} + /****************************************** Groups permissions *****************************************/ @@ -143,6 +171,13 @@ resource "google_project_iam_member" "kms_admin" { member = "group:${var.gcp_groups.kms_admin}" } +resource "google_organization_iam_member" "kms_protected_resources_viewer" { + count = var.gcp_groups.kms_admin != null && var.enable_kms_key_usage_tracking ? 1 : 0 + org_id = local.org_id + role = "roles/cloudkms.protectedResourcesViewer" + member = "group:${var.gcp_groups.kms_admin}" +} + resource "google_project_iam_member" "cai_monitoring_builder" { project = module.scc_notifications.project_id for_each = toset(var.enable_scc_resources_in_terraform ? diff --git a/1-org/envs/shared/variables.tf b/1-org/envs/shared/variables.tf index bc6fae1cf..1c1830366 100644 --- a/1-org/envs/shared/variables.tf +++ b/1-org/envs/shared/variables.tf @@ -26,6 +26,12 @@ variable "enable_scc_resources_in_terraform" { default = false } +variable "enable_kms_key_usage_tracking" { + description = "Enable KMS centralized key usage tracking system." + type = bool + default = true +} + variable "domains_to_allow" { description = "The list of domains to allow users from in IAM. Used by Domain Restricted Sharing Organization Policy. Must include the domain of the organization you are deploying the foundation. To add other domains you must also grant access to these domains to the Terraform Service Account used in the deploy." type = list(string) @@ -141,7 +147,7 @@ variable "gcp_groups" { network_viewer: Google Workspace or Cloud Identity group that members are part of the networking team and review network configurations. scc_admin: Google Workspace or Cloud Identity group that can administer Security Command Center. audit_viewer: Google Workspace or Cloud Identity group that members are part of an audit team and view audit logs in the logging project. - global_secrets_admin: Google Workspace or Cloud Identity group that members are responsible for putting secrets into Secrets Manage + global_secrets_admin: Google Workspace or Cloud Identity group that members are responsible for putting secrets into Secrets Management. EOT type = object({ audit_viewer = optional(string, null) diff --git a/test/integration/testutils/retry.go b/test/integration/testutils/retry.go index 67c05bb19..d70ca41a6 100644 --- a/test/integration/testutils/retry.go +++ b/test/integration/testutils/retry.go @@ -45,5 +45,8 @@ var ( // Error waiting for creating service network connection. This happens randomly for development, production and non-production environments ".*Error code 16.*Error waiting for Create Service Networking Connection*": "Request had invalid authentication credentials", + + // Error 400: The eTag provided {} does not match the eTag of the current version of the Access Policy, which is {}. + ".*Error 400: The eTag provided.*does not match the eTag of the current version of the Access Policy, which is.*": "Conflict during Access Policy configuration.", } )