OCI IAM Admin Group Should Be Protected From
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
- Remediation
Remediation
Using Console
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
- Sign in to the OCI Console as a tenancy administrator (or root user).
- Open the navigation menu → Identity & Security → Identity → Groups.
- Locate the group that is flagged (often called
Administratorsor similar).
Note its exact name; assume it’sAdministratorsfor the examples below.
2. Check Current Policies That Let It Manage Itself
- Navigation menu → Identity & Security → Identity → Policies.
- 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 tenancyAllow group Administrators to manage groups in tenancy
- For each such policy, verify whether it allows this group to:
- manage
groups - manage
users - manage
policies - manage
tenancyorall-resources(which implicitly includes groups).
- manage
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:
- Go to Identity & Security → Identity → Groups → Create Group.
- Name it something like
IAM-Admins. - 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
- Go to Identity & Security → Identity → Policies → Create Policy.
- Place it in the root compartment (so it can manage tenancy-level IAM).
- Give it a name like
policy-iam-admins. - In the Policy Builder, add statements such as:
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.)
- 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):
-
Open the policy.
-
Click Edit Policy Statements.
-
Either:
-
Remove statements such as:
Allow group Administrators to manage groups in tenancyAllow group Administrators to manage all-resources in tenancyAllow group Administrators to manage users in tenancyAllow 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).
-
-
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):
-
In the policy for
IAM-Admins, you can use a condition to protect theAdministratorsgroup:Allow group IAM-Admins to manage groups in tenancywhere any {target.group.name != 'Administrators'} -
Edit the
IAM-Adminspolicy and replace the genericmanage groupsline with the conditional one above. -
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
-
Log in as a member of the protected admin group (e.g.,
Administrators). -
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).
- They cannot:
-
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.
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-adminsgroup 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.
oci setup config
You will also need the tenancy OCID:
TENANCY_OCID="<your_tenancy_ocid>"
2. Identify the “Administrators” group
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 tenancyAllow group Administrators to manage groups in tenancyAllow group Administrators to manage policies in tenancyAllow group Administrators to manage dynamic-groups in tenancy- etc.
List policies:
oci iam policy list \
--compartment-id "$TENANCY_OCID" \
--all \
--query 'data[].{id:id, name:name}' \
--output table
For each policy ID, inspect statements:
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):
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>):
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):
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:
- Download current statements.
- Remove/adjust the lines giving IAM management to
Administrators. - Update the policy with the modified list.
6.1 Export current statements
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:
"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
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):
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.
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:
AdministratorsSecurityAdmins- Or any group that:
- can
manage all-resources in tenancy, or - can
manage groups/manage policies/manage users.
- can
In the Console:
- Go to Identity & Security → Domains (or Identity → Groups in classic).
- Open each candidate group (e.g.,
Administrators). - 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):
- In Identity → Groups, click Create group.
- Name it something like
IAM-Security-Admins. - 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:
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:
-- 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.:
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 groupson itself, ormanage policiesthat define its own power, or- broad
manage all-resourcesincluding 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
- Install OCI Python SDK:
pip install oci
- Have a working OCI config (e.g.,
~/.oci/config) with a profile that canreadpolicies at tenancy level:[DEFAULT]user=ocid1.user.oc1..xxxxfingerprint=...key_file=~/.oci/oci_api_key.pemtenancy=ocid1.tenancy.oc1..xxxxregion=us-phoenix-1
2.2. Python example
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_findingsis 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.
Using Terraform
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.