Back to Checks
Service account was used within the configured maximum unused period
iam_service_account_unused
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:iam.googleapis.com/ServiceAccount
Google Cloud service accounts are evaluated for recent usage within a configurable window (default 180 days) using usage telemetry.
It highlights which accounts show activity versus those with no observed use in that period.
Risk
Dormant but permissioned service accounts threaten confidentiality and integrity via:
- Impersonation/privilege escalation through stale roles or leaked keys
- Lateral movement and persistent access They also weaken accountability, obscuring audit trails when reactivated unnoticed.
Run this check with Prowler
Run in Prowler CloudRun
prowler gcp --checks iam_service_account_unusedRecommendation
Apply least privilege and reduce attack surface:
- Verify inactivity, then disable and later delete unused accounts
- Revoke role bindings and keys; favor short-lived impersonation over keys
- Avoid powerful defaults; enforce separation of duties
- Continuously monitor usage and alert on dormancy
Remediation
CLI
gcloud auth print-access-token --impersonate-service-account=<SERVICE_ACCOUNT_EMAIL>Other
1In the Google Cloud console, open the IAM Service Account Credentials API reference for "GenerateAccessToken" and click "Try this method" (APIs Explorer)
2Set name to: projects/-/serviceAccounts/<SERVICE_ACCOUNT_EMAIL>
3Add scope: https://www.googleapis.com/auth/cloud-platform
4Click Execute (use an identity with roles/iam.serviceAccountTokenCreator on the service account)
5The generated token records recent usage for the service account, changing the finding to PASS
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_service_account_unused(Check):
def execute(self) -> Check_Report_GCP:
findings = []
max_unused_days = monitoring_client.audit_config.get(
"max_unused_account_days", 180
)
sa_ids_used = monitoring_client.sa_api_metrics
for account in iam_client.service_accounts:
report = Check_Report_GCP(
metadata=self.metadata(),
resource=account,
resource_id=account.email,
location=iam_client.region,
)
if account.disabled:
report.status = "PASS"
report.status_extended = (
f"Service Account {account.email} is disabled and cannot be used."
)
elif account.uniqueId in sa_ids_used:
report.status = "PASS"
report.status_extended = f"Service Account {account.email} was used over the last {max_unused_days} days."
else:
report.status = "FAIL"
report.status_extended = f"Service Account {account.email} was not used over the last {max_unused_days} days."
findings.append(report)
return findings