> ## 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.uploadserviceaccountkey remediation

### Event Information

* **Event meaning and risk**
  * `google.iam.admin.v1.UploadServiceAccountKey` is generated when a *user uploads an existing service account key* (typically a user-managed JSON key) to a service account, rather than creating a new key.
  * This usually indicates importing a key that was generated or stored outside GCP, which increases the risk of key sprawl and loss of key lifecycle control.

* **Practical monitoring and response**
  * Log fields to review: `authenticationInfo.principalEmail` (who uploaded), `requestMetadata.callerIp`, `serviceAccount` in the request, and `methodName` to confirm the upload operation.
  * Treat unexpected occurrences as potential incidents: verify business justification with the owner, rotate/delete the uploaded key if not strictly required, and check for related access or anomalous activity using that service account.

* **Compliance and governance implications**
  * For standards like ISO 27001, SOC 2, PCI DSS, and HIPAA, unmanaged or imported keys can violate key management and access control requirements.
  * Enforce policies to:
    * Disable or strictly limit user-managed service account keys (via Organization Policies).
    * Mandate use of Workload Identity / workload identity federation instead of long‑lived keys.
    * Alert on this event type and include it in periodic access and key reviews.

### Examples

* **Exfiltration via rogue key upload to sensitive service account**
  * An attacker (or overly privileged user) uploads a new key to a high-privilege service account (e.g., project editor / org admin SA), then uses that key outside GCP to call Google APIs, bypassing corporate SSO/MFA and SOC monitoring.
  * Impact: Persistent unauthorized access violating least-privilege and authentication controls required by ISO 27001, SOC 2, and CIS GCP Benchmark (e.g., control around minimizing long‑lived keys).

* **Compliance breach from unmanaged, long‑lived credentials**
  * A team automates `UploadServiceAccountKey` to distribute keys to CI/CD systems or contractors without lifecycle controls, logging, or rotation, leading to key sprawl and inability to prove full key inventory and revocation during audits.
  * Impact: Non-compliance with PCI DSS (3.5, 8.x), HIPAA, and NIST 800‑53 requirements for strong credential management, key protection, and traceability.

* **Lateral movement and privilege escalation using uploaded keys**
  * After gaining limited access, an attacker uploads keys to multiple service accounts, then uses those keys to enumerate and access other projects or datasets (e.g., BigQuery, GCS) from external infrastructure, blending in with normal service traffic.
  * Impact: Breach of data segregation and access control mandates (GDPR, FedRAMP, NIST AC/IA families); makes incident response harder since activity appears as legitimate SA usage rather than user logins.

### Remediation

#### Using Console

* **Immediately contain & investigate rogue / long‑lived keys (per SA)**
  * In GCP Console: IAM & Admin → Service Accounts → select sensitive SA → **KEYS** tab → under “User‑managed keys” remove any unknown/unapproved keys (`DELETE`), then under “Activity” review `google.iam.admin.v1.*` events for `UploadServiceAccountKey` and note the actor/IP/time.
  * In Logs Explorer: filter
    ```text theme={null}
    resource.type="service_account"
    protoPayload.methodName="google.iam.admin.v1.IAM.UploadServiceAccountKey"
    ```
    Export to SIEM; identify which SAs and keys were affected, where the keys were used (correlate with `AuditData.authenticationInfo.serviceAccountKeyName`), and revoke any derived access (e.g., tokens, sessions).
  * For compliance evidence (ISO 27001/SOC 2/PCI/HIPAA/NIST): document keys removed, time of revocation, impacted systems, and user/service identities; open an incident ticket and attach logs demonstrating containment and inventory of all remaining keys.

* **Lock down key creation / use and migrate away from downloaded keys**
  * In Console: IAM & Admin → IAM → **Roles** → ensure only a tightly controlled group has `iam.serviceAccountKeys.create` / `UploadServiceAccountKey`; remove these from broad roles (e.g., custom “admin” roles) and from regular project editors. Use separate “Key Admin” role only in a secure admin project.
  * In Console: IAM & Admin → Organization Policies → set at org/folder:
    * `constraints/iam.disableServiceAccountKeyCreation` = **Customized** → **Deny all** (except in dedicated break‑glass projects via policy exceptions).
    * `constraints/iam.allowedPolicyMemberDomains` to restrict who can be granted SA access; avoid adding external principals that can use keys off‑corp.\
      Migrate CI/CD and contractors to **Workload Identity Federation**, Cloud Build SA, or GCE/GKE/GCF default service identities; update pipelines to **stop using JSON keys** and rotate/remove any still in use.
  * For long‑lived existing keys: inventory via Cloud Shell:
    ```bash theme={null}
    gcloud iam service-accounts keys list --iam-account SA_NAME@PROJECT_ID.iam.gserviceaccount.com
    ```
    Create a deprecation plan (notify owners, rotate, cut‑off date), then delete old keys in Console (**Service account → KEYS → DELETE**) and record key IDs, dates, and owners for PCI/NIST audit trails.

* **Harden detection, least privilege, and lateral‑movement prevention**
  * Set up alerting: in Monitoring → Alerting → Create Policy, with logs‑based metrics on:
    * `UploadServiceAccountKey`, `CreateServiceAccountKey`, `ServiceAccountKey.Delete`.
    * SA usage from unusual IPs/geos (via `protoPayload.requestMetadata.callerIp`) and from non‑corporate networks; forward to SIEM/SOC.\
      Tune alerts to fire immediately for uploads on high‑privilege SAs and for any key creation where org policy should block it (indicates misconfig or exception abuse).
  * Reduce SA blast radius: per sensitive SA in Console → **Permissions** tab, remove broad roles like `Editor`/`Owner`; grant minimum roles on specific projects/resources only. Use **separate SAs per app/tenant**, restrict to specific BigQuery datasets/GCS buckets, and prevent cross‑project use by not granting SA roles outside its home project unless justified and approved.
  * Enhance IR & compliance alignment: define a runbook that, upon detection, (1) disables/deletes keys, (2) scopes access via IAM review, (3) reprocesses BigQuery/GCS access logs for that SA, (4) documents all steps and timestamps. Map the runbook to ISO 27001 A.9/A.10, SOC 2 CC6/CC7, PCI 3.5/8.x, NIST 800‑53 AC/IA/CM, and keep it referenced in your audit documentation.

#### Using CLI

* **Immediate containment & forensic cleanup of rogue keys**
  * List and delete unauthorized user‑managed keys on high‑privilege service accounts; consider temporarily disabling or rotating the SA:
    * List all keys for a SA:
      ```bash theme={null}
      gcloud iam service-accounts keys list \
        --iam-account sa-name@project-id.iam.gserviceaccount.com \
        --project project-id
      ```
    * Delete specific keys (by KEY\_ID from above):
      ```bash theme={null}
      gcloud iam service-accounts keys delete KEY_ID \
        --iam-account sa-name@project-id.iam.gserviceaccount.com \
        --project project-id
      ```
    * Optionally disable / re-enable SA during incident:
      ```bash theme={null}
      gcloud iam service-accounts disable sa-name@project-id.iam.gserviceaccount.com --project project-id
      gcloud iam service-accounts enable sa-name@project-id.iam.gserviceaccount.com --project project-id
      ```
  * Investigate access using Cloud Audit Logs and Cloud Logging for `google.iam.admin.v1.IAM.UploadServiceAccountKey` events (who, when, from where, to which SA) and correlate with API usage (BigQuery, GCS, etc.) for potential data exfiltration, documenting for ISO 27001/SOC 2/NIST evidence.

* **Hardening: prevent new key uploads & eliminate long‑lived keys**
  * Enforce **no user‑managed keys** for sensitive SAs using Org Policy and IAM:
    * Set org policy to disallow SA key creation (at org/folder/project as appropriate):
      ```bash theme={null}
      gcloud org-policies set-policy policy.yaml \
        --organization=ORG_ID
      ```
      `policy.yaml` example (for `constraints/iam.disableServiceAccountKeyCreation`):
      ```yaml theme={null}
      name: organizations/ORG_ID/policies/iam.disableServiceAccountKeyCreation
      spec:
        rules:
        - enforce: true
      ```
    * Remove `roles/iam.serviceAccountKeyAdmin` / `roles/iam.serviceAccountAdmin` from users/groups that should not manage keys:
      ```bash theme={null}
      gcloud projects remove-iam-policy-binding PROJECT_ID \
        --member=user:alice@example.com \
        --role=roles/iam.serviceAccountKeyAdmin
      ```
  * Replace downloaded keys with **Workload Identity Federation / GCE default SA** where possible to meet PCI DSS, HIPAA, and NIST 800‑53 key‑management requirements:
    * For GKE/Compute: bind SA to workload instead of distributing a key:
      ```bash theme={null}
      gcloud iam service-accounts add-iam-policy-binding \
        sa-name@project-id.iam.gserviceaccount.com \
        --member="serviceAccount:project-id.svc.id.goog[ns/sa]" \
        --role="roles/iam.workloadIdentityUser"
      ```

* **Ongoing monitoring, least privilege, and lateral‑movement control**
  * Continuously monitor and alert on key‑related and high‑risk SA events with Cloud Logging / SCC:
    * Create log‑based metric on `UploadServiceAccountKey`, `CreateServiceAccountKey`, `ServiceAccountKey.deleted`, and use it in Alerting.
    * Example filter:
      ```text theme={null}
      protoPayload.methodName=("google.iam.admin.v1.IAM.UploadServiceAccountKey" OR
                               "google.iam.admin.v1.IAM.CreateServiceAccountKey")
      ```
  * Apply strict least‑privilege roles to high‑value SAs (no `roles/editor`, minimize `roles/owner/orgAdmin`), and segment projects/datasets to reduce blast radius (supporting GDPR, FedRAMP, NIST AC/IA):
    * View bindings on a SA to find excessive privileges:
      ```bash theme={null}
      gcloud projects get-iam-policy PROJECT_ID \
        --filter="bindings.members:sa-name@project-id.iam.gserviceaccount.com" \
        --format="yaml(bindings.role,bindings.members)"
      ```
  * For CI/CD or contractor use, enforce short‑lived credentials with federation or Access Context Manager, document key inventory and rotation policy, and periodically enumerate all SA keys org‑wide for audits:
    * List all SAs and keys per project (scriptable for org‑wide inventory):
      ```bash theme={null}
      gcloud iam service-accounts list --project PROJECT_ID --format="value(email)" | \
      while read SA; do
        gcloud iam service-accounts keys list --iam-account "$SA" --project PROJECT_ID
      done
      ```

#### Using Python

* **Immediately detect, revoke, and lock down SA keys (GCPIAM + Monitoring)**
  * Enable Cloud Audit Logs + Cloud Logging log sinks for `google.iam.admin.v1.IAM.UploadServiceAccountKey` and `google.iam.admin.v1.IAM.CreateServiceAccountKey`, and create alerting policies on these methods (preferably “no one should call this” in production).
  * Use Python + GCPIAM (IAM API) to enumerate and revoke existing user‑managed keys on sensitive SAs, and enforce `DISABLE_SERVICE_ACCOUNT_KEY_CREATION` via org policy (`constraints/iam.disableServiceAccountKeyCreation`) except for tightly controlled break‑glass projects:
    ```python theme={null}
    from google.oauth2 import service_account
    from googleapiclient.discovery import build

    PROJECT_ID = "my-project"
    SVC_EMAILS = ["high-priv-sa@my-project.iam.gserviceaccount.com"]

    def list_keys(iam, sa_email):
        name = f"projects/{PROJECT_ID}/serviceAccounts/{sa_email}"
        return iam.projects().serviceAccounts().keys().list(
            name=name, keyTypes="USER_MANAGED"
        ).execute().get("keys", [])

    def disable_key(iam, key_name):
        iam.projects().serviceAccounts().keys().disable(name=key_name).execute()

    def main():
        creds = service_account.Credentials.from_service_account_file(
            "admin-sa.json",
            scopes=["https://www.googleapis.com/auth/cloud-platform"],
        )
        iam = build("iam", "v1", credentials=creds)
        for sa in SVC_EMAILS:
            for key in list_keys(iam, sa):
                print(f"Disabling key: {key['name']}")
                disable_key(iam, key["name"])

    if __name__ == "__main__":
        main()
    ```
  * Map to compliance: enforce key minimization and strong auth (ISO 27001 A.9/A.10, SOC 2 CC6/CC7, CIS GCP 1.3/1.4, PCI 8.x, NIST 800‑53 IA/AC/SC) by formally documenting that user‑managed SA keys are prohibited except under approved exceptions, with emergency revocation runbook using the above scripts.

* **Migrate off long‑lived keys to Workload Identity / short‑lived tokens and control CI/CD usage**
  * Replace `UploadServiceAccountKey`‑based automations with: GKE Workload Identity / Workload Identity Federation for GitHub, GitLab, Jenkins, etc., or short‑lived OAuth tokens via `gcloud auth application-default print-access-token`; block SA key creation in CI/CD repos and pipelines.
  * Implement an inventory & rotation control using Python to continuously discover SAs with user‑managed keys and fail compliance if any are found outside an allowlist (export to CSV for auditors):
    ```python theme={null}
    import csv
    from google.oauth2 import service_account
    from googleapiclient.discovery import build

    ORG_PROJECTS = ["proj-a", "proj-b"]  # ideally fetched via Cloud Resource Manager

    def list_sa_keys_for_project(project_id, iam):
        svc_accounts = iam.projects().serviceAccounts().list(
            name=f"projects/{project_id}"
        ).execute().get("accounts", [])
        rows = []
        for sa in svc_accounts:
            keys = iam.projects().serviceAccounts().keys().list(
                name=sa["name"], keyTypes="USER_MANAGED"
            ).execute().get("keys", [])
            for k in keys:
                rows.append({
                    "project": project_id,
                    "service_account": sa["email"],
                    "key_name": k["name"],
                    "valid_after": k.get("validAfterTime", ""),
                    "valid_before": k.get("validBeforeTime", ""),
                })
        return rows

    def main():
        creds = service_account.Credentials.from_service_account_file(
            "org-admin-sa.json",
            scopes=["https://www.googleapis.com/auth/cloud-platform"],
        )
        iam = build("iam", "v1", credentials=creds)
        all_rows = []
        for p in ORG_PROJECTS:
            all_rows.extend(list_sa_keys_for_project(p, iam))
        with open("sa_keys_inventory.csv", "w", newline="") as f:
            writer = csv.DictWriter(
                f, fieldnames=["project", "service_account", "key_name", "valid_after", "valid_before"]
            )
            writer.writeheader()
            writer.writerows(all_rows)

    if __name__ == "__main__":
        main()
    ```
  * Use this inventory as evidence for PCI 3.5/8, HIPAA, SOC 2, NIST 800‑53 (AU, IA, SC), and configure policy-as-code (Terraform Validator / Policy Controller) to reject any `google_service_account_key` resources in IaC.

* **Constrain lateral movement, improve attribution, and harden monitoring/IR**
  * Restrict SA scope: remove broad roles (`roles/editor`, `roles/owner`) from SAs, use least‑privilege custom roles, separate duties by project, and enforce VPC‑SC / per‑project isolation; disable SA impersonation from untrusted principals using IAM Conditions (e.g., source IP / principal attributes).
  * Implement SA behavior monitoring: export audit logs to a SIEM, correlate SA calls with expected workloads (IP ranges, user agents, time windows); alert when high‑risk SAs are used from the internet or from unexpected geos; build IR playbooks that: (1) disable SA keys, (2) temporarily disable SA, (3) revoke tokens (`gcloud auth revoke` from compromised hosts), and (4) re‑grant access via Workload Identity.
  * For compliance (GDPR, FedRAMP, NIST AC/IA), document that service accounts are non‑human identities with traceable usage: require per‑service SA, no sharing across teams, mandatory logging retention, and periodic Python‑driven reviews of who can `iam.serviceAccountKeys.create` or `UploadServiceAccountKey` on each SA (use Access Analyzer / IAM Policy Analyzer to validate).
