> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Google.iam.admin.v1.createserviceaccount remediation

### Event Information

* **Event purpose & scope**
  * `google.iam.admin.v1.CreateServiceAccount` indicates that a new IAM service account was created in a GCP project (via Console, gcloud, API, or Terraform) using the IAM Admin API.
  * The payload typically includes the service account name, email, display name, and the actor (user/service) that initiated the creation.

* **Security & compliance relevance (e.g., ISO 27001, SOC 2, PCI-DSS)**
  * Creation of service accounts introduces new identities that can hold roles and keys; this is a sensitive event for access control and least-privilege enforcement.
  * It should be monitored and logged in Cloud Audit Logs and forwarded to SIEM for anomaly detection, owner validation, and periodic access reviews.

* **Practical controls & monitoring**
  * Set up log-based alerts (Cloud Logging) on `protoPayload.methodName="google.iam.admin.v1.CreateServiceAccount"` to notify security/operations when new service accounts are created.
  * Enforce policies via Organization Policy / IAM conditions and deployment pipelines (e.g., Terraform with code review) to restrict who can create service accounts and ensure naming conventions, owner tagging, and rotation/usage of keys align with compliance requirements.

### Examples

* **Over-privileged / Mis-scoped service account for workloads**
  * A new service account is created and then granted broad roles like `roles/owner`, `roles/editor`, or project-level `roles/iam.serviceAccountTokenCreator`. This allows lateral movement, privilege escalation, and token abuse if the workload or service account key is compromised.
  * Compliance: Violates least-privilege requirements in ISO 27001, SOC 2, PCI DSS (e.g., PCI DSS 7 – access needs to be restricted to business need-to-know).

* **Shadow / Backdoor service accounts created outside standard process**
  * An attacker or insider with IAM admin rights creates a hidden service account (e.g., not registered in CMDB/ITSM) and binds it to critical resources, then uses it for persistence or data exfiltration.
  * Compliance: Breaks access governance and account lifecycle controls (e.g., ISO 27001 A.9, SOC 2 CC6, NIST 800-53 AC family).

* **Service accounts with user-like capabilities**
  * Service account is created with roles that allow impersonating users or other service accounts (`roles/iam.serviceAccountUser`, `roles/iam.serviceAccountTokenCreator` across the project), enabling bypass of SSO/MFA, audit trails tied to the wrong principal, and impersonation of privileged identities.
  * Compliance: Undermines identity assurance and non-repudiation (e.g., PCI DSS 10, SOX logging/traceability, NIST 800-53 AU/IA families).

### Remediation

#### Using Console

* **Remove broad / mis-scoped roles and re-scope to least privilege**
  * In GCP Console: Go to **IAM & Admin → IAM** → locate the over-privileged service account → click **Edit principal** (pencil icon) → remove broad roles (`Owner`, `Editor`, project-wide `Service Account Token Creator`, etc.).
  * Create or use minimal custom roles: **IAM & Admin → Roles → Create Role** → add only the specific permissions needed for the workload → return to **IAM** and assign this custom role **only at the narrowest scope** (folder/project/specific resource) required.
  * For compliance (ISO 27001, SOC 2, PCI DSS 7): document the new role design, keep an approval record (e.g., in your ITSM), and enforce change control for any future privilege increases.

* **Detect and remove shadow/backdoor service accounts; enforce lifecycle controls**
  * Discover rogue SAs: Go to **IAM & Admin → Service Accounts** → filter by project and compare against your CMDB/ITSM; look for SAs with no owner record, unusual names, or created by unexpected users (check **Service account details → Audit logs**).
  * For any unapproved SA: in **Service Accounts**, click the SA → **Delete** (or first revoke its bindings via **IAM & Admin → IAM** by removing all roles that reference that SA). Also remove any keys: **Service account → Keys → Delete** for each key.
  * Implement governance: restrict who can create SAs and bind roles by going to **IAM** and removing `roles/iam.serviceAccountAdmin`, `roles/iam.admin`, and `roles/resourcemanager.projectIamAdmin` from general users; keep these only in tightly controlled admin groups, and review SA inventory periodically against compliance requirements (ISO 27001 A.9, SOC 2 CC6, NIST AC).

* **Remove user-like capabilities and impersonation; constrain service account usage**
  * In **IAM & Admin → IAM**, search for principals with `roles/iam.serviceAccountUser` or `roles/iam.serviceAccountTokenCreator` at project level; click **Edit principal** and remove project-wide bindings. Reassign these roles only on **specific service accounts** where absolutely necessary: open the SA under **Service Accounts → Show Info Panel → Permissions → Grant Access**, and grant `Service Account User` only to the minimal group/workload.
  * Disable broad impersonation: avoid granting SAs roles that allow impersonating users (e.g., custom roles with `impersonate` permissions or `roles/iam.serviceAccountTokenCreator` on many SAs). Where required, scope to a single SA and enforce usage through workload identity (e.g., GCE/GKE default SA) rather than keys.
  * For compliance (PCI DSS 10, SOX, NIST AU/IA): ensure auditability by confirming in **IAM & Admin → Audit Logs** that actions are performed by distinct, named principals; document which SAs are allowed to impersonate whom, require approvals, and periodically review these bindings.

#### Using CLI

* **Constrain over-privileged / mis-scoped service accounts**
  * Identify and review risky bindings (e.g., `roles/owner`, `roles/editor`, wide `serviceAccountTokenCreator`) and export for approval:
    ```bash theme={null}
    gcloud projects get-iam-policy PROJECT_ID --format=json > iam-policy.json
    gcloud iam service-accounts list --project=PROJECT_ID
    gcloud projects get-iam-policy PROJECT_ID \
      --flatten="bindings[].members" \
      --filter="bindings.members:serviceAccount:" \
      --format="table(bindings.role, bindings.members)"
    ```
  * Remove broad roles and replace with least-privilege, role-scoped bindings (prefer custom roles and per-service-project scope):
    ```bash theme={null}
    # Remove project-level owner/editor from SA
    gcloud projects remove-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/editor"

    # Grant minimal custom role at narrow resource scope
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
      --role="projects/PROJECT_ID/roles/CUSTOM_MIN_ROLE"
    ```
  * Enforce prevention controls aligned with ISO 27001 / PCI DSS 7 (policy-as-code, org policy, CI checks):
    ```bash theme={null}
    # Example org policy to disable basic roles at project level
    gcloud org-policies set-policy policy.yaml --organization=ORG_ID
    # policy.yaml: constraint=iam.disableServiceAccountKeyCreation / iam.allowedPolicyMemberDomains etc.
    ```

* **Detect and remove shadow / backdoor service accounts**
  * Discover unregistered / shadow SAs and bindings by comparing GCP to CMDB lists:
    ```bash theme={null}
    gcloud iam service-accounts list --project=PROJECT_ID \
      --format="table(email,disabled,oauth2ClientId)"
    gcloud projects get-iam-policy PROJECT_ID \
      --flatten="bindings[].members" \
      --filter="bindings.members:serviceAccount:" \
      --format="table(bindings.role, bindings.members)"
    ```
  * Disable or delete backdoor SAs (after impact review) and strip their bindings to meet ISO 27001 A.9 / NIST AC lifecycle controls:
    ```bash theme={null}
    # Remove all bindings for backdoor SA
    gcloud projects get-iam-policy PROJECT_ID --format=json > policy.json
    # edit policy.json to remove that SA, then:
    gcloud projects set-iam-policy PROJECT_ID policy.json

    # Optionally disable before delete
    gcloud iam service-accounts disable BACKDOOR_SA@PROJECT_ID.iam.gserviceaccount.com
    gcloud iam service-accounts delete BACKDOOR_SA@PROJECT_ID.iam.gserviceaccount.com
    ```
  * Hardening and governance (prevent future shadow SAs): require Terraform/Deployment Manager + approval for SA creation and monitor with log-based alerts:
    ```bash theme={null}
    gcloud logging sinks create sa-creation-sink STORAGE_BUCKET \
      --log-filter='protoPayload.methodName="google.iam.admin.v1.CreateServiceAccount"'
    ```

* **Restrict service accounts with user-like capabilities (impersonation / token creation)**
  * Enumerate who can impersonate or mint tokens (violates non-repudiation in PCI DSS 10 / SOX if overly broad):
    ```bash theme={null}
    # List Service Account User / TokenCreator bindings
    gcloud projects get-iam-policy PROJECT_ID \
      --flatten="bindings[].members" \
      --filter='bindings.role:roles/iam.serviceAccountUser OR bindings.role:roles/iam.serviceAccountTokenCreator' \
      --format="table(bindings.role, bindings.members)"
    ```
  * Remove project-wide impersonation and re-scope to specific identities and SAs only where needed:
    ```bash theme={null}
    gcloud projects remove-iam-policy-binding PROJECT_ID \
      --member="user:USER@EXAMPLE.COM" \
      --role="roles/iam.serviceAccountUser"

    # Grant SA User only on specific SA
    gcloud iam service-accounts add-iam-policy-binding SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
      --member="user:USER@EXAMPLE.COM" \
      --role="roles/iam.serviceAccountUser"
    ```
  * Enforce controls that keep SA usage non-interactive and traceable: disallow SA keys, require Workload Identity Federation, and alert on high-risk methods:
    ```bash theme={null}
    # Org policy to disable service account key creation
    gcloud org-policies set-policy disable-sa-keys.yaml --organization=ORG_ID
    # disable-sa-keys.yaml uses constraint: iam.disableServiceAccountKeyCreation

    # Alert on token creation / signBlob/signJwt
    gcloud logging sinks create sa-token-abuse-sink PUBSUB_TOPIC \
      --log-filter='protoPayload.methodName=("google.iam.credentials.v1.IAMCredentials.GenerateAccessToken" OR "google.iam.credentials.v1.IAMCredentials.SignJwt" OR "google.iam.credentials.v1.IAMCredentials.SignBlob")'
    ```

#### Using Python

* **Detect and right-size over-privileged / mis-scoped service accounts**

  * Enumerate service accounts and flag broad roles (`roles/owner`, `roles/editor`, project-level `roles/iam.serviceAccount*`); export for review and replace with least-privilege custom or predefined roles.
    ```python theme={null}
    from google.cloud import resourcemanager_v3, iam_v1

    project_id = "YOUR_PROJECT_ID"
    broad_roles = {
        "roles/owner",
        "roles/editor",
        "roles/iam.serviceAccountTokenCreator",
        "roles/iam.serviceAccountUser",
    }

    def get_project_number(project_id):
        client = resourcemanager_v3.ProjectsClient()
        proj = client.get_project(name=f"projects/{project_id}")
        return proj.name.split("/")[-1]

    def list_bindings_with_broad_roles(project_id):
        project_number = get_project_number(project_id)
        resource = f"projects/{project_number}"
        client = iam_v1.IAMPolicyClient()
        policy = client.get_iam_policy(resource=resource)
        for b in policy.bindings:
            if b.role in broad_roles:
                print(f"ROLE: {b.role}")
                for m in b.members:
                    if m.startswith("serviceAccount:"):
                        print(f"  SA: {m}")

    if __name__ == "__main__":
        list_bindings_with_broad_roles(project_id)
    ```
  * To remediate, adjust the binding: remove broad role from SA and add granular roles on specific resources (e.g., specific GCS buckets, Pub/Sub topics).
    ```python theme={null}
    from google.cloud import iam_v1

    project_id = "YOUR_PROJECT_ID"
    sa_email = "sa-name@YOUR_PROJECT_ID.iam.gserviceaccount.com"
    role_to_remove = "roles/editor"
    roles_to_add = ["roles/storage.objectViewer"]  # example

    def update_sa_bindings(project_id, sa_email, role_to_remove, roles_to_add):
        resource = f"projects/{project_id}"
        client = iam_v1.IAMPolicyClient()
        policy = client.get_iam_policy(resource=resource)

        member = f"serviceAccount:{sa_email}"
        new_bindings = []
        for b in policy.bindings:
            if b.role == role_to_remove:
                b.members[:] = [m for m in b.members if m != member]
                if not b.members:
                    continue
            new_bindings.append(b)
        policy.bindings[:] = new_bindings

        for r in roles_to_add:
            found = False
            for b in policy.bindings:
                if b.role == r:
                    if member not in b.members:
                        b.members.append(member)
                    found = True
                    break
            if not found:
                policy.bindings.append(
                    iam_v1.Binding(role=r, members=[member])
                )

        client.set_iam_policy(resource=resource, policy=policy)

    if __name__ == "__main__":
        update_sa_bindings(project_id, sa_email, role_to_remove, roles_to_add)
    ```
  * Governance: enforce least-privilege via CI/CD checks and Org Policies (`constraints/iam.allowedPolicyMemberDomains`, `constraints/iam.disableServiceAccountKeyCreation`), and maintain approvals/records for ISO 27001/SOC 2/PCI DSS evidence.

***

* **Detect and remove shadow/backdoor service accounts**

  * List all service accounts and compare against an “approved” inventory (from CMDB/ITSM) to detect unregistered SAs; immediately review and, if unauthorized, disable and remove bindings.
    ```python theme={null}
    from google.cloud import iam_credentials_v1
    from google.cloud import iam_v1

    project_id = "YOUR_PROJECT_ID"
    approved_sas = {
        "approved1@YOUR_PROJECT_ID.iam.gserviceaccount.com",
        "approved2@YOUR_PROJECT_ID.iam.gserviceaccount.com",
    }

    def list_service_accounts(project_id):
        client = iam_v1.IAMClient()
        parent = f"projects/{project_id}"
        return list(client.list_service_accounts(name=parent))

    if __name__ == "__main__":
        sas = list_service_accounts(project_id)
        for sa in sas:
            if sa.email not in approved_sas:
                print(f"UNAPPROVED SA: {sa.email}")
    ```
  * For any unapproved SA, revoke IAM bindings and disable/delete account, keeping logs for audit:
    ```python theme={null}
    from google.cloud import iam_v1

    project_id = "YOUR_PROJECT_ID"
    sa_email = "suspicious@YOUR_PROJECT_ID.iam.gserviceaccount.com"

    def remove_sa_from_project_bindings(project_id, sa_email):
        resource = f"projects/{project_id}"
        client = iam_v1.IAMPolicyClient()
        policy = client.get_iam_policy(resource=resource)
        member = f"serviceAccount:{sa_email}"

        new_bindings = []
        for b in policy.bindings:
            b.members[:] = [m for m in b.members if m != member]
            if b.members:
                new_bindings.append(b)
        policy.bindings[:] = new_bindings
        client.set_iam_policy(resource=resource, policy=policy)

    def disable_and_delete_sa(project_id, sa_email):
        client = iam_v1.IAMClient()
        name = f"projects/{project_id}/serviceAccounts/{sa_email}"
        client.disable_service_account(name=name)
        # wait / validate, then:
        client.delete_service_account(name=name)

    if __name__ == "__main__":
        remove_sa_from_project_bindings(project_id, sa_email)
        disable_and_delete_sa(project_id, sa_email)
    ```
  * Governance: restrict who can create SAs (`roles/iam.serviceAccountAdmin`) at org/folder level, require change tickets for any SA, and periodically reconcile against CMDB to satisfy ISO 27001 A.9, SOC 2 CC6, NIST AC controls.

***

* **Limit service accounts with user-like/impersonation capabilities**

  * Enumerate bindings for `roles/iam.serviceAccountUser` and `roles/iam.serviceAccountTokenCreator` and verify they are only granted to tightly scoped technical identities on specific SAs, never broad “project-wide” or to generic groups.
    ```python theme={null}
    from google.cloud import iam_v1

    project_id = "YOUR_PROJECT_ID"
    sensitive_roles = {
        "roles/iam.serviceAccountUser",
        "roles/iam.serviceAccountTokenCreator",
    }

    def list_impersonation_bindings(project_id):
        resource = f"projects/{project_id}"
        client = iam_v1.IAMPolicyClient()
        policy = client.get_iam_policy(resource=resource)
        for b in policy.bindings:
            if b.role in sensitive_roles:
                print(f"SENSITIVE ROLE: {b.role}")
                for m in b.members:
                    print(f"  MEMBER: {m}")

    if __name__ == "__main__":
        list_impersonation_bindings(project_id)
    ```
  * Where over-broad, remove project-level impersonation and re-grant at the individual service account resource path (e.g., `projects/{p}/serviceAccounts/{sa}`) only to approved identities, ensuring user access still flows through SSO/MFA and that logs clearly attribute actions.
    ```python theme={null}
    from google.cloud import iam_v1

    project_id = "YOUR_PROJECT_ID"
    sa_email = "target-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com"
    member_to_allow = "user:admin@example.com"
    role = "roles/iam.serviceAccountUser"

    def set_sa_level_impersonation(project_id, sa_email, member):
        resource = f"projects/{project_id}/serviceAccounts/{sa_email}"
        client = iam_v1.IAMPolicyClient()
        policy = client.get_iam_policy(resource=resource)

        for b in policy.bindings:
            if b.role == role and member in b.members:
                return  # already present

        policy.bindings.append(
            iam_v1.Binding(role=role, members=[member])
        )
        client.set_iam_policy(resource=resource, policy=policy)

    if __name__ == "__main__":
        set_sa_level_impersonation(project_id, sa_email, member_to_allow)
    ```
  * Governance: enable Cloud Audit Logs for all admin/data access, monitor SA-impersonation events (e.g., `GenerateAccessToken`, `SignJwt`), and document mappings of who may impersonate which SA to satisfy PCI DSS 10, SOX, and NIST AU/IA non‑repudiation requirements.
