> ## 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.updateserviceaccount

### Event Information

* **Event purpose & scope**
  * `google.iam.admin.v1.UpdateServiceAccount` is fired when a service account’s *metadata* is modified via the IAM Admin API (e.g., display name, description, disabled flag), not when its IAM policy (roles/bindings) is changed.
  * Typical sources: `gcloud iam service-accounts update`, Console edits, or API clients calling `projects.serviceAccounts.patch`.

* **Security & compliance relevance**
  * Changes can affect how a service account is identified, whether it is enabled/disabled, and sometimes can indicate repurposing of an identity—important for SOC 2, ISO 27001, and internal IAM governance.
  * Track for anomalous edits (e.g., unexpected re-enabling of previously disabled accounts) and ensure only authorized roles (e.g., `roles/iam.serviceAccountAdmin`) are performing these actions.

* **Practical monitoring actions**
  * In Cloud Logging, filter on `protoPayload.@type="type.googleapis.com/google.iam.admin.v1.UpdateServiceAccount"` and alert when:
    * `authenticationInfo.principalEmail` is outside approved admin groups, or
    * `requestMetadata.callerSuppliedUserAgent` or source IP is unusual, or
    * `serviceAccount.disabled` flips from `true` to `false`.
  * Feed these logs into SIEM / SCC, and use them as part of periodic IAM reviews and change-control evidence.

### Examples

* **Privilege escalation via role change**
  * An attacker updates a service account used by an internal app to add high-privilege roles (e.g., `roles/owner`, `roles/iam.serviceAccountTokenCreator`) on the project.
  * Impact: Full project takeover (read/write/delete of data, KMS use, billing changes). Violates least-privilege principles in ISO 27001, SOC 2, and CIS GCP.

* **Persistence by key/impersonation enablement**
  * A malicious admin modifies a low-profile service account to allow key creation or to grant `roles/iam.serviceAccountUser` to another principal they control.
  * Impact: Long-lived credentials or impersonation path for persistent access, bypassing identity lifecycle controls (NIST 800-53 AC-2, AC-6).

* **Lateral movement via resource access expansion**
  * The service account for a CI/CD pipeline is updated to include access to additional projects or sensitive APIs (e.g., BigQuery datasets with PII, Cloud Storage backups).
  * Impact: Cross-project lateral movement and data exfiltration, undermining data access controls required by GDPR, HIPAA, and PCI-DSS (principle of data minimization and access segregation).

### Remediation

#### Using Console

* **Immediate containment & investigation (Console + IAM Recommender)**
  * In **IAM & Admin → IAM**, sort by **Type = Service account** and locate the impacted accounts (by name/email). For each:
    * Click the pencil icon, remove high-privilege roles (`roles/owner`, `roles/iam.admin`, `roles/iam.serviceAccountTokenCreator`, broad `*Admin` roles) and any roles not required by the app; click **Save**.
    * In **IAM & Admin → Role recommendations**, review suggestions and apply least-privilege roles where possible; document all changes for ISO 27001/SOC 2 change records.
  * In **IAM & Admin → Audit Logs**, filter by `Resource type = Service Account` and `Method name contains setIamPolicy` or `roles.setIamPolicy` to identify who changed what and when; preserve logs for incident response and compliance (NIST 800‑53 AU-6, IR controls).

* **Lock down service account capabilities (keys, impersonation, lateral movement)**
  * In **IAM & Admin → Service Accounts**:
    * Click each sensitive/low-profile service account → **Keys** tab → delete all unnecessary keys; disable **“Enable key creation”** for admins by removing `roles/iam.serviceAccountKeyAdmin` or similar from their identities in **IAM**.
    * On the **Permissions** tab, remove `roles/iam.serviceAccountUser` and `roles/iam.serviceAccountTokenCreator` grants to any untrusted or unnecessary principals to break impersonation paths; keep only specific workloads/principals that must impersonate (aligns with NIST AC‑2/AC‑6).
  * For CI/CD and cross-project access:
    * In each project’s **IAM** page, restrict the CI/CD service account to tightly scoped roles (e.g., dataset‑specific BigQuery roles, bucket‑level Storage roles) instead of project‑wide or multi-project high-privilege roles.
    * For BigQuery and Cloud Storage, use resource-level permissions: go to **BigQuery → Dataset → Share** or **Cloud Storage → Bucket → Permissions**, remove broad grants and add minimal needed roles (satisfies GDPR/HIPAA/PCI-DSS data minimization and segregation).

* **Prevent recurrence (guardrails & monitoring)**
  * Implement **predefined custom roles and groups**: in **IAM & Admin → Roles**, create least-privilege custom roles for admins and CI/CD; then in **IAM**, assign these instead of primitive roles (`Owner`, `Editor`). Restrict who can assign high-privilege roles by limiting `roles/iam.admin` and `roles/resourcemanager.projectIamAdmin` to a small, controlled group.
  * In **Security → Security Command Center (if enabled)** and **IAM → Audit Logs**, set up alerts (via Cloud Logging → **Logs Router → Sinks** and **Alerting**) for:
    * Any assignment of `roles/owner`, `roles/iam.serviceAccountUser`, `roles/iam.serviceAccountTokenCreator`, `roles/iam.serviceAccountKeyAdmin` to service accounts or users.
    * New key creation events for service accounts and IAM policy changes to CI/CD or low-profile accounts.
  * Regularly review **IAM → Policy Analyzer** and **IAM → Service Accounts** for over-privileged accounts; formalize quarterly access reviews and approvals to support ISO 27001, SOC 2, CIS GCP, and NIST 800‑53 access review requirements.

#### Using CLI

* **Immediate containment & rollback (privilege escalation / persistence / lateral movement)**
  * Identify the compromised service account and list its current bindings and keys:
    * `gcloud iam service-accounts get-iam-policy SA_NAME@PROJECT_ID.iam.gserviceaccount.com --project=PROJECT_ID`
    * `gcloud iam service-accounts keys list --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com --project=PROJECT_ID`
  * Remove high-privilege or persistence-enabling roles from the **service account** and **project-level IAM** (ISO 27001 A.9, CIS GCP IAM):
    * From project IAM:
      * `gcloud projects get-iam-policy PROJECT_ID > policy.yaml`
      * Edit `policy.yaml` to remove bindings like `roles/owner`, `roles/editor`, `roles/iam.serviceAccountTokenCreator`, `roles/iam.serviceAccountUser`, or cross-project roles for the SA, then:
      * `gcloud projects set-iam-policy PROJECT_ID policy.yaml`
    * From SA IAM:
      * `gcloud iam service-accounts get-iam-policy SA_NAME@PROJECT_ID.iam.gserviceaccount.com --project=PROJECT_ID > sa-policy.yaml`
      * Edit to remove `roles/iam.serviceAccountUser`, `roles/iam.serviceAccountKeyAdmin`, or any unwanted member bindings:
      * `gcloud iam service-accounts set-iam-policy SA_NAME@PROJECT_ID.iam.gserviceaccount.com sa-policy.yaml --project=PROJECT_ID`
  * Disable or delete compromised keys and regenerate only if absolutely required (NIST 800-53 AC-2, AC-6; PCI-DSS key management):
    * `gcloud iam service-accounts keys delete KEY_ID --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com --project=PROJECT_ID`
    * For CI/CD / lateral movement risk, also revoke unnecessary cross-project roles: use `gcloud projects get-iam-policy` on all linked projects and remove the SA from sensitive roles (e.g., BigQuery, Storage, KMS).

* **Hardening IAM to prevent recurrence (least privilege, data minimization)**
  * Enforce least privilege per use-case and create dedicated service accounts with scoped roles instead of `roles/owner`/`roles/editor` or broad `*Admin` on the project (SOC 2 CC6, ISO 27001 A.9, GDPR data minimization):
    * Example tightening for CI/CD SA:
      * `gcloud projects add-iam-policy-binding PROJECT_ID --member="serviceAccount:CI_SA@PROJECT_ID.iam.gserviceaccount.com" --role="roles/storage.objectAdmin"`
      * Avoid adding global roles like `roles/bigquery.admin`, prefer dataset-level ACLs and per-project roles.
  * Restrict who can modify service accounts and grant impersonation/keys:
    * Limit `roles/iam.serviceAccountAdmin`, `roles/iam.serviceAccountUser`, `roles/iam.serviceAccountTokenCreator`, and `roles/iam.serviceAccountKeyAdmin` to a small break-glass admin group.
    * Example: remove broad group access:
      * `gcloud projects get-iam-policy PROJECT_ID > policy.yaml`
      * Remove group bindings for these roles, then: `gcloud projects set-iam-policy PROJECT_ID policy.yaml`
  * Use Org Policies and constraints to block risky patterns (supports CIS GCP, HIPAA/PCI segregation):
    * Disable SA key creation where possible:
      * `gcloud resource-manager org-policies allow constraints/iam.disableServiceAccountKeyCreation TRUE --project=PROJECT_ID`
    * Restrict who can impersonate all service accounts:
      * `gcloud resource-manager org-policies allow constraints/iam.allowedPolicyMemberDomains ...` (restrict to corporate domains)
      * Prefer using narrower custom roles instead of wide `roles/iam.serviceAccountUser` on `projects/PROJECT_ID/serviceAccounts/*`.

* **Detection, investigation & compliance alignment**
  * Enable and monitor Cloud Audit Logs for IAM changes, SA key operations, and project-level policy changes; create log-based alerts for high-risk roles or impersonation grants (NIST 800-53 AU-2/AU-6, SOC 2 monitoring):
    * Example high-risk filter:
      * `resource.type="project" AND protoPayload.methodName=("SetIamPolicy" OR "SetServiceAccountPolicy" OR "CreateServiceAccountKey") AND ("roles/owner" OR "roles/iam.serviceAccountUser" OR "roles/iam.serviceAccountTokenCreator" OR "roles/iam.serviceAccountKeyAdmin")`
  * For suspected compromise, revoke active tokens and sessions and rotate upstream app credentials (e.g., CI/CD systems, internal apps) that use the impacted service accounts; re-run access reviews for BigQuery datasets with PII, backup buckets, and KMS keys (GDPR, HIPAA, PCI-DSS segregation).
  * Document the change and remediation steps, link to internal IAM standards (least privilege, no keys unless justified, impersonation controls), and feed lessons learned into access review and change-management processes to satisfy ISO 27001 A.12/A.18 and SOC 2 CC5/CC7.

#### Using Python

* **Immediately detect and revoke over-privileged / persistence-enabling role changes**

  * Use Cloud Audit Logs + Python to detect suspicious role bindings (e.g., `roles/owner`, `roles/iam.serviceAccountTokenCreator`, `roles/iam.serviceAccountUser`, key creation roles) on service accounts, then automatically strip them from project or service account IAM policies.
  * This supports least-privilege and SoD requirements (ISO 27001 A.9, SOC 2 CC6, CIS GCP, NIST 800-53 AC-2/AC-6).

  ```python theme={null}
  from google.cloud import resourcemanager_v3
  from google.iam.v1 import policy_pb2

  PROJECT_ID = "my-project-id"
  SENSITIVE_ROLES = {
      "roles/owner",
      "roles/iam.serviceAccountTokenCreator",
      "roles/iam.serviceAccountUser",
      "roles/iam.serviceAccountKeyAdmin",
      "roles/iam.serviceAccountAdmin",
  }

  def clean_project_policy(project_id: str):
      client = resourcemanager_v3.ProjectsClient()
      project_name = f"projects/{project_id}"
      policy = client.get_iam_policy(request={"resource": project_name})
      new_bindings = []

      for b in policy.bindings:
          if b.role in SENSITIVE_ROLES and any("serviceAccount:" in m for m in b.members):
              # Drop binding or surgically remove service accounts
              filtered_members = [m for m in b.members if not m.startswith("serviceAccount:")]
              if filtered_members:
                  b.members[:] = filtered_members
                  new_bindings.append(b)
          else:
              new_bindings.append(b)

      policy.bindings[:] = new_bindings
      client.set_iam_policy(request={"resource": project_name, "policy": policy})

  if __name__ == "__main__":
      clean_project_policy(PROJECT_ID)
  ```

* **Lock down service account keys and impersonation paths; rotate if compromised**

  * Enumerate service accounts, remove `roles/iam.serviceAccountUser` and key-admin roles from non-admin principals, disable key creation where not required, and rotate keys/credentials if abuse is suspected, aligning with NIST 800-53 AC-2/IA-5 and SOC 2 change management controls.
  * Use Python with the IAM Admin API to (a) remove risky members from service account IAM, (b) disable/delete user-managed keys.

  ```python theme={null}
  from google.cloud import iam_admin_v1

  PROJECT_ID = "my-project-id"
  SENSITIVE_MEMBER_PREFIXES = {"allUsers", "allAuthenticatedUsers"}
  RISKY_ROLES = {
      "roles/iam.serviceAccountUser",
      "roles/iam.serviceAccountTokenCreator",
      "roles/iam.serviceAccountKeyAdmin",
  }

  def harden_service_account(sa_email: str):
      client = iam_admin_v1.IAMClient()
      name = f"projects/{PROJECT_ID}/serviceAccounts/{sa_email}"

      # Clean IAM policy on the service account
      policy = client.get_iam_policy(request={"resource": name})
      new_bindings = []
      for b in policy.bindings:
          if b.role in RISKY_ROLES:
              safe_members = [
                  m for m in b.members
                  if not any(m.startswith(p) for p in SENSITIVE_MEMBER_PREFIXES)
              ]
              # Optionally restrict to a central break-glass group only
              # safe_members = [m for m in safe_members if m == "group:breakglass-admins@org.com"]
              if safe_members:
                  b.members[:] = safe_members
                  new_bindings.append(b)
          else:
              new_bindings.append(b)

      policy.bindings[:] = new_bindings
      client.set_iam_policy(request={"resource": name, "policy": policy})

      # Disable/delete existing user-managed keys for this SA
      key_client = iam_admin_v1.IAMClient()
      for key in key_client.list_service_account_keys(
          request={
              "name": name,
              "key_types": [iam_admin_v1.ListServiceAccountKeysRequest.KeyType.USER_MANAGED],
          }
      ).keys:
          key_client.delete_service_account_key(request={"name": key.name})

  if __name__ == "__main__":
      harden_service_account("sa-internal-app@my-project-id.iam.gserviceaccount.com")
  ```

* **Constrain lateral movement by scoping CI/CD and cross-project access; continuously verify**

  * Review and constrain CI/CD service account permissions to least privilege (project- or resource-scoped roles instead of `roles/editor/owner`, no broad BigQuery/Storage access), and ensure separate accounts per environment/project to satisfy GDPR/HIPAA/PCI-DSS segregation and data-minimization.
  * Use Python to scan for CI/CD SAs with cross-project or high-risk roles and remove/replace them with narrower roles.

  ```python theme={null}
  from google.cloud import resourcemanager_v3

  ORG_PROJECTS = ["prod-project", "stg-project", "dev-project"]
  CICD_SA_SUFFIX = "-cicd@"
  OVERBROAD_ROLES = {
      "roles/owner",
      "roles/editor",
      "roles/bigquery.admin",
      "roles/storage.admin",
  }

  def find_and_downgrade_cicd(project_id: str):
      client = resourcemanager_v3.ProjectsClient()
      res = f"projects/{project_id}"
      policy = client.get_iam_policy(request={"resource": res})

      for b in list(policy.bindings):
          if b.role in OVERBROAD_ROLES:
              risky_members = [
                  m for m in b.members
                  if m.startswith("serviceAccount:") and CICD_SA_SUFFIX in m
              ]
              if risky_members:
                  # Remove CI/CD SAs from broad roles; keep others
                  b.members[:] = [m for m in b.members if m not in risky_members]
                  if not b.members:
                      policy.bindings.remove(b)

      client.set_iam_policy(request={"resource": res, "policy": policy})

  if __name__ == "__main__":
      for p in ORG_PROJECTS:
          find_and_downgrade_cicd(p)
  ```
