Skip to main content
compliance · gcp

Service accounts carrying downloadable user-managed keys

resource types
1
rule IDs covered
1
severity
medium

What does ZopNight detect here?

User-managed service account keys are static credentials that keep working until explicitly deleted. Leaked once, they authenticate indefinitely. ZopNight raises RC-131 at medium severity when the discoverer records user_managed_keys_present=true on a service-account principal. Workload Identity Federation removes the key file entirely, which beats any rotation cadence, including 90-day.

Signal and threshold

How ZopNight evaluates Service accounts carrying downloadable user-managed keys.
Field Value
Rule IDsRC-131
Categorycompliance
Severitymedium
Metricnone — pure configuration read
Sourceiam_user_managed_key.go

A credential file with no expiry

Creating a user-managed key downloads a JSON file containing a private key that authenticates as the service account from anywhere on the internet, with no expiration date. From that moment the security of the account equals the security of every place the file ever lands: a laptop, a CI secret store, a container image layer, a git commit someone force-pushed away but never purged. Public-repo scanners find committed GCP key files within minutes, and unlike a session token, a harvested key does not age out. Access persists until the key object itself is deleted. Google-managed keys have none of these properties (they never leave Google’s infrastructure), which is why the rule counts only USER_MANAGED keys.

The federation alternative

Most keys exist to let something outside GCP call GCP, and every mainstream case now has a keyless answer. GKE workloads get identity through Workload Identity; Cloud Run and Compute Engine attach service accounts natively; GitHub Actions, other clouds, and on-prem systems authenticate via Workload Identity Federation, exchanging their own short-lived tokens for GCP credentials. Migration order that avoids surprises: find the key’s consumer, wire up the keyless path, run both in parallel, then delete the key and watch for authentication failures. Where an org is ready to forbid the pattern outright, the constraints/iam.disableServiceAccountKeyCreation org policy stops new keys from being minted at all.

Inventory the keys that exist today

Terminal window
gcloud iam service-accounts keys list \
--iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
--managed-by=user

An empty result is the goal state. Anything listed is a standing credential to track down.

Presence, not age, and a fail-closed gate

Detection here is existence: the discoverer’s IAM listing (using iam.serviceAccountKeys.list, granted through roles/iam.securityReviewer) writes user_managed_keys_present=true on service-account principals that have at least 1 user-managed key. Age is a different question, handled by the companion rotation rule RC-132 for keys older than 90 days, so an account can legitimately trip this rule the day a fresh key is created. The rule narrows to service accounts via the serviceAccount: UID prefix, fires only on the explicit true, and abstains whenever the metadata key is absent. Key deletion is deliberately manual: revoking a credential that something may still depend on deserves a human decision.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·