Skip to main content

Google.Admin.Adminservice.Addgroupmember Remediation

Event Information

  • Event meaning & scope

    • google.admin.AdminService.addGroupMember indicates a member (user, service account, or group) was added to a Google Group via the Admin SDK / Admin Console.
    • In a GCPIAM context, this often means the subject gained indirect IAM permissions wherever that group is bound to IAM roles (projects, folders, org, or specific GCP resources).
  • Security & compliance implications

    • This event can represent a privilege escalation if the group has high‑privilege roles (e.g., roles/owner, roles/editor, custom admin roles).
    • For compliance frameworks (e.g., ISO 27001, SOC 2, PCI DSS), it is relevant to access control, least privilege, and auditability—track who added which identities to which groups and when.
  • Practical handling in GCP

    • Monitor and alert on this event when the target group is mapped to sensitive IAM roles or production projects.
    • Correlate with IAM bindings (Cloud Asset Inventory, gcloud asset or Organization Policy) to understand the effective new permissions granted.
    • Periodically review groups with broad or privileged bindings and enforce approval workflows for membership changes.

Examples

  • Privilege escalation via high-privilege group

    • google.admin.AdminService.addGroupMember adds a user/service account to an admin or privileged group (e.g., gcp-org-admins, project-owners).
    • Impact: New member inherits broad IAM and possibly org-policy override rights; can create keys, modify logging, or disable security controls.
    • Compliance: Violates least-privilege (ISO 27001 A.6, SOC 2 CC6, CIS GCP); must be justified, approved, and logged.
  • Circumventing access reviews and joiner/mover/leaver controls

    • Member is added outside the standard HR/IT workflow, bypassing SoD and access review processes.
    • Impact: Former employees, contractors, or external identities may retain or gain access to sensitive resources (e.g., production data, PHI/PII).
    • Compliance: Conflicts with access recertification and termination controls (PCI DSS 7.2, HIPAA §164.308(a)(3), SOX access governance).
  • Unauthorized external collaboration / data exfiltration vector

    • External identity (e.g., @gmail.com or partner domain) is added to a group mapped to GCP roles with data access (e.g., BigQuery datasets, GCS buckets).
    • Impact: External party can read/export regulated or confidential data, potentially outside approved data residency or DLP boundaries.
    • Compliance: Risks breach of data transfer, residency, and DLP requirements (GDPR, HIPAA, ISO 27018); must trigger alerting and review of group-to-IAM bindings.

Remediation

Using Console

  • Immediately contain and review the group membership change

    • In Google Admin Console: go to Directory → Groups → [impacted group] → Members → identify the newly added member; if not explicitly authorized, Remove them.
    • In GCP Console: go to IAM & Admin → IAM, filter by Principal = the added user/service account and review inherited roles from this group (especially roles/owner, roles/resourcemanager.organizationAdmin, custom high-privilege roles); remove any unintended bindings.
    • Document the incident (who/when/why), map to violations of least-privilege and access controls (ISO 27001 A.6, SOC 2 CC6, CIS GCP, PCI DSS 7.2, HIPAA, SOX), and open a ticket/change record for formal approval/exception or permanent revocation.
  • Align group membership to joiner/mover/leaver and access review controls

    • In Google Admin Console:
      • Under Security → Access and data control → Admin roles, restrict who can manage high-privilege groups (e.g., only a small “IAM-admin” role tied to IT security).
      • Under Rules (Security → Rules) create rules to alert on:
        • Condition: Group membership changed for specific privileged groups (e.g., GCP org/project admin groups).
        • Action: Send email/ webhook to security/IT and log to SIEM for SoD/access-review checks.
    • In GCP Console:
      • Use IAM → Audit Logs (and Cloud Logging) to confirm google.admin.AdminService.addGroupMember and correlate with HR/IT workflows; ensure Admin Activity logs are routed to a central log project and retained per compliance.
      • Establish a periodic review (at least quarterly) of members of high-privilege groups and cross-check with HR roster and access recertification requirements (PCI DSS 7.2, HIPAA 164.308(a)(3), SOX).
  • Control external collaboration and data exfiltration via group-to-IAM bindings

    • In Google Admin Console → Security → External access and Domain settings:
      • Restrict or disallow adding external members to sensitive groups; configure whitelists for trusted partner domains only.
      • Regularly review high-risk groups (mapped to BigQuery/GCS access) for members with external domains (@gmail.com, other external domains) and remove any unapproved accounts.
    • In GCP Console:
      • Go to IAM & Admin → IAM, identify roles granted to these groups that provide data access (e.g., roles/storage.objectViewer, roles/bigquery.dataViewer, custom data roles) and tighten to least-privilege; remove group bindings where group membership includes externals without DPA/contract.
      • Configure Security → Data Loss Prevention and Cloud Logging → Log-based alerts to detect unusual BigQuery exports, GCS object downloads, or access from external identities, and review against GDPR/HIPAA/ISO 27018 data transfer and residency policies.

Using CLI

  • Immediately contain and validate high-privilege group change

    • Identify the event and the affected group/member:
      • gcloud logging read 'protoPayload.methodName="google.admin.AdminService.addGroupMember"' --project=<LOGGING_PROJECT> --limit=50 --format=json
    • List current members of the impacted high-privilege group (e.g., mapped Google Group → IAM):
      • gcloud identity groups memberships list --group-email=<GROUP_EMAIL> --format="table(name, preferredMemberKey.id, roles)"
    • If the addition is not explicitly approved via your access workflow, remove the member and document the incident:
      • gcloud identity groups memberships delete <MEMBERSHIP_NAME> --group-email=<GROUP_EMAIL>
  • Reinforce least-privilege, SoD, and access review controls

    • Discover which groups are mapped to high-privilege IAM roles and review for inappropriate members (internal and external):
      • gcloud projects get-iam-policy <PROJECT_ID> --format=json | jq '.bindings[] | select(.role|test("owner|admin|OrgAdmin"; "i"))'
      • gcloud iam roles list --organization=<ORG_ID> --format="value(name)" | grep -Ei 'admin|owner|security|orgPolicy'
    • Enforce centralized, ticket-based access with time-bound membership for admin groups (e.g., using Access Approval / PAM):
      • Where feasible, replace static membership with short-lived IAM conditions:
        • gcloud projects add-iam-policy-binding <PROJECT_ID> --member="group:<GROUP_EMAIL>" --role="roles/resourcemanager.projectIamAdmin" --condition='expression=request.time < timestamp("2026-07-31T00:00:00Z"),title=TimeBoundAccess'
    • Align with ISO 27001 A.6, SOC 2 CC6, CIS GCP, PCI DSS 7.2 by integrating HR/IT workflows and periodic recertification of all high-privilege groups.
  • Control external identities and data access / exfiltration risk

    • Enumerate external members of groups bound to data-access roles (BQ/GCS) and remove or justify them:
      • Find IAM bindings to groups for data roles:
        • gcloud projects get-iam-policy <PROJECT_ID> --format=json | jq '.bindings[] | select(.role|test("bigquery|storage.objectViewer|storage.objectAdmin"; "i"))'
      • List group memberships and filter for non-corporate domains:
        • gcloud identity groups memberships list --group-email=<GROUP_EMAIL> --format=json | jq '.[] | select(.preferredMemberKey.id|test("@gmail.com$|@yahoo.com$|@outlook.com$"))'
      • Remove any unapproved external member and log rationale:
        • gcloud identity groups memberships delete <MEMBERSHIP_NAME> --group-email=<GROUP_EMAIL>
    • Review and, if necessary, tighten group-to-IAM bindings on BigQuery datasets and GCS buckets to comply with GDPR/HIPAA/ISO 27018:
      • bq show --format=prettyjson <PROJECT_ID>:<DATASET> | jq '.access'
      • gsutil iam get gs://<BUCKET_NAME> | jq '.bindings'
    • Configure alerts on google.admin.AdminService.addGroupMember events and on IAM changes involving external principals; ensure DLP and data residency controls are applied to any resource accessible by these groups.

Using Python

  • Detect and review high-privilege group additions (GCPIAM / Admin SDK)

    • Use Cloud Logging + Python to detect google.admin.AdminService.addGroupMember events on sensitive groups (e.g., gcp-org-admins, project-owners, groups mapped to roles/owner, roles/resourcemanager.organizationAdmin), then auto-flag for review and optionally auto-remove if not approved:
    from google.cloud import logging_v2
    import json, re, datetime as dt

    HIGH_PRIV_GROUP_PATTERNS = [
    r'gcp-org-admins@', r'project-owners@', r'org-admins@',
    r'security-admins@', r'prod-admins@'
    ]

    def is_high_priv_group(email: str) -> bool:
    return any(re.search(p, email, re.IGNORECASE) for p in HIGH_PRIV_GROUP_PATTERNS)

    def list_recent_addGroupMember(project_id: str, minutes: int = 15):
    client = logging_v2.Client(project=project_id)
    now = dt.datetime.utcnow()
    start = now - dt.timedelta(minutes=minutes)
    filter_ = (
    'protoPayload.methodName="google.admin.AdminService.addGroupMember" '
    f'timestamp>="{start.isoformat("T")}Z"'
    )
    for entry in client.list_entries(filter_=filter_):
    payload = entry.payload
    if "protoPayload" in payload:
    pp = payload["protoPayload"]
    else:
    pp = payload
    params = pp.get("request", {})
    group_email = params.get("group", {}).get("email") or params.get("groupKey", {}).get("id")
    member_email = params.get("memberKey", {}).get("id")
    actor = pp.get("authenticationInfo", {}).get("principalEmail")
    if group_email and is_high_priv_group(group_email):
    yield {
    "group": group_email,
    "member": member_email,
    "actor": actor,
    "insertId": pp.get("insertId", entry.insert_id),
    "timestamp": entry.timestamp
    }

    if __name__ == "__main__":
    for ev in list_recent_addGroupMember("YOUR_LOGGING_PROJECT_ID"):
    print("HIGH-PRIV GROUP CHANGE:", ev)
    # Integrate with ticketing / approval workflows to meet ISO27001/SOC2/CIS
    • Tie this to a manual approval workflow (e.g., ticket ID in description) and retain logs for PCI/SOX/HIPAA evidence; only changes with valid change tickets should persist.
  • Enforce JML (Joiner/Mover/Leaver) and SoD controls via group / IAM reconciliation

    • Periodically reconcile group membership with HR/IdP authoritative sources; auto-remove members no longer in “active” employment or approved roles:
    from google.oauth2 import service_account
    from googleapiclient.discovery import build

    SCOPES = ['https://www.googleapis.com/auth/admin.directory.group.readonly',
    'https://www.googleapis.com/auth/admin.directory.group.member']

    def get_directory_service(sa_file: str, admin_user: str):
    creds = service_account.Credentials.from_service_account_file(
    sa_file, scopes=SCOPES
    ).with_subject(admin_user)
    return build('admin', 'directory_v1', credentials=creds)

    def cleanup_group_members(group_email: str, allowed_members: set, service):
    members = service.members().list(groupKey=group_email).execute().get('members', [])
    for m in members:
    email = m['email']
    if email not in allowed_members:
    print(f"Removing unauthorized member {email} from {group_email}")
    service.members().delete(groupKey=group_email, memberKey=email).execute()

    if __name__ == "__main__":
    svc = get_directory_service("svc-account.json", "admin@your-domain.com")
    # allowed_members should come from HR/IdP export to satisfy PCI 7.2 / HIPAA / SOX
    allowed_members = {"alice@corp.com", "bob@corp.com"}
    cleanup_group_members("gcp-org-admins@your-domain.com", allowed_members, svc)
    • Run this as a scheduled job (Cloud Scheduler + Cloud Run/Functions) to enforce access recertification, SoD, and leaver removal.
  • Detect and remediate external identities & data-exposure risk

    • Identify external members (@gmail.com, non-corporate domains) on groups mapped to GCP IAM bindings with data access (BigQuery/GCS), then either remove or downgrade them; log for GDPR/ISO 27018 review:
    from googleapiclient.discovery import build
    from google.oauth2 import service_account

    CORP_DOMAINS = ["your-domain.com", "trusted-partner.com"]

    def is_external(email: str) -> bool:
    domain = email.split("@")[-1].lower()
    return domain not in [d.lower() for d in CORP_DOMAINS]

    def list_group_members(service, group_email: str):
    req = service.members().list(groupKey=group_email)
    while req is not None:
    res = req.execute()
    for m in res.get('members', []):
    yield m
    req = service.members().list_next(req, res)

    def remove_external_from_group(service, group_email: str):
    for m in list_group_members(service, group_email):
    email = m['email']
    if is_external(email):
    print(f"External member {email} found in {group_email}, removing to reduce exfil risk")
    service.members().delete(groupKey=group_email, memberKey=email).execute()

    if __name__ == "__main__":
    svc = get_directory_service("svc-account.json", "admin@your-domain.com")
    sensitive_groups = [
    "bq-prod-readers@your-domain.com",
    "gcs-phi-access@your-domain.com"
    ]
    for g in sensitive_groups:
    remove_external_from_group(svc, g)
    • Combine with an IAM inventory (e.g., Cloud Asset Inventory export) to list group-to-IAM bindings for BigQuery datasets and GCS buckets, then trigger alerts when external identities are detected on those groups to support DLP/data residency requirements.