Compliance and Audit Logging

Audit Logging Configuration

# audit_logging.tf
resource "google_project_iam_audit_config" "audit_config" {
  project = var.project_id
  
  service = "allServices"
  
  audit_log_config {
    log_type = "ADMIN_READ"
  }
  
  audit_log_config {
    log_type = "DATA_READ"
    exempted_members = var.exempted_members
  }
  
  audit_log_config {
    log_type = "DATA_WRITE"
  }
}
 
# Log Sinks
resource "google_logging_project_sink" "audit_sink" {
  for_each = var.log_sinks
 
  name        = "${var.environment}-${each.key}"
  project     = var.project_id
  destination = each.value.destination
 
  filter = each.value.filter
 
  unique_writer_identity = true
 
  dynamic "exclusions" {
    for_each = each.value.exclusions
    content {
      name        = exclusions.key
      description = exclusions.value.description
      filter      = exclusions.value.filter
    }
  }
}
 
# Log Metrics
resource "google_logging_metric" "logging_metric" {
  for_each = var.log_metrics
 
  name    = "${var.environment}-${each.key}"
  project = var.project_id
  filter  = each.value.filter
 
  metric_descriptor {
    metric_kind = each.value.metric_kind
    value_type  = each.value.value_type
    unit        = each.value.unit
    labels {
      key         = "severity"
      value_type  = "STRING"
      description = "Severity of the event"
    }
  }
 
  label_extractors = {
    "severity" = "EXTRACT(severity)"
  }
}

Log Export and Aggregation

# log_export.tf
resource "google_storage_bucket" "log_archive" {
  name          = "${var.project_id}-log-archive"
  project       = var.project_id
  location      = var.region
  storage_class = "COLDLINE"
 
  lifecycle_rule {
    condition {
      age = 365
    }
    action {
      type = "Delete"
    }
  }
 
  retention_policy {
    is_locked = true
    retention_period = 2592000 # 30 days
  }
}
 
resource "google_bigquery_dataset" "logs_dataset" {
  dataset_id  = "${var.environment}_logs"
  project     = var.project_id
  location    = var.region
  description = "Dataset for centralized logging"
 
  default_table_expiration_ms = 8640000000 # 100 days
 
  access {
    role          = "OWNER"
    user_by_email = google_service_account.logs_admin.email
  }
 
  access {
    role           = "READER"
    group_by_email = var.security_group
  }
}
 
resource "google_logging_project_sink" "aggregated_sink" {
  name        = "${var.environment}-aggregated-sink"
  project     = var.project_id
  destination = "bigquery.googleapis.com/projects/${var.project_id}/datasets/${google_bigquery_dataset.logs_dataset.dataset_id}"
 
  filter = <<EOF
    resource.type="gce_instance" OR
    resource.type="cloud_function" OR
    resource.type="cloud_run_revision" OR
    resource.type="gke_cluster"
EOF
 
  unique_writer_identity = true
 
  bigquery_options {
    use_partitioned_tables = true
  }
}

Compliance Monitoring

# compliance.tf
resource "google_monitoring_dashboard" "compliance_dashboard" {
  dashboard_json = jsonencode({
    displayName = "Compliance Dashboard"
    gridLayout = {
      widgets = [
        {
          title = "IAM Changes"
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = "resource.type=\"project\" AND protoPayload.methodName=\"SetIamPolicy\""
                }
              }
            }]
          }
        },
        {
          title = "Security Group Changes"
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = "resource.type=\"group\" AND protoPayload.methodName=~\"groups.*\""
                }
              }
            }]
          }
        }
      ]
    }
  })
}
 
# Compliance Alerts
resource "google_monitoring_alert_policy" "compliance_alerts" {
  for_each = var.compliance_alerts
 
  display_name = "${var.environment}-${each.key}"
  project      = var.project_id
  combiner     = "OR"
 
  conditions {
    display_name = each.value.condition_name
    
    condition_threshold {
      filter          = each.value.filter
      duration        = each.value.duration
      comparison      = each.value.comparison
      threshold_value = each.value.threshold
    }
  }
 
  notification_channels = [
    for channel in each.value.notification_channels :
    google_monitoring_notification_channel.compliance_channels[channel].name
  ]
 
  documentation {
    content   = each.value.documentation
    mime_type = "text/markdown"
  }
}

Data Governance

# data_governance.tf
resource "google_data_catalog_policy_tag" "policy_tags" {
  for_each = var.policy_tags
 
  provider     = google-beta
  project      = var.project_id
  taxonomy     = google_data_catalog_taxonomy.taxonomy.id
  display_name = each.value.display_name
  description  = each.value.description
 
  dynamic "child_policy_tags" {
    for_each = each.value.children
    content {
      display_name = child_policy_tags.value.display_name
      description  = child_policy_tags.value.description
    }
  }
}
 
resource "google_data_catalog_taxonomy" "taxonomy" {
  provider     = google-beta
  project      = var.project_id
  region       = var.region
  display_name = "${var.environment} Data Taxonomy"
  description  = "Taxonomy for data classification"
  
  activated_policy_types = [
    "FINE_GRAINED_ACCESS_CONTROL"
  ]
}
 
resource "google_data_catalog_taxonomy_iam_binding" "taxonomy_iam" {
  provider = google-beta
  project  = var.project_id
  taxonomy = google_data_catalog_taxonomy.taxonomy.id
  role     = "roles/datacatalog.categoryFineGrainedReader"
  members  = var.taxonomy_readers
}

Asset Inventory

# asset_inventory.tf
resource "google_cloud_asset_project_feed" "asset_feed" {
  project      = var.project_id
  feed_id      = "${var.environment}-asset-feed"
  content_type = "RESOURCE"
 
  asset_types = [
    "compute.googleapis.com/Instance",
    "storage.googleapis.com/Bucket",
    "iam.googleapis.com/ServiceAccount"
  ]
 
  feed_output_config {
    pubsub_destination {
      topic = google_pubsub_topic.asset_feed.id
    }
  }
 
  condition {
    expression = "resource.location.startsWith('us-')"
  }
}
 
resource "google_cloud_asset_organization_search" "asset_search" {
  provider = google-beta
  
  scope = "organizations/${var.organization_id}"
  query = "state:ACTIVE"
  
  search_results_storage_config {
    storage_destination = "gs://${google_storage_bucket.asset_inventory.name}/search-results"
  }
}
 
resource "google_cloud_asset_folder_feed" "folder_feed" {
  provider     = google-beta
  folder       = var.folder_id
  feed_id      = "${var.environment}-folder-feed"
  content_type = "IAM_POLICY"
 
  feed_output_config {
    pubsub_destination {
      topic = google_pubsub_topic.folder_feed.id
    }
  }
}

[Continue to Part 10 with Cost Management, Resource Optimization, and more advanced configurations?]

Would you like me to continue with the next part covering Cost Management, Resource Optimization, and more advanced GCP configurations?