OCI IAM Policies Should Not Grant Manage/Use On All
More Info:
IAM policies should not grant manage or use permissions on all-resources. Broad resource access violates least-privilege principles and magnifies the impact of credential compromise.
Risk Level
Critical
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)
- 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
Here’s how to remediate “OCI IAM Policies Should Not Grant Manage/Use On All Resources” using the OCI Console.
1. Identify Overly Broad Policies
-
Sign in to the OCI Console.
-
Open the navigation menu (☰) → Identity & Security → Identity → Policies.
-
In the Scope selector at the top left, check both:
- Tenancy level (root)
- Each compartment where you define policies
-
In the policy list, look for policies containing statements like:
... to manage all-resources in tenancy... to manage all-resources in compartment <name>... to use all-resources in tenancy... to use all-resources in compartment <name>
You can quickly find them by:
- Clicking a policy name
- Using browser search (Ctrl+F / Cmd+F) for
all-resources.
These are the ones violating the rule.
2. Plan Least-Privilege Replacement
For each policy statement using manage all-resources or use all-resources, decide:
-
Which principal actually needs access?
- Group? Dynamic group? User?
-
Which services/resources do they really need?
Replaceall-resourceswith more specific verbs and resource-types, e.g.:Common replacements:
- Instead of:
allow group app-admins to manage all-resources in compartment app-compartment - Use something like:
allow group app-admins to manage instance-family in compartment app-compartmentallow group app-admins to manage volume-family in compartment app-compartmentallow group app-admins to read virtual-network-family in compartment app-compartment
Useful resource-type families:
instance-familyvolume-familyvirtual-network-familyobject-familydatabase-familystream-familyfunctions-family- etc.
- Instead of:
-
Scope to the smallest compartment possible.
Avoid “in tenancy” unless truly necessary; prefer “in compartment<name>”.
3. Edit the Policy in the Console
For each problematic policy:
-
In Identity → Policies, click the policy name.
-
Click Edit Policy.
-
In the Statements text box:
- Remove or change statements containing:
manage all-resourcesuse all-resources
- Replace them with:
- Specific resource families (e.g.,
instance-family,database-family) - Appropriate verb (
inspect,read,use,manage) - Narrower scope (
in compartment <name>instead ofin tenancy)
- Specific resource families (e.g.,
Example transformation:
Before:
allow group monitoring-ops to manage all-resources in tenancyAfter (more appropriate for monitoring use cases):
allow group monitoring-ops to read metrics in tenancyallow group monitoring-ops to read alarms in tenancyallow group monitoring-ops to read compartments in tenancyallow group monitoring-ops to inspect instances in tenancy(Adjust to your actual needs; often read/inspect is enough for monitoring.)
- Remove or change statements containing:
-
Click Save Changes.
4. Validate Access Still Works
- Identify a test user in the affected group (e.g., member of
monitoring-ops). - Log in as that user (or use Auth token + CLI to test).
- Confirm they can:
- Perform their required monitoring tasks (view metrics, alarms, logs, etc.).
- Cannot create/delete unrelated resources (e.g., VCNs, instances, buckets).
If something fails due to missing permission, add only the minimal additional statements needed.
5. Clean Up and Standardize
- Repeat the above steps for any remaining
manage/use all-resourcespolicies. - Document:
- Which groups have which policies.
- Which compartments those apply to.
- Going forward:
- Use compartment + resource-family + minimal verb for all new policies.
- Avoid
all-resourcesentirely unless under a controlled break-glass/admin account.
If you share one of your current policy statements, I can rewrite it into a least‑privilege version tailored to your exact monitoring use case.
Using CLI
Below is a step‑by‑step remediation using OCI CLI to fix policies that grant manage/use on all-resources, and replace them with least‑privilege Monitoring permissions.
Assumptions (adjust for your tenancy):
- You have OCI CLI configured (
oci setup configalready done). - You know:
- Compartment OCID where the policy lives:
COMPARTMENT_OCID - Group name that should have Monitoring access:
MONITORING_GROUP - Namespace you want to allow access to (optional):
my_app_ns
- Compartment OCID where the policy lives:
1. Identify Problem Policies
List policies in the compartment:
oci iam policy list \
--compartment-id COMPARTMENT_OCID \
--all
For each policy, inspect its statements:
oci iam policy get \
--policy-id POLICY_OCID \
--query 'data."statements"' \
--output table
Look for statements like:
allow group MONITORING_GROUP to manage all-resources in compartment <name>
allow group MONITORING_GROUP to use all-resources in compartment <name>
allow group MONITORING_GROUP to manage all-resources in tenancy
allow group MONITORING_GROUP to use all-resources in tenancy
Note the POLICY_OCID of each policy that has such statements.
2. Decide Desired Least‑Privilege Monitoring Access
Typical least‑privilege examples for Monitoring:
Read metrics only:
allow group MONITORING_GROUP to read metrics in compartment <compartment-name>
Manage alarms only:
allow group MONITORING_GROUP to manage alarms in compartment <compartment-name>
Optionally restrict metrics further by namespace:
allow group MONITORING_GROUP to read metrics in compartment <compartment-name> where target.metrics.namespace = 'my_app_ns'
You will replace the manage/use all-resources statements with such specific ones.
3. Export Existing Policy for Backup
For each affected policy:
oci iam policy get \
--policy-id POLICY_OCID \
--query 'data' \
--output json > old-policy-POLICY_OCID.json
Keep this as backup.
4. Build a Cleaned‑Up Policy Definition (Locally)
Open the backup JSON file and extract / edit the statements array.
For example, if original statements were:
"statements": [
"allow group MONITORING_GROUP to manage all-resources in compartment my-compartment",
"allow group OTHER_GROUP to manage users in tenancy"
]
Change to something like:
"statements": [
"allow group MONITORING_GROUP to read metrics in compartment my-compartment where target.metrics.namespace = 'my_app_ns'",
"allow group MONITORING_GROUP to manage alarms in compartment my-compartment",
"allow group OTHER_GROUP to manage users in tenancy"
]
Save this minimal JSON file (for update) as updated-statements.json:
{
"statements": [
"allow group MONITORING_GROUP to read metrics in compartment my-compartment where target.metrics.namespace = 'my_app_ns'",
"allow group MONITORING_GROUP to manage alarms in compartment my-compartment",
"allow group OTHER_GROUP to manage users in tenancy"
]
}
Alternatively, just keep the array and use --statements directly (see next step).
5. Update the Policy Using OCI CLI
Option A – Pass --statements directly (simpler):
oci iam policy update \
--policy-id POLICY_OCID \
--statements '[
"allow group MONITORING_GROUP to read metrics in compartment my-compartment where target.metrics.namespace = '\''my_app_ns'\''",
"allow group MONITORING_GROUP to manage alarms in compartment my-compartment",
"allow group OTHER_GROUP to manage users in tenancy"
]' \
--if-match "$(oci iam policy get --policy-id POLICY_OCID --query 'data."etag"' --raw-output)"
Note the quoting: ' around JSON, escaped ' inside the where clause.
Option B – Use a JSON file:
Create policy-update.json:
{
"statements": [
"allow group MONITORING_GROUP to read metrics in compartment my-compartment where target.metrics.namespace = 'my_app_ns'",
"allow group MONITORING_GROUP to manage alarms in compartment my-compartment",
"allow group OTHER_GROUP to manage users in tenancy"
]
}
Then:
ETAG=$(oci iam policy get --policy-id POLICY_OCID --query 'data."etag"' --raw-output)
oci iam policy update \
--policy-id POLICY_OCID \
--from-json file://policy-update.json \
--if-match "$ETAG"
This replaces the entire statements array, removing manage/use all-resources.
6. Verify the Updated Policy
oci iam policy get \
--policy-id POLICY_OCID \
--query 'data."statements"' \
--output table
Ensure:
- No statement includes
manage all-resourcesoruse all-resources. - Monitoring group has only the specific Monitoring permissions you want.
7. (Optional) Split Broad Policies into Separate Monitoring‑Specific Policy
Instead of mixing Monitoring and non‑Monitoring permissions in a single policy, you can:
- Create a new Monitoring policy:
oci iam policy create \
--compartment-id COMPARTMENT_OCID \
--name "monitoring-least-privilege-policy" \
--description "Least-privilege Monitoring access" \
--statements '[
"allow group MONITORING_GROUP to read metrics in compartment my-compartment where target.metrics.namespace = '\''my_app_ns'\''",
"allow group MONITORING_GROUP to manage alarms in compartment my-compartment"
]'
- Edit the old policy to remove
MONITORING_GROUPlines, keeping only non‑Monitoring ones.
If you paste a sample of your current problematic policy statements, I can give you an exact oci iam policy update command tailored to your case.
Using Python
Below is a practical way to detect and remediate OCI IAM policies that grant manage/use on all-resources, and then restrict them to Monitoring-only permissions using Python and the OCI SDK.
1. Decide What “Monitoring-Only” Access Should Be
Typical least-privilege Monitoring permissions look like:
Read-only monitoring (view metrics and alarms):
allow group <group-name> to read metrics in compartment <compartment-name>
allow group <group-name> to read alarms in compartment <compartment-name>
allow group <group-name> to use metrics-family in compartment <compartment-name>
If you genuinely need to manage alarms:
allow group <group-name> to manage alarms in compartment <compartment-name>
allow group <group-name> to use metrics-family in compartment <compartment-name>
Replace:
<group-name>with the actual group name used in the overbroad policy.<compartment-name>with the correct compartment.
You will be replacing overbroad statements like:
allow group <group-name> to manage all-resources in tenancy
allow group <group-name> to use all-resources in compartment <compartment-name>
with the minimal set above.
2. Install and Configure the OCI Python SDK
pip install oci
Set up your ~/.oci/config or environment variables (tenancy, user OCID, key, region).
Example ~/.oci/config:
[DEFAULT]
user=ocid1.user.oc1..aaaa...
fingerprint=aa:bb:cc:dd:...
key_file=~/.oci/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..aaaa...
region=eu-frankfurt-1
3. Python Script: Find and Fix Overbroad Policies
This script:
- Lists policies in a given compartment or tenancy.
- Looks for statements containing
manage all-resourcesoruse all-resources. - For statements containing a target group you care about, it:
- Removes the overbroad lines.
- Appends Monitoring-only statements.
- Updates the policy.
Important:
- Run in dry-run mode first (set
DRY_RUN = True) to see what would change. - Adjust
TARGET_GROUPS,MONITORING_STATEMENTS, and compartments to match your environment.
import oci
import re
# ---------- CONFIG ----------
PROFILE = "DEFAULT" # profile in ~/.oci/config
COMPARTMENT_OCID = "<compartment-ocid-or-tenancy-ocid>" # where policies live
DRY_RUN = True # set to False when you are sure
TARGET_GROUPS = ["MyMonitoringGroup"] # groups you want to fix
# --------------------------------
# Minimal monitoring-only policy lines to add per group and compartment
def monitoring_statements_for_group(group_name, compartment_name):
return [
f"allow group {group_name} to read metrics in compartment {compartment_name}",
f"allow group {group_name} to read alarms in compartment {compartment_name}",
f"allow group {group_name} to use metrics-family in compartment {compartment_name}",
# uncomment if they must manage alarms
# f"allow group {group_name} to manage alarms in compartment {compartment_name}",
]
def main():
config = oci.config.from_file(profile_name=PROFILE)
identity_client = oci.identity.IdentityClient(config)
# List policies in the chosen compartment/tenancy
policies = oci.pagination.list_call_get_all_results(
identity_client.list_policies,
compartment_id=COMPARTMENT_OCID
).data
for policy in policies:
original_statements = list(policy.statements or [])
new_statements = []
modified = False
print(f"\nChecking policy: {policy.name} ({policy.id})")
# Determine compartment name (optional, for better rules)
try:
comp = identity_client.get_compartment(policy.compartment_id).data
compartment_name = comp.name
except Exception:
compartment_name = "ROOT" # fallback; adjust as needed
for stmt in original_statements:
stmt_stripped = stmt.strip()
lower_stmt = stmt_stripped.lower()
# Does this statement grant manage/use all-resources?
if (
(" manage all-resources " in lower_stmt or
" use all-resources " in lower_stmt or
lower_stmt.endswith(" manage all-resources") or
lower_stmt.endswith(" use all-resources"))
and "group " in lower_stmt
):
# Check if this statement involves one of our target groups
involves_target = any(
re.search(rf"\bgroup\s+{re.escape(g.lower())}\b", lower_stmt)
for g in TARGET_GROUPS
)
if involves_target:
print(f" - Found overbroad statement to fix: '{stmt_stripped}'")
modified = True
# For each group in this statement, add monitoring-only rules
for g in TARGET_GROUPS:
if re.search(rf"\bgroup\s+{re.escape(g.lower())}\b", lower_stmt):
ms = monitoring_statements_for_group(g, compartment_name)
print(f" -> Replacing with least-privilege Monitoring rules for group {g}:")
for line in ms:
print(f" {line}")
if line not in new_statements:
new_statements.append(line)
# Do NOT keep the overbroad statement
continue
# If statement is not overbroad (or not on target group), keep as-is
new_statements.append(stmt_stripped)
if modified:
print(f"\nPolicy '{policy.name}' will be UPDATED.")
print("Old statements:")
for s in original_statements:
print(f" {s}")
print("New statements:")
for s in new_statements:
print(f" {s}")
if not DRY_RUN:
update_details = oci.identity.models.UpdatePolicyDetails(
description=policy.description,
statements=new_statements,
version_date=policy.version_date
)
identity_client.update_policy(policy.id, update_details)
print(f"Policy '{policy.name}' updated.")
else:
print("DRY RUN: No changes sent to OCI.")
else:
print(" No overbroad Monitoring-related statements found to remediate.")
if __name__ == "__main__":
main()
4. Steps to Use Safely
- Fill in:
COMPARTMENT_OCIDTARGET_GROUPS
- Start with
DRY_RUN = True. - Review the script’s console output for each policy.
- Once satisfied, set
DRY_RUN = Falseand run again. - Test that Monitoring users can still perform required actions (view metrics/alarms, manage alarms if needed).
If you share an example of one of your current overbroad policy statements, I can give you the exact replacement statements and a tighter filter for the script.
Using Terraform
resource "oci_identity_policy" "monitoring_policy" {
# Replace with your tenancy or compartment OCID that owns the policy
compartment_id = "OCID_OF_TENANCY_OR_COMPARTMENT"
name = "MONITORING_POLICY_NAME"
description = "Least-privilege IAM policy for Monitoring"
# Replace GROUP_NAME with the name of the IAM group that needs Monitoring access
# Replace COMPARTMENT_OCID_WITH_MONITORED_RESOURCES with the compartment OCID whose resources are being monitored
statements = [
# Narrowed from: "Allow group GROUP_NAME to manage all-resources in tenancy"
# or: "Allow group GROUP_NAME to use all-resources in tenancy"
"Allow group GROUP_NAME to use metrics in tenancy",
"Allow group GROUP_NAME to manage alarms in compartment COMPARTMENT_OCID_WITH_MONITORED_RESOURCES"
]
}
Changing the statements of oci_identity_policy updates the policy in place and does not force replacement of the resource.
For verification, terraform plan should show the existing oci_identity_policy with its statements being updated from manage/use all-resources to the more specific Monitoring permissions shown above, with no other changes.