From 99129d54a37da4c2d977b7db705de5024d530944 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 25 Apr 2024 09:31:51 +0300 Subject: [PATCH] Update FAST logging (#2235) * Update FAST logging * Fix readme * Fix tests --- fast/stages/0-bootstrap/README.md | 20 +++++++++------- fast/stages/0-bootstrap/automation.tf | 18 ++++++++++++++ fast/stages/0-bootstrap/variables.tf | 24 ++++++++++++++++--- tests/fast/stages/s0_bootstrap/checklist.yaml | 10 ++++---- tests/fast/stages/s0_bootstrap/simple.yaml | 10 ++++---- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/fast/stages/0-bootstrap/README.md b/fast/stages/0-bootstrap/README.md index 83031f5d2a..ee5c7f52e7 100644 --- a/fast/stages/0-bootstrap/README.md +++ b/fast/stages/0-bootstrap/README.md @@ -138,7 +138,9 @@ Because of limitations of API availability, manual steps have to be followed to ### Organization-level logging -We create organization-level log sinks early in the bootstrap process to ensure a proper audit trail is in place from the very beginning. By default, we provide log filters to capture [Cloud Audit Logs](https://cloud.google.com/logging/docs/audit), [VPC Service Controls violations](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#vpc-sc-errors) and [Workspace Logs](https://cloud.google.com/logging/docs/audit/configure-gsuite-audit-logs) into logging buckets in the top-level audit logging project. +We create organization-level log sinks early in the bootstrap process to ensure a proper audit trail is in place from the very beginning. By default, we provide log filters to capture [Cloud Audit Logs](https://cloud.google.com/logging/docs/audit), [VPC Service Controls violations](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#vpc-sc-errors) and [Workspace Logs](https://cloud.google.com/logging/docs/audit/configure-gsuite-audit-logs) into logging buckets in the top-level audit logging project. + +An organization-level sink captures IAM data access logs, including authentication and impersonation events for service accounts. To manage logging costs, the default configuration enables IAM data access logging only within the automation project (where sensitive service accounts reside). For enhanced security across the entire organization, consider enabling these logs at the organization level. The [Customizations](#log-sinks-and-log-destinations) section explains how to change the logs captured and their destination. @@ -626,8 +628,8 @@ The `fast_features` variable consists of 4 toggles: | name | description | type | required | default | producer | |---|---|:---:|:---:|:---:|:---:| | [billing_account](variables.tf#L17) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | | -| [organization](variables.tf#L223) | Organization details. | object({…}) | ✓ | | | -| [prefix](variables.tf#L238) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | +| [organization](variables.tf#L241) | Organization details. | object({…}) | ✓ | | | +| [prefix](variables.tf#L256) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | | [bootstrap_user](variables.tf#L27) | Email of the nominal user running this stage for the first time. | string | | null | | | [cicd_repositories](variables.tf#L33) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | | | [custom_roles](variables.tf#L79) | Map of role names => list of permissions to additionally create at the organization level. | map(list(string)) | | {} | | @@ -639,12 +641,12 @@ The `fast_features` variable consists of 4 toggles: | [iam_bindings_additive](variables.tf#L141) | Organization-level custom additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | | | [iam_by_principals](variables.tf#L156) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | | | [locations](variables.tf#L163) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | | -| [log_sinks](variables.tf#L177) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | -| [org_policies_config](variables.tf#L206) | Organization policies customization. | object({…}) | | {} | | -| [outputs_location](variables.tf#L232) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | -| [project_parent_ids](variables.tf#L247) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | | -| [workforce_identity_providers](variables.tf#L258) | Workforce Identity Federation pools. | map(object({…})) | | {} | | -| [workload_identity_providers](variables.tf#L274) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | +| [log_sinks](variables.tf#L177) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | +| [org_policies_config](variables.tf#L224) | Organization policies customization. | object({…}) | | {} | | +| [outputs_location](variables.tf#L250) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [project_parent_ids](variables.tf#L265) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | | +| [workforce_identity_providers](variables.tf#L276) | Workforce Identity Federation pools. | map(object({…})) | | {} | | +| [workload_identity_providers](variables.tf#L292) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | ## Outputs diff --git a/fast/stages/0-bootstrap/automation.tf b/fast/stages/0-bootstrap/automation.tf index 6200deab38..8463ff16b6 100644 --- a/fast/stages/0-bootstrap/automation.tf +++ b/fast/stages/0-bootstrap/automation.tf @@ -156,6 +156,24 @@ module "automation-project" { "container.googleapis.com", ] ) + + # Enable IAM data access logs to capture impersonation and service + # account token generation events. This is implemented within the + # automation project to limit log volume. For heightened security, + # consider enabling it at the organization level. A log sink within + # the organization will collect and store these logs in a logging + # bucket. See + # https://cloud.google.com/iam/docs/audit-logging#audited_operations + logging_data_access = { + "iam.googleapis.com" = { + # ADMIN_READ captures impersonation and token generation/exchanges + ADMIN_READ = [] + # enable DATA_WRITE if you want to capture configuration changes + # to IAM-related resources (roles, deny policies, service + # accounts, identity pools, etc) + # DATA_WRITE = [] + } + } } # output files bucket diff --git a/fast/stages/0-bootstrap/variables.tf b/fast/stages/0-bootstrap/variables.tf index 64978dc30f..b769f1088f 100644 --- a/fast/stages/0-bootstrap/variables.tf +++ b/fast/stages/0-bootstrap/variables.tf @@ -182,15 +182,33 @@ variable "log_sinks" { })) default = { audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName:\"/logs/cloudaudit.googleapis.com%2Fsystem_event\" OR protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.TransparencyLog\"" + filter = <<-FILTER + log_id("cloudaudit.googleapis.com/activity") OR + log_id("cloudaudit.googleapis.com/system_event") OR + log_id("cloudaudit.googleapis.com/policy") OR + log_id("cloudaudit.googleapis.com/access_transparency") + FILTER + type = "logging" + } + iam = { + filter = <<-FILTER + protoPayload.serviceName="iamcredentials.googleapis.com" OR + protoPayload.serviceName="iam.googleapis.com" OR + protoPayload.serviceName="sts.googleapis.com" + FILTER type = "logging" } vpc-sc = { - filter = "protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata\"" + filter = <<-FILTER + protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata" + FILTER type = "logging" } workspace-audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Fdata_access\" and protoPayload.serviceName:\"login.googleapis.com\"" + filter = <<-FILTER + log_id("cloudaudit.googleapis.com/data_access") + protoPayload.serviceName:"login.googleapis.com" + FILTER type = "logging" } } diff --git a/tests/fast/stages/s0_bootstrap/checklist.yaml b/tests/fast/stages/s0_bootstrap/checklist.yaml index 91fe60eb76..8c24a1fdfe 100644 --- a/tests/fast/stages/s0_bootstrap/checklist.yaml +++ b/tests/fast/stages/s0_bootstrap/checklist.yaml @@ -360,15 +360,15 @@ counts: google_bigquery_dataset: 1 google_bigquery_default_service_account: 3 google_essential_contacts_contact: 3 - google_logging_organization_sink: 3 - google_logging_project_bucket_config: 3 + google_logging_organization_sink: 4 + google_logging_project_bucket_config: 4 google_org_policy_policy: 22 google_organization_iam_binding: 27 google_organization_iam_custom_role: 7 google_organization_iam_member: 35 google_project: 3 google_project_iam_binding: 19 - google_project_iam_member: 6 + google_project_iam_member: 7 google_project_service: 31 google_project_service_identity: 4 google_service_account: 4 @@ -380,5 +380,5 @@ counts: google_storage_project_service_account: 3 google_tags_tag_key: 1 google_tags_tag_value: 1 - modules: 17 - resources: 198 + modules: 18 + resources: 202 diff --git a/tests/fast/stages/s0_bootstrap/simple.yaml b/tests/fast/stages/s0_bootstrap/simple.yaml index 904471a061..69908ad358 100644 --- a/tests/fast/stages/s0_bootstrap/simple.yaml +++ b/tests/fast/stages/s0_bootstrap/simple.yaml @@ -39,15 +39,15 @@ counts: google_bigquery_dataset: 1 google_bigquery_default_service_account: 3 google_essential_contacts_contact: 3 - google_logging_organization_sink: 3 - google_logging_project_bucket_config: 3 + google_logging_organization_sink: 4 + google_logging_project_bucket_config: 4 google_org_policy_policy: 22 google_organization_iam_binding: 27 google_organization_iam_custom_role: 7 google_organization_iam_member: 22 google_project: 3 google_project_iam_binding: 19 - google_project_iam_member: 6 + google_project_iam_member: 7 google_project_service: 31 google_project_service_identity: 4 google_service_account: 4 @@ -60,8 +60,8 @@ counts: google_tags_tag_key: 1 google_tags_tag_value: 1 local_file: 7 - modules: 16 - resources: 189 + modules: 17 + resources: 193 outputs: custom_roles: