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 & Security → Identity → Policies.

  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.