Skip to content

Google Cloud Security Command Center

Patchy ingests Security Command Center findings and triages them alongside code-scanning alerts. A cloud finding is about a resource, not a file, so the pipeline treats it differently in two places: how it accumulates (below), and how it finds a repository to work in.

One provider, two capabilities

The SCC source on this page and the Cloud Asset Inventory enhancer are independent halves of the one google-cloud Integration — an estate sourcing findings from Wiz alone still configures the enhancer half, without enabling the source. The integrations overview maps every provider's roles.

How findings arrive

Security Command Center has no webhook. Its only egress is a NotificationConfig publishing to a Pub/Sub topic, so a push subscription forwards each notification to patchy's receiver at /google-cloud/webhooks. The scc-notifications Terraform submodule provisions that path — topic, notification config, subscription, dead-letter queue and IAM — and outputs the two values the Integration must agree with.

Authentication is the OIDC token Pub/Sub signs, not an HMAC. A push subscription cannot compute one: Pub/Sub composes the message, so the sender never sees the bytes patchy receives. The token is the stronger primitive anyway — asymmetric, short-lived, and bound to both a service account and an audience. Patchy checks both, because anyone with a Google Cloud account can mint a Google-signed token; it is the identity and audience that make one meaningful.

apiVersion: patchy.bitwisemedia.uk/v1alpha1
kind: Integration
metadata:
  name: google-cloud
  namespace: patchy
spec:
  provider: google-cloud
  googleCloud:
    securityCommandCenter:
      enabled: true
      # Both must match the push subscription exactly; a mismatch fails closed.
      audience: https://patchy.example.co.uk/google-cloud/webhooks
      serviceAccount: patchy-scc-push@x-patchy-app.iam.gserviceaccount.com
      # Numeric organization id, for composing Console links.
      organization: "123456789012"
      # A backstop under the notification config's own filter.
      minSeverity: high

A google-cloud Integration carries no secretRef: it holds no credential, and nothing in it calls a Google API.

Deliveries patchy declines are retried by Pub/Sub and then dead-lettered, never silently dropped. Two signals are worth alerting on: anything in the dead-letter topic, and the subscription's oldest unacknowledged message age — patchy answers 503 when its delivery queue is full, which Pub/Sub correctly treats as backpressure.

What patchy keeps

The notification is self-contained, so ingest makes no API call. From it a Finding gets:

Finding field From
spec.cloudResource finding.resourceName plus the notification's resource block
spec.advisories the CVE when there is one, then category:<CATEGORY>
spec.alerts[].id finding.name, the full SCC resource name
spec.severity finding.severity, lowercased
spec.description the whole notification, rendered to markdown

Notifications are skipped when the finding is not ACTIVE, is muted, is an SCC_ERROR (a detector that could not run — an operational problem for whoever owns the SCC configuration, not something to triage), or falls below minSeverity.

Accumulation is per resource, not per project. SCC re-notifies on every update to a finding, and those re-notifications fold into one Finding. Two different buckets with the same misconfiguration stay separate, because repository resolution is per resource and a family spanning resources could resolve to two different repositories with no right answer.

What is not implemented

Muting on an ignore verdict. Patchy dismisses a GHAS alert when it judges a finding a false positive; the equivalent for SCC is muting, which needs securitycenter.findings.setMute — a Google Cloud write permission integration-controller deliberately does not hold. The write-back seam (pkg/source.Resolver) is in place and the googleCloud.securityCommandCenter.mute block is accepted and validated but not yet honoured, so enabling it later is one implementation rather than a refactor.