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

# OCI IAM Admin Group Should Be Protected From Self-Modification

### More Info:

A deny policy statement should prevent administrators from modifying the admin group membership. This prevents privilege escalation by ensuring no single admin can grant themselves additional access.

### Risk Level

Medium

### Address

Compliance, Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* Cloudanix Best Practice
* DPDPA
* Digital Operational Resilience Act (EU)
* Essential 8
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below is how to remediate the finding **“OCI IAM Admin Group Should Be Protected From Self-Modification”** using the **OCI Console**.

        The goal:\
        No group that has permission to manage IAM groups/administrators should be able to change its own membership or policies directly.

        ***

        ## 1. Identify the High‑Privilege Admin Group

        1. Sign in to the **OCI Console** as a tenancy administrator (or root user).
        2. Open the navigation menu → **Identity & Security** → **Identity** → **Groups**.
        3. Locate the group that is flagged (often called `Administrators` or similar).\
           Note its exact name; assume it’s `Administrators` for the examples below.

        ***

        ## 2. Check Current Policies That Let It Manage Itself

        1. Navigation menu → **Identity & Security** → **Identity** → **Policies**.
        2. Filter or search policies where the **Subject** (left side of the statement) includes the admin group, e.g.:
           * `Allow group Administrators to manage all-resources in tenancy`
           * `Allow group Administrators to manage groups in tenancy`
        3. For each such policy, verify whether it allows this group to:
           * manage `groups`
           * manage `users`
           * manage `policies`
           * manage `tenancy` or `all-resources` (which implicitly includes groups).

        These are the policies that allow **self-modification** and must be adjusted.

        ***

        ## 3. Create a Separate IAM Admin Group (if you don’t already have one)

        If you don’t already have a dedicated group for IAM management that is different from the group you want to protect:

        1. Go to **Identity & Security** → **Identity** → **Groups** → **Create Group**.
        2. Name it something like `IAM-Admins`.
        3. Add at least one trusted admin user to this group:
           * Go to **Identity & Security** → **Identity** → **Users**.
           * Open a user you trust.
           * Under **Groups**, click **Add User to Group** → select `IAM-Admins` → **Add**.

        This group will hold IAM management permissions instead of the protected admin group.

        ***

        ## 4. Move IAM Management Permissions Off the Protected Group

        ### 4.1. Create a Policy for the IAM-Admins Group

        1. Go to **Identity & Security** → **Identity** → **Policies** → **Create Policy**.
        2. Place it in the **root compartment** (so it can manage tenancy-level IAM).
        3. Give it a name like `policy-iam-admins`.
        4. In the **Policy Builder**, add statements such as:

        ```text theme={null}
        Allow group IAM-Admins to manage groups in tenancy
        Allow group IAM-Admins to manage policies in tenancy
        Allow group IAM-Admins to manage users in tenancy
        ```

        (Adjust to your requirements, but ensure this group can manage groups/users/policies.)

        5. Click **Create**.

        ### 4.2. Remove or Restrict IAM Management from the Original Admin Group

        For each policy that currently grants IAM powers to the protected group (e.g., `Administrators`):

        1. Open the policy.

        2. Click **Edit Policy Statements**.

        3. Either:
           * **Remove** statements such as:

             ```text theme={null}
             Allow group Administrators to manage groups in tenancy
             Allow group Administrators to manage all-resources in tenancy
             Allow group Administrators to manage users in tenancy
             Allow group Administrators to manage policies in tenancy
             ```

           * Or **narrow** them to exclude IAM resources (e.g., change to manage only specific non-IAM resources/compartments).

        4. Save the edited policy.

        Result: the `Administrators` group (or equivalent) no longer has the ability to modify groups, users, or policies, including itself.

        ***

        ## 5. Optionally Add a Condition to Explicitly Protect the Group (Advanced)

        If you want more granular control (for example, other groups can manage groups but **not** the critical admin group):

        1. In the policy for `IAM-Admins`, you can use a condition to protect the `Administrators` group:

           ```text theme={null}
           Allow group IAM-Admins to manage groups in tenancy
           where any {target.group.name != 'Administrators'}
           ```

        2. Edit the `IAM-Admins` policy and replace the generic `manage groups` line with the conditional one above.

        3. Save the policy.

        Now `IAM-Admins` can manage groups except the protected one; any change to the protected group can only be done by higher-trust mechanisms (e.g., root user or a break-glass identity).

        ***

        ## 6. Validate

        1. Log in as a member of the **protected admin group** (e.g., `Administrators`).

        2. Confirm:
           * They **cannot**:
             * Add/remove users to/from their own group.
             * Edit policies that grant themselves IAM control.
           * But they can still perform whatever non-IAM tasks you intended for them (if any).

        3. Log in as a member of `IAM-Admins`:
           * Confirm they can manage other groups/policies as designed.

        ***

        This configuration ensures that the **OCI IAM admin group is protected from self-modification**, satisfying the monitoring/control requirement while preserving an administrative path through a separate IAM-admin group or root identity.
      </Accordion>

      <Accordion title="Using CLI">
        Below is how to **remediate** the issue “OCI IAM Admin Group Should Be Protected From Self-Modification” using **OCI CLI**. The main idea is:

        * Remove “IAM‑management” permissions from your general admin group (typically `Administrators`)
        * Create a separate `iam-admins` group that manages IAM
        * Optionally script a check (monitoring) with OCI CLI to ensure the problem doesn’t return

        ***

        ## 1. Prerequisites

        Make sure OCI CLI is configured and you have a user with enough permission to modify policies and groups at the tenancy level.

        ```bash theme={null}
        oci setup config
        ```

        You will also need the **tenancy OCID**:

        ```bash theme={null}
        TENANCY_OCID="<your_tenancy_ocid>"
        ```

        ***

        ## 2. Identify the “Administrators” group

        ```bash theme={null}
        ADMIN_GROUP_OCID=$(
          oci iam group list \
            --compartment-id "$TENANCY_OCID" \
            --all \
            --query "data[?name=='Administrators'].id | [0]" \
            --raw-output
        )

        echo "Administrators group OCID: $ADMIN_GROUP_OCID"
        ```

        ***

        ## 3. List all policies in the tenancy and find IAM‑related permissions for the admin group

        You’re looking for statements like:

        * `Allow group Administrators to manage users in tenancy`
        * `Allow group Administrators to manage groups in tenancy`
        * `Allow group Administrators to manage policies in tenancy`
        * `Allow group Administrators to manage dynamic-groups in tenancy`
        * etc.

        List policies:

        ```bash theme={null}
        oci iam policy list \
          --compartment-id "$TENANCY_OCID" \
          --all \
          --query 'data[].{id:id, name:name}' \
          --output table
        ```

        For each policy ID, inspect statements:

        ```bash theme={null}
        POLICY_ID="<policy_ocid_here>"

        oci iam policy get --policy-id "$POLICY_ID" \
          --query "data.{name:name, statements:statements}" \
          --output json
        ```

        Find and note the specific statements that give the `Administrators` group the ability to `manage` IAM resources (users, groups, policies, dynamic-groups, identity-providers, tag-namespaces, etc.).

        ***

        ## 4. Create a dedicated IAM admin group

        Create a new group for IAM management (example name: `iam-admins`):

        ```bash theme={null}
        IAM_ADMINS_GROUP=$(
          oci iam group create \
            --name "iam-admins" \
            --description "Dedicated group to manage IAM (users, groups, policies) for the tenancy" \
            --query "data.id" \
            --raw-output
        )

        echo "iam-admins group OCID: $IAM_ADMINS_GROUP"
        ```

        Add at least one trusted user to this group (replace `<user_ocid>`):

        ```bash theme={null}
        USER_OCID="<user_ocid_to_become_iam_admin>"

        oci iam group add-user \
          --group-id "$IAM_ADMINS_GROUP" \
          --user-id "$USER_OCID"
        ```

        ***

        ## 5. Create new IAM policy for the `iam-admins` group

        Define a policy that gives `iam-admins` the IAM management powers you are about to remove from `Administrators`:

        Example (adjust as needed):

        ```bash theme={null}
        oci iam policy create \
          --compartment-id "$TENANCY_OCID" \
          --name "iam-admins-policy" \
          --description "Policy granting IAM management rights to iam-admins group" \
          --statements '[
            "Allow group iam-admins to manage users in tenancy",
            "Allow group iam-admins to manage groups in tenancy",
            "Allow group iam-admins to manage policies in tenancy",
            "Allow group iam-admins to manage dynamic-groups in tenancy",
            "Allow group iam-admins to manage federation-providers in tenancy",
            "Allow group iam-admins to manage tag-namespaces in tenancy"
          ]'
        ```

        ***

        ## 6. Remove IAM-management permissions from the `Administrators` group

        For **each** policy that currently gives IAM‑management to `Administrators`, you must:

        1. Download current statements.
        2. Remove/adjust the lines giving IAM management to `Administrators`.
        3. Update the policy with the modified list.

        ### 6.1 Export current statements

        ```bash theme={null}
        POLICY_ID="<policy_ocid_with_admin_iam_perms>"

        oci iam policy get --policy-id "$POLICY_ID" \
          --query "data.statements" \
          --output json > policy-statements.json
        ```

        Edit `policy-statements.json` locally and **delete** any line like:

        ```text theme={null}
        "Allow group Administrators to manage users in tenancy",
        "Allow group Administrators to manage groups in tenancy",
        "Allow group Administrators to manage policies in tenancy",
        "Allow group Administrators to manage dynamic-groups in tenancy",
        "Allow group Administrators to manage tag-namespaces in tenancy",
        ...
        ```

        Leave all other non‑IAM permissions intact.

        ### 6.2 Update the policy

        ```bash theme={null}
        oci iam policy update \
          --policy-id "$POLICY_ID" \
          --statements file://policy-statements.json
        ```

        Repeat this for every affected policy.

        After this, the `Administrators` group can no longer modify IAM (including itself); IAM changes are now only possible via `iam-admins`.

        ***

        ## 7. (Optional) Basic CLI-based monitoring script

        You can periodically check (e.g., via cron/OCI Functions) that no new policy grants IAM‑manage rights to `Administrators`.

        Example check (Linux shell):

        ```bash theme={null}
        oci iam policy list \
          --compartment-id "$TENANCY_OCID" \
          --all \
          --query "data[*].{name:name, id:id, statements:statements}" \
          --output json > all-policies.json

        grep -n '"Allow group Administrators to manage ' all-policies.json || echo "No self-modifying IAM policy found for Administrators."
        ```

        You can refine the grep for specific IAM verbs/resources as needed and alert if any match is found.

        ***

        These steps remove IAM self‑modification capability from the admin/default group and place it under a separate controlled group, satisfying the control “OCI IAM Admin Group Should Be Protected From Self-Modification,” and all changes are done using OCI CLI.
      </Accordion>

      <Accordion title="Using Python">
        Below are (1) the IAM remediation steps in OCI and (2) a Python example you can use for monitoring / detection.

        ***

        ## 1. Remediation concept in OCI

        Goal: Ensure your “Admin” group cannot modify its own membership, policies, or other IAM primitives that control itself.

        ### Step 1 – Identify your admin group(s)

        Typical names:

        * `Administrators`
        * `SecurityAdmins`
        * Or any group that:
          * can `manage all-resources in tenancy`, or
          * can `manage groups` / `manage policies` / `manage users`.

        In the Console:

        1. Go to **Identity & Security → Domains** (or **Identity → Groups** in classic).
        2. Open each candidate group (e.g., `Administrators`).
        3. Note the **group name** and **OCID**.

        ### Step 2 – Create a separate “IAM Security” group (recommended)

        Create a new group to own IAM administration (and especially the admin group itself):

        1. In **Identity → Groups**, click **Create group**.
        2. Name it something like `IAM-Security-Admins`.
        3. Add only your highest-trust break-glass users.

        This group will get exclusive ability to manage the admin group and IAM policies.

        ### Step 3 – Adjust policies so Admin group cannot self‑modify

        Find all tenancy (root) policies that give your admin group broad permissions. Common risky statements:

        ```text theme={null}
        Allow group Administrators to manage all-resources in tenancy
        Allow group Administrators to manage groups in tenancy
        Allow group Administrators to manage users in tenancy
        Allow group Administrators to manage policies in tenancy
        ```

        You want to:

        * Remove or narrow these for the Admin group.
        * Move IAM-management privileges to `IAM-Security-Admins`.
        * Optionally, use a condition to explicitly deny managing the Admin group.

        Example safer pattern:

        ```text theme={null}
        -- Give Admin group general admin, but NOT IAM:
        Allow group Administrators to manage all-resources in tenancy
            where target.service.name != 'identity'

        -- Give IAM-Security-Admins full IAM control:
        Allow group IAM-Security-Admins to manage identity-domains in tenancy
        Allow group IAM-Security-Admins to manage users in tenancy
        Allow group IAM-Security-Admins to manage groups in tenancy
        Allow group IAM-Security-Admins to manage policies in tenancy
        ```

        Or, if using conditional policies (Identity Domains / advanced conditions), you can be more explicit, e.g.:

        ```text theme={null}
        Allow group Administrators to manage groups in tenancy
            where target.group.name != 'Administrators'
        ```

        The exact condition keys vary slightly by domain type; check OCI docs for “IAM policy conditions” to confirm `target.group.name` / `target.iam.group.name` in your environment.

        Key point: the admin group should not have permission to:

        * `manage groups` on itself, or
        * `manage policies` that define its own power, or
        * broad `manage all-resources` including identity, unless constrained with conditions.

        ***

        ## 2. Python monitoring for “self‑modifiable” admin groups (OCI SDK)

        This script does *detection* (for monitoring). It scans tenancy policies and flags lines where an admin group has risky powers like `manage all-resources`, `manage groups`, or `manage policies` without any condition.

        ### 2.1. Prerequisites

        1. Install OCI Python SDK:
           ```bash theme={null}
           pip install oci
           ```
        2. Have a working OCI config (e.g., `~/.oci/config`) with a profile that can `read` policies at tenancy level:
           ```ini theme={null}
           [DEFAULT]
           user=ocid1.user.oc1..xxxx
           fingerprint=...
           key_file=~/.oci/oci_api_key.pem
           tenancy=ocid1.tenancy.oc1..xxxx
           region=us-phoenix-1
           ```

        ### 2.2. Python example

        ```python theme={null}
        import oci
        import re

        # ---------------- CONFIG ----------------
        PROFILE_NAME = "DEFAULT"
        # Admin-like groups you want to protect from self-modification:
        PROTECTED_GROUPS = [
            "Administrators",
            "SecurityAdmins",
            "TenantAdmins",
        ]
        # ----------------------------------------


        def is_risky_statement(stmt: str, group: str) -> bool:
            """
            Heuristic: flags statements where a protected group can manage:
            - all-resources
            - groups
            - policies
            - users
            without a 'where' clause restricting IAM or itself.
            """
            normalized = " ".join(stmt.split()).lower()

            # must have: "allow group <group>" or "allow dynamic-group <group>" etc.
            if f"allow group {group.lower()}" not in normalized:
                return False

            # simple pattern checks
            risky_verbs = [
                "manage all-resources",
                "manage groups",
                "manage users",
                "manage policies",
                "manage identity-domains",
            ]
            has_risky_verb = any(rv in normalized for rv in risky_verbs)
            if not has_risky_verb:
                return False

            # If there is a WHERE clause, you might want a deeper parse;
            # here we treat ANY condition as "less risky", but you can tighten this.
            has_condition = " where " in normalized

            # Flag when powerful AND no condition
            return has_risky_verb and not has_condition


        def main():
            config = oci.config.from_file(profile_name=PROFILE_NAME)
            identity = oci.identity.IdentityClient(config)

            tenancy_id = config["tenancy"]

            print(f"Scanning policies in tenancy {tenancy_id} ...")

            # List all policies in the tenancy (root compartment)
            list_policies_response = oci.pagination.list_call_get_all_results(
                identity.list_policies,
                compartment_id=tenancy_id
            )

            risky_findings = []

            for policy in list_policies_response.data:
                for stmt in policy.statements:
                    for group in PROTECTED_GROUPS:
                        if is_risky_statement(stmt, group):
                            risky_findings.append({
                                "policy_name": policy.name,
                                "policy_id": policy.id,
                                "compartment_id": policy.compartment_id,
                                "group": group,
                                "statement": stmt,
                            })

            if not risky_findings:
                print("No risky self-modification statements found for protected groups.")
                return

            print("\nRISKY STATEMENTS FOUND:")
            for f in risky_findings:
                print("-------------------------------------------------")
                print(f"Policy Name  : {f['policy_name']}")
                print(f"Policy OCID  : {f['policy_id']}")
                print(f"Compartment  : {f['compartment_id']}")
                print(f"Group        : {f['group']}")
                print(f"Statement    : {f['statement']}")
            print("-------------------------------------------------")
            print(f"Total findings: {len(risky_findings)}")

            # Here you could:
            # - push to monitoring system (e.g., send to OCI Logging, Splunk, etc.)
            # - send an email or Slack alert
            # - write to a file for compliance reports


        if __name__ == "__main__":
            main()
        ```

        ### 2.3. How to use this for continuous monitoring

        * Run this script on a schedule (e.g., with:
          * OCI Functions + Events,
          * a cron job on a bastion / CI runner,
          * or an OCI DevOps pipeline).
        * When `risky_findings` is non-empty:
          * Notify security / cloud team.
          * Manually update the flagged policies as described in Section 1.

        ***

        If you share a sample of your current policy statements for the admin group, I can adjust the detection logic and give an exact “before/after” policy example.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "oci_identity_policy" "IAM_ADMIN_GROUP_PROTECTION" {
          compartment_id = "TENANCY_OCID"        # Replace with your tenancy OCID (the root compartment)
          name           = "ADMIN_GROUP_PROTECTION_POLICY"  # Replace with your desired policy name
          description    = "Prevent the Administrators group from modifying its own membership"

          statements = [
            # Add this deny rule alongside any existing allow rules that grant admin privileges.
            # If you already manage an IAM policy for admins, add this statement into that resource's `statements` list.
            "Deny group Administrators to manage groups in tenancy where target.group.name = 'Administrators'",
          ]

          # Optional: pin to the date when policy language was valid
          # version_date = "2024-01-01"
        }
        ```

        This change is in-place and does not force replacement of the policy resource; it only updates its statements.

        To verify, `terraform plan` should show the `oci_identity_policy.IAM_ADMIN_GROUP_PROTECTION` resource with an updated `statements` attribute including the new `Deny group Administrators to manage groups in tenancy where target.group.name = 'Administrators'` entry and no resource replacement (`-/+` or `+/-`) for this policy.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
