GCP service accounts whose user-managed key is more than 90 days old
What does ZopNight detect here?
GCP service account keys never expire by default, so a user-managed key created months ago stays valid until someone deletes it. ZopNight flags service accounts whose user-managed key is more than 90 days old, reports the exact age in days, and recommends rotating now and moving to Workload Identity Federation.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-132 |
| Category | compliance |
| Severity | medium |
| Metric | none — pure configuration read |
| Threshold | key age > 90 days |
| Source | ZopNight |
| Permissions used | iam.serviceAccounts.list · iam.serviceAccountKeys.list |
Where it applies
Why old keys are a larger risk than new ones
Every day a key stays valid is another day a leaked copy works. Google’s key best practices recommend routinely rotating all keys you manage, because a leaked key might take attackers days or weeks to find, and regular rotation raises the chance it is already invalid by then. Keys created through IAM have no expiry time by default and stay valid until deleted.
A 90-day ceiling is a common policy line. A key older than that has been through at least a quarter of laptop replacements, CI migrations and staff changes, any of which could have left a copy somewhere.
Listing keys past the cutoff
Use a timestamp 90 days before today. For example, run on 25 September 2026:
gcloud iam service-accounts keys list \ --iam-account=SA_EMAIL \ --managed-by=user \ --created-before=2026-06-27T00:00:00ZAny key returned is older than 90 days. Loop over
gcloud iam service-accounts list --format="value(email)" to cover a project.
The threshold and what it measures
ZopNight records, for each service account, the age in days of its user-managed key. The rule fires when the principal is a service account and that age is greater than 90 days, so a key exactly 90 days old does not yet trigger it. The finding’s title carries the measured age, which makes the oldest keys easy to sort to the top.
When nothing is raised
No finding appears if the principal is not a service account, if no key age was recorded, or if the recorded value cannot be read as a whole number of days. Service accounts with only Google-managed keys never have an age recorded and are silent. Whether an account should have user-managed keys at all is a separate question, answered by GCP Service Account Has User-Managed Keys.
Exposure window, not a saving
There is no saving attached. The risk grows with age: the older the key, the more places a copy may exist and the longer an attacker who has one can keep using it.
Rotating the key without an outage
- Create a new key:
gcloud iam service-accounts keys create new-key.json --iam-account=SA_EMAIL. - Roll it out to every consumer, ideally through a secret manager rather than files.
- Disable the old key and watch for authentication errors for a few days:
gcloud iam service-accounts keys disable OLD_KEY_ID --iam-account=SA_EMAIL. - Delete it once nothing fails:
gcloud iam service-accounts keys delete OLD_KEY_ID --iam-account=SA_EMAIL. - Plan the move to Workload Identity Federation or attached service accounts so there is no key to rotate next quarter.