Back to Checks
gcp

User-managed service account key was used within the allowed inactivity period

iam_sa_user_managed_key_unused
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:secrets
Resource Type:iam.googleapis.com/ServiceAccountKey

User-managed service account keys with no recorded activity during the last max_unused_account_days are identified using key-usage metrics per service account.

Risk

Stale user-managed keys expand exposure of long-lived credentials. If leaked, an attacker can authenticate as the service account off-platform, bypass network controls, access data, alter resources, and persist-compromising confidentiality and integrity, and risking availability via destructive changes.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler gcp --checks iam_sa_user_managed_key_unused

Recommendation

Prefer managed workload identities and service account impersonation over user-managed keys. Enforce iam.disableServiceAccountKeyCreation, remove unused keys, and use short key lifetimes with rotation when unavoidable. Apply least privilege, monitor key usage, and enforce separation of duties to limit blast radius.

Remediation

CLI

gcloud iam service-accounts keys delete <KEY_ID> --iam-account=<SERVICE_ACCOUNT_EMAIL>

Other

1In Google Cloud Console, go to IAM & Admin > Service Accounts
2Select your project and click the service account with the unused user-managed key
3Open the Keys tab
4Find the unused key (Type: User-managed), click Delete, and confirm

Check Code

from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.iam.iam_client import iam_client
from prowler.providers.gcp.services.monitoring.monitoring_client import (
    monitoring_client,
)


class iam_sa_user_managed_key_unused(Check):
    def execute(self) -> Check_Report_GCP:
        findings = []
        max_unused_days = monitoring_client.audit_config.get(
            "max_unused_account_days", 180
        )
        keys_used = monitoring_client.sa_keys_metrics
        for account in iam_client.service_accounts:
            for key in account.keys:
                if key.type == "USER_MANAGED":
                    report = Check_Report_GCP(
                        metadata=self.metadata(),
                        resource=account,
                        resource_id=key.name,
                        resource_name=account.email,
                        location=iam_client.region,
                    )
                    if key.name in keys_used:
                        report.status = "PASS"
                        report.status_extended = f"User-managed key {key.name} for Service Account {account.email} was used over the last {max_unused_days} days."
                    else:
                        report.status = "FAIL"
                        report.status_extended = f"User-managed key {key.name} for Service Account {account.email} was not used over the last {max_unused_days} days."
                    findings.append(report)

        return findings