project_cis_log_alerts — version 1.1

Source: presets/monitoring/project-cis-log-alerts.satz

Purpose

CIS log metric filters and alert policies, per project.

Covers CIS GCP Foundations 2.5 – 2.12: eight log-based metric filters, each with an alert policy, plus the notification channel they fire into.

It declares several resource types, so it goes at the TOP level: the target project is chosen by each resource's own project field, not by where the use sits.


ONE PROJECT PER USE — no parameterisation

The labels below (cis_2_5_project_ownership, ...) are fixed, so using this pack twice collides on the fold. For a second project, fork it and prefix every label and metric name (cis_2_5_project_ownership -> tenantb_cis_2_5_project_ownership), or use the central variant, which covers all projects at once: presets/monitoring/organization-cis-log-alerts-central.satz


PER PROJECT, AND WHAT IT COSTS

Notification channels are PROJECT resources (google_monitoring_notification_channel -> projects.notificationChannels). An alert policy can only reference channels living in its OWN project; there is no organization-level channel and no cross-project reference. So one channel cannot serve every project: using this pack in N projects creates N channels pointing at the same mailbox, N x 8 metrics and N x 8 policies. Every new project needs it again; without it the project fails CIS 2.5-2.12.

The cheaper topology: route all projects' logs through an org-level aggregated sink into a LOGGING bucket (not GCS), then define the eight metrics bucket-scoped in that one project. Prowler credits every child project of such a sink as compliant (logging_service.get_projects_covered_by_aggregated_metric) — eight metrics and one channel for the whole organization, and future projects are covered on creation without touching their config. See organization-cis-log-alerts-central.satz.

Use THIS pack when a project must alert on its own (separate on-call, delegated ownership, tenant isolation) or when the central logging bucket does not exist yet. Both variants may coexist: Prowler passes the control as soon as EITHER condition is met.


WHAT PROWLER CHECKS — and what it does not

The checks require (a) a metric whose filter CONTAINS the CIS filter string and (b) any alert policy whose condition filter mentions that metric name. Whether the policy has a recipient is not checked: an alert policy with notification_channels = [] passes CIS and notifies nobody. The channel below exists for that reason, not because the benchmark asks for it.

Filter strings must match Prowler's expectation verbatim — they are compared by substring. A reformatted filter fails the check and keeps the alert working. The expected strings are in: prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_*


PREREQUISITES

Verify after transpile: grep -c 'google_logging_metric' hcl/main.tf # expect 8 grep -c 'google_monitoring_alert_policy' hcl/main.tf # expect 8 grep -A3 'notification_channels' hcl/main.tf # reference, not literal

After apply, test the pipeline end to end; the compliance check also passes on a metric that never increments: gcloud iam roles create cis_probe --project=

--permissions=storage.buckets.get --stage=GA gcloud iam roles delete cis_probe --project=

expect an alert from the 2.7 policy within ~5 minutes

Use it

params {
  // the pack's own defaults — copy only the lines you change
  cis_alert_project = "{infra_project_name}"
  cis_alert_email_local = "gcp-security"
  cis_alert_channel_name = "CIS Security Alerts"
  cis_alert_window = "300s"
}

use "presets/monitoring/project-cis-log-alerts.satz"

Needs from outside the pack:

Params

param default
cis_alert_project "{infra_project_name}"
cis_alert_email_local "gcp-security"
cis_alert_channel_name "CIS Security Alerts"
cis_alert_window "300s"

Questions

What to ask before this pack is configured, and what changing the answer costs.

asks about prompt reversal blast recommends
cis_alert_project The one project this pack watches — its metrics, policies and channel are created there recreate low —
cis_alert_email_local The local part of the alert recipient's address (the customer domain is added) edit high —

cis_alert_project — One project per use: the labels are fixed, so a second project means a fork. Changing the project later recreates all eight metrics and policies in the new one and loses the alert history of the old.

cis_alert_email_local — Monitoring sends from alerting-noreply@google.com, so the mailbox must exist and accept external mail; a group whose members have no mailboxes drops every alert silently. A group, never a person.

Contributes

resource type labels
google_logging_metric cis_2_5_project_ownership, cis_2_6_audit_config, cis_2_7_custom_role, cis_2_8_firewall_rule, cis_2_9_network_route, cis_2_10_network, cis_2_11_bucket_permission, cis_2_12_sql_instance
google_monitoring_alert_policy cis_2_5_project_ownership, cis_2_6_audit_config, cis_2_7_custom_role, cis_2_8_firewall_rule, cis_2_9_network_route, cis_2_10_network, cis_2_11_bucket_permission, cis_2_12_sql_instance
google_monitoring_notification_channel cis_security_alerts

Claims

None — this pack proves no control by itself.

History

version date change
1.1 2026-09-10 two question blocks: the one project this use watches, and the alert recipient's local part. Nothing emitted changes
1.0 2026-08-21 per-project variant of the CIS 2.5–2.12 metrics + alerts

The whole library's history: the changelog in presets/CHANGELOG.md.

Notes

The central pack, monitoring.organization_cis_log_alerts_central, covers every project in the organisation through one org-level sink — this one is for a single project outside that sweep. Using it twice in one estate collides on the fold: for a second project, fork it and prefix every label and metric name.

It makes no claims: a per-project pipeline does not discharge an organisation-wide control.