Back to Checks
gcp

Project has no IAM users assigned the Service Account User or Service Account Token Creator roles at project level

iam_no_service_roles_at_project_level
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:cloudresourcemanager.googleapis.com/Project

Google Cloud IAM policies are inspected for project-level grants of roles/iam.serviceAccountUser and roles/iam.serviceAccountTokenCreator to principals. The focus is on bindings that enable attaching or impersonating service accounts at the project scope rather than on individual service accounts.

Risk

Project-wide impersonation rights enable privilege escalation and lateral movement. Holders can act as any service account, access data across services, modify resources, and persist access. New service accounts inherit exposure, undermining confidentiality and integrity.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler gcp --checks iam_no_service_roles_at_project_level

Recommendation

Assign roles/iam.serviceAccountUser and roles/iam.serviceAccountTokenCreator only on the specific service account, not at project scope. Enforce least privilege and separation of duties with per-SA grants, conditional bindings, and time-bound access. Prefer short-lived impersonation; review grants regularly.

Remediation

Terraform

# Grant required access at the service account level instead of the project level
resource "google_service_account_iam_member" "<example_resource_name>" {
  service_account_id = "projects/<example_resource_id>/serviceAccounts/<example_resource_name>@<example_resource_id>.iam.gserviceaccount.com"  # CRITICAL: scope grant to a specific service account, not the project
  role               = "roles/iam.serviceAccountUser"  # CRITICAL: this role is granted only at the service account level
  member             = "user:<example_resource_name>@example.com"
}

Other

1In Google Cloud Console, go to IAM & Admin > IAM
2Use the filter to find Role: Service Account User
3Remove all project-level bindings for this role and click Save
4Repeat steps 2-3 for Role: Service Account Token Creator
5Do not add these roles at the project level; if needed, grant them on specific service accounts only (IAM & Admin > Service Accounts > select account > Permissions > Grant access)

Check Code

from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.cloudresourcemanager.cloudresourcemanager_client import (
    cloudresourcemanager_client,
)


class iam_no_service_roles_at_project_level(Check):
    def execute(self) -> Check_Report_GCP:
        findings = []
        failed_projects = set()
        for binding in cloudresourcemanager_client.bindings:
            report = Check_Report_GCP(
                metadata=self.metadata(),
                resource=binding,
                resource_id=binding.role,
                resource_name=binding.role if binding.role else "Service Role",
                location=cloudresourcemanager_client.region,
            )
            if binding.role in [
                "roles/iam.serviceAccountUser",
                "roles/iam.serviceAccountTokenCreator",
            ]:
                report.status = "FAIL"
                report.status_extended = f"IAM Users assigned to service role '{binding.role}' at project level {binding.project_id}."
                failed_projects.add(binding.project_id)
                findings.append(report)

        for project in cloudresourcemanager_client.project_ids:
            if project not in failed_projects:
                report = Check_Report_GCP(
                    metadata=self.metadata(),
                    resource=cloudresourcemanager_client.projects[project],
                    project_id=project,
                    location=cloudresourcemanager_client.region,
                )
                report.status = "PASS"
                report.status_extended = f"No IAM Users assigned to service roles at project level {project}."
                findings.append(report)
        return findings