Google.IAM.Admin.V1.Setiampolicy Remediation
Event Information
-
Event purpose & scope
google.iam.admin.v1.SetIamPolicyis generated when an IAM policy is set or replaced on a GCP resource (e.g., project, folder, organization, service account, some Google Cloud services).- It typically originates from calls to
setIamPolicyvia gcloud, console, or API, and can overwrite existing bindings if not using properupdateMask/ conditional updates.
-
Security & compliance implications
- This event indicates privilege changes (add/remove roles, modify members, or adjust conditional bindings) and is critical for SOC 2, ISO 27001, and PCI-DSS controls around access management and least privilege.
- It should be monitored as a high-sensitivity change: alert on additions of high-privilege roles (e.g.,
roles/owner,roles/editor,roles/iam.serviceAccountTokenCreator) or grants to broad principals (e.g.,allUsers,allAuthenticatedUsers).
-
Practical monitoring & response
- Enable and route Audit Logs (Admin Activity) for IAM to a central sink (e.g., Cloud Logging → Pub/Sub → SIEM) and create rules keyed on
protoPayload.methodName="google.iam.admin.v1.SetIamPolicy". - Enrich detections by checking
authenticationInfo.principalEmailandresourceNameto confirm who changed which resource, and feed into approval workflows or periodic access reviews to ensure policies remain compliant.
- Enable and route Audit Logs (Admin Activity) for IAM to a central sink (e.g., Cloud Logging → Pub/Sub → SIEM) and create rules keyed on
Examples
-
Over-privileged role assignment on sensitive resources
SetIamPolicyon a production project or high-value resource (e.g., KMS key, GCS bucket with PHI/PII) that adds broad roles likeroles/owner,roles/editor, orroles/storage.adminto a wide group orallUsers/allAuthenticatedUsers.- Impact: Violates least-privilege (e.g., ISO 27001 A.9, NIST AC-6), can lead to data exfiltration or key misuse; must be flagged and rolled back via policy versioning / Terraform state.
-
Privilege escalation or bypassing separation of duties
- A user with limited rights uses
SetIamPolicyonprojects/*orfolders/*to grant themselves or a peerroles/iam.securityAdminorroles/iam.serviceAccountTokenCreator. - Impact: Enables lateral movement and impersonation, potentially breaching SOC 2 / PCI-DSS access control requirements; configure IAM Recommender, org policies (
constraints/iam.allowedPolicyMemberDomains) and Access Approval / Approval workflows to control.
- A user with limited rights uses
-
Granting external or unmanaged identities access to regulated data
SetIamPolicyadds external domains or consumer Google accounts to resources holding regulated data (e.g., BigQuery datasets with PCI/PHI) viaroles/bigquery.dataVieweror higher.- Impact: Possible non-compliance with GDPR, HIPAA, PCI-DSS (data residency, data sharing); enforce organization policies restricting member domains, use VPC-SC perimeters, and monitor
SetIamPolicylogs in Cloud Logging / SCC with alerting.
Remediation
Using Console
-
Immediately roll back risky IAM bindings and lock down sensitive resources
- In GCP Console, go to IAM & Admin → Audit Logs (or Logging → Logs Explorer) and filter on
protoPayload.methodName="SetIamPolicy"and the specific resource (project, KMS key, GCS bucket, BigQuery dataset) to identify the exact change (who/when/what role). - Navigate to the impacted resource in the Console (e.g., Cloud Storage → Buckets → [bucket] → Permissions, BigQuery → [dataset] → Share, KMS → Key rings/keys → Permissions, or IAM & Admin → IAM for projects/folders), and:
- Remove broad roles (
Owner,Editor,Storage Admin,BigQuery Data Viewer/Admin, etc.) from wide groups,allUsers,allAuthenticatedUsers, external domains, or consumer accounts. - Re-add only required, narrow roles (prefer predefined or custom least-privilege roles) to managed identities in your corporate domain.
- Remove broad roles (
- If managed by Terraform or another IaC tool, treat Console as read-only going forward: restore the last known-good configuration from version control, run
terraform plan/applyto overwrite the drifted IAM, and ensure state is in sync to avoid re-introducing non-compliant bindings.
- In GCP Console, go to IAM & Admin → Audit Logs (or Logging → Logs Explorer) and filter on
-
Prevent privilege escalation and enforce least-privilege & domain restrictions
- In IAM & Admin → IAM, remove any self-granted or peer-granted high-privilege roles (
Security Admin,Organization Admin,Service Account Token Creator,Project Owner) from users who should not have them; ensure separation of duties by assigning these to tightly controlled admin groups only. - Configure IAM Recommender (IAM & Admin → Recommender) to get and apply role reduction suggestions, and set Organization Policies in IAM & Admin → Organization Policies:
constraints/iam.allowedPolicyMemberDomainsto restrict which identity domains can be added.- Optionally, additional constraints like
constraints/iam.disableServiceAccountKeyCreationand others aligned with NIST AC-6 / ISO 27001 A.9.
- Implement approval workflows: integrate Access Approval (for supported services) and/or use ticketing-based change management so any IAM change on production or regulated resources requires secondary approval, supporting SOC 2 / PCI-DSS change-control and access-control requirements.
- In IAM & Admin → IAM, remove any self-granted or peer-granted high-privilege roles (
-
Harden perimeter and monitoring for regulated data access
- For datasets/buckets with PCI/PHI/PII, label and group them (e.g., using Labels and separate projects/folders) and, where applicable, place them inside VPC Service Controls perimeters (Security → VPC Service Controls) to reduce exfiltration risk.
- In Organization Policies, enforce domain and external sharing restrictions (e.g.,
constraints/iam.allowedPolicyMemberDomains, relevant BigQuery and Storage sharing constraints) to prevent adding external or unmanaged identities; document this as part of GDPR/HIPAA/PCI-DSS data sharing controls. - Set up continuous monitoring: in Logging → Logs Explorer, create log-based metrics on
SetIamPolicywith conditions likemembers:"allUsers" OR roles/owner OR roles/editor OR roles/iam.securityAdmin OR gmail.comand configure Cloud Monitoring alerts and Security Command Center findings to notify security/compliance teams for rapid review and remediation.
Using CLI
-
Immediately roll back over-privileged / mis-scoped IAM and lock down policies
- Identify and revert bad bindings using policy versioning or explicit
set-iam-policywith a corrected JSON:Repeat similarly for KMS keys, buckets, BigQuery datasets:# View current policygcloud projects get-iam-policy PROJECT_ID --format=json > policy.json# Edit policy.json: remove roles/owner, roles/editor, roles/storage.admin from wide groups / allUsers / allAuthenticatedUsers, etc.# Apply corrected policygcloud projects set-iam-policy PROJECT_ID policy.jsongcloud kms keys get-iam-policy KEY_NAME --keyring=KR --location=LOC > key-policy.jsongcloud kms keys set-iam-policy KEY_NAME key-policy.json --keyring=KR --location=LOCgsutil iam get gs://BUCKET > bucket-policy.jsongsutil iam set bucket-policy.json gs://BUCKETbq show --format=prettyjson PROJECT:DATASET > bq-dataset.json# edit access[] then:bq update --source=bq-dataset.json PROJECT:DATASET - Enforce org-level guardrails and least privilege to meet ISO 27001 A.9 / NIST AC‑6:
Use custom roles instead of broad primitives and clean up Terraform to align desired vs. actual IAM (update# Restrict who can administer IAMgcloud organizations get-iam-policy ORG_ID > org-policy.json# ensure only limited group has roles/iam.securityAdmin, etc., then:gcloud organizations set-iam-policy ORG_ID org-policy.json# Restrict which domains can be membersgcloud org-policies set-policy allowed-domains.yaml# allowed-domains.yaml uses constraints/iam.allowedPolicyMemberDomains
.tfand runterraform plan && terraform apply).
- Identify and revert bad bindings using policy versioning or explicit
-
Prevent privilege escalation and enforce separation of duties
- Detect and remove self-granted or peer-granted high-privilege roles:
Audit# Example: remove a bad bindinggcloud projects remove-iam-policy-binding PROJECT_ID \--member="user:USER@domain.com" \--role="roles/iam.securityAdmin"
SetIamPolicyevents:gcloud logging read \'protoPayload.methodName="SetIamPolicy" AND resource.type="project"' \--organization=ORG_ID --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.resourceName, protoPayload.serviceData.policyDelta)" - Harden IAM administration to satisfy SOC 2 / PCI-DSS:
Use:# Limit who can grant tokens / impersonategcloud projects remove-iam-policy-binding PROJECT_ID \--member="user:USER@domain.com" \--role="roles/iam.serviceAccountTokenCreator"
- Approval workflows / Access Approval for sensitive projects.
- IAM Recommender to downscope broad roles:
gcloud recommender recommendations list \--recommender=google.iam.policy.Recommender \--project=PROJECT_ID --location=global
- Separate admin accounts / groups for IAM vs. security monitoring, and enforce 2FA.
- Detect and remove self-granted or peer-granted high-privilege roles:
-
Block external / unmanaged identities from regulated data and monitor continuously
- Remove external / consumer accounts from PHI/PCI datasets and storage:
# BigQuery: list and then strip non-corporate membersbq show --format=prettyjson PROJECT:DATASET > ds.json# edit access[] to remove external users/domainsbq update --source=ds.json PROJECT:DATASET# Cloud Storage: remove allUsers / allAuthenticatedUsers or external domainsgsutil iam ch -d allUsers:objectViewer gs://BUCKETgsutil iam ch -d allAuthenticatedUsers:objectViewer gs://BUCKETgsutil iam get gs://BUCKET > bucket-iam.json # verify cleanup
- Enforce domain and perimeter restrictions (GDPR/HIPAA/PCI alignment):
# Restrict identity domains org-widegcloud org-policies set-policy allowed-domains.yaml # uses constraints/iam.allowedPolicyMemberDomains# (If using VPC-SC) Add projects with regulated data to a service perimetergcloud access-context-manager perimeters update PERIMETER_NAME \--add-resources=projects/PROJECT_NUMBER \--policy=POLICY_ID
- Configure continuous monitoring and alerts on
SetIamPolicy:Attach alerting in Cloud Monitoring and surface findings in Security Command Center; document incidents and remediations for audit evidence.# Example log-based metric for risky SetIamPolicygcloud logging metrics create risky_set_iam_policy \--description="Sensitive IAM policy changes" \--log-filter='protoPayload.methodName="SetIamPolicy" AND(protoPayload.serviceData.policyDelta.bindingDeltas.permission="roles/owner" ORprotoPayload.serviceData.policyDelta.bindingDeltas.permission="roles/editor" ORprotoPayload.serviceData.policyDelta.bindingDeltas.member:"allUsers" ORprotoPayload.serviceData.policyDelta.bindingDeltas.member:"allAuthenticatedUsers")'
- Remove external / consumer accounts from PHI/PCI datasets and storage:
Using Python
-
Detect and roll back over-privileged role assignments on sensitive resources
-
Use Cloud Logging to find risky
SetIamPolicycalls (broad roles on sensitive resources), then remove them and re-apply least-privilege via Terraform or a controlled policy file:from google.cloud import logging_v2import jsonclient = logging_v2.Client()logger = client.logger("iam-setiampolicy-audit")# Example: query recent SetIamPolicy calls that granted broad roles on KMS keys or bucketsFILTER = """protoPayload.methodName="SetIamPolicy"protoPayload.serviceName=("cloudkms.googleapis.com" OR "storage.googleapis.com")protoPayload.request.policy.bindings.role=("roles/owner" OR "roles/editor" OR "roles/storage.admin")"""for entry in client.list_entries(filter_=FILTER):payload = entry.payloadresource_name = payload["resourceName"]policy = payload["request"]["policy"]bindings = policy.get("bindings", [])risky = [b for b in bindings if b["role"] in ["roles/owner", "roles/editor", "roles/storage.admin"]]if risky:logger.log_text(f"Risky SetIamPolicy detected on {resource_name}: {json.dumps(risky)}")# In practice: trigger a rollback pipeline (e.g., Cloud Build) that reapplies a known-good IAM policy -
For production projects, enforce guardrails via org policies and deny policies to block these roles from being assigned to
allUsers/allAuthenticatedUsers:from google.cloud import orgpolicy_v2client = orgpolicy_v2.OrgPolicyClient()project = "projects/1234567890"policy_name = f"{project}/policies/iam.allowedPolicyMemberDomains"policy = orgpolicy_v2.Policy(name=policy_name,spec=orgpolicy_v2.PolicySpec(rules=[orgpolicy_v2.PolicySpec.PolicyRule(deny_all=True # deny non-corporate domains & anonymous)]))client.update_policy(policy=policy)
-
-
Prevent privilege escalation / separation-of-duties bypass via IAM controls
-
Continuously scan IAM policies on
projects/*andfolders/*to detect users who can grant themselvesroles/iam.securityAdminorroles/iam.serviceAccountTokenCreatorand remove those bindings:from google.cloud import resourcemanager_v3, iam_v1crm_client = resourcemanager_v3.ProjectsClient()iam_client = iam_v1.IAMPolicyClient()def remove_risky_admin_roles(project_id: str):resource = f"projects/{project_id}"policy = iam_client.get_iam_policy(resource=resource)risky_roles = ["roles/iam.securityAdmin", "roles/iam.serviceAccountTokenCreator"]new_bindings = []changed = Falsefor b in policy.bindings:if b.role in risky_roles:# keep bindings only for approved admin groups/service accountsallowed_members = [m for m in b.membersif m.startswith("group:sec-admins@corp.com") # example SOD group]if allowed_members:b.members[:] = allowed_membersnew_bindings.append(b)changed = Trueelse:new_bindings.append(b)if changed:policy.bindings[:] = new_bindingsiam_client.set_iam_policy(resource=resource, policy=policy)for p in crm_client.list_projects():if p.state == resourcemanager_v3.Project.State.ACTIVE:remove_risky_admin_roles(p.project_id) -
Combine with:
- IAM Recommender (UI/API) to downscope excessive admin roles.
- Org Policy constraints like
constraints/iam.disableServiceAccountKeyCreationandconstraints/iam.allowedPolicyMemberDomainsto reduce impersonation/abuse paths. - Approval workflows (e.g., via Access Approval, ticketing integration) for role elevation to meet SOC 2 / PCI-DSS change control.
-
-
Restrict external/unmanaged identities on regulated data and enforce compliant access
-
Scan for external domains or consumer accounts on BigQuery datasets / GCS buckets and remove them unless explicitly approved; apply org policies to restrict member domains:
from google.cloud import bigqueryfrom google.cloud import storageALLOWED_DOMAIN = "corp.com"def is_external_member(member: str) -> bool:if member.startswith(("allUsers", "allAuthenticatedUsers")):return Trueif ":" not in member:return False_, identity = member.split(":", 1)if "@" in identity and not identity.endswith("@" + ALLOWED_DOMAIN):return Truereturn Falsedef clean_bq_dataset_iam(project_id: str):bq = bigquery.Client(project=project_id)for ds in bq.list_datasets():dataset = bq.get_dataset(ds.reference)policy = bq.get_iam_policy(dataset.reference)changed = Falsefor b in list(policy.bindings):if any(is_external_member(m) for m in b["members"]):b["members"] = [m for m in b["members"] if not is_external_member(m)]changed = Trueif changed:bq.set_iam_policy(dataset.reference, policy)def clean_gcs_bucket_iam(project_id: str):cs = storage.Client(project=project_id)for bucket in cs.list_buckets():policy = bucket.get_iam_policy()changed = Falsefor role, members in list(policy.items()):keep = [m for m in members if not is_external_member(m)]if len(keep) != len(members):policy[role] = keepchanged = Trueif changed:bucket.set_iam_policy(policy)project_id = "my-regulated-project"clean_bq_dataset_iam(project_id)clean_gcs_bucket_iam(project_id) -
For GDPR/HIPAA/PCI-DSS workloads:
- Enforce
iam.allowedPolicyMemberDomainsand VPC-SC service perimeters for regulated projects. - Enable SCC and create alerting policies on
SetIamPolicylogs that add external members to BigQuery, GCS, or KMS, so any violations are quickly detected and remediated.
- Enforce
-