Skip to main content

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

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

  1. Sign in to the OCI Console.

  2. Open the navigation menu (☰) → Identity & SecurityIdentityPolicies.

  3. In the Scope selector at the top left, check both:

    • Tenancy level (root)
    • Each compartment where you define policies
  4. 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:

  1. Which principal actually needs access?

    • Group? Dynamic group? User?
  2. Which services/resources do they really need?
    Replace all-resources with 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-compartment
      allow group app-admins to manage volume-family in compartment app-compartment
      allow group app-admins to read virtual-network-family in compartment app-compartment

    Useful resource-type families:

    • instance-family
    • volume-family
    • virtual-network-family
    • object-family
    • database-family
    • stream-family
    • functions-family
    • etc.
  3. 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:

  1. In Identity → Policies, click the policy name.

  2. Click Edit Policy.

  3. In the Statements text box:

    • Remove or change statements containing:
      • manage all-resources
      • use 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 of in tenancy)

    Example transformation:

    Before:

    allow group monitoring-ops to manage all-resources in tenancy

    After (more appropriate for monitoring use cases):

    allow group monitoring-ops to read metrics in tenancy
    allow group monitoring-ops to read alarms in tenancy
    allow group monitoring-ops to read compartments in tenancy
    allow group monitoring-ops to inspect instances in tenancy

    (Adjust to your actual needs; often read/inspect is enough for monitoring.)

  4. Click Save Changes.


4. Validate Access Still Works

  1. Identify a test user in the affected group (e.g., member of monitoring-ops).
  2. Log in as that user (or use Auth token + CLI to test).
  3. 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

  1. Repeat the above steps for any remaining manage/use all-resources policies.
  2. Document:
    • Which groups have which policies.
    • Which compartments those apply to.
  3. Going forward:
    • Use compartment + resource-family + minimal verb for all new policies.
    • Avoid all-resources entirely 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 config already 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

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-resources or use 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:

  1. 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"
]'
  1. Edit the old policy to remove MONITORING_GROUP lines, 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:

  1. Lists policies in a given compartment or tenancy.
  2. Looks for statements containing manage all-resources or use all-resources.
  3. For statements containing a target group you care about, it:
    • Removes the overbroad lines.
    • Appends Monitoring-only statements.
  4. 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

  1. Fill in:
    • COMPARTMENT_OCID
    • TARGET_GROUPS
  2. Start with DRY_RUN = True.
  3. Review the script’s console output for each policy.
  4. Once satisfied, set DRY_RUN = False and run again.
  5. 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.