Skip to main content

OCI Governance Policies Should Not Grant Unrestricted

More Info:

Flag any IAM policy statement that grants broad verbs (manage/use) across all-resources to unconstrained groups. Wildcard administrative grants are the most critical vulnerability in identity perimeters.

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)
  • 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

Using Console

Below are concise, console-focused steps to remediate the issue “OCI Governance Policies Should Not Grant Unrestricted Resource Access” for OCI Governance Monitoring, by tightening IAM policies to least privilege.


1. Identify the Problem Policies

  1. Sign in to the OCI Console.
  2. Open the navigation menu → Identity & SecurityPolicies.
  3. Ensure you are in the root compartment (or the compartment where your Governance policies are defined).
  4. Look for policies related to:
    • governance-monitoring
    • governance-rule-family
    • or any policy used by your Governance Monitoring dynamic group or user group.
  5. Open each candidate policy and look for overly broad statements, such as:
    • Allow group <name> to manage all-resources in tenancy
    • Allow dynamic-group <name> to manage all-resources in compartment <name>
    • or use of manage with all-resources or inspect/use all-resources across the tenancy.

These are the ones that need to be remediated.


2. Determine the Minimum Required Access

Verify what the Governance Monitoring service actually needs. In most environments, it only requires permissions to:

  • Read configuration / resources to evaluate governance rules.
  • Write/read its own governance rule configurations and evaluation results.

Common resource-types involved:

  • governance-rule-family
  • Possibly instance-family, object-family, vcn-family, tag-namespaces (for read/inspect only), depending on what the rules evaluate.

Your goal: restrict “manage all-resources” to only the specific resource-families and only with the minimal verb (inspect/use/read/manage) required.


3. Edit the Policy to Remove Unrestricted Access

For each over-permissive policy:

  1. From the Policies page, click the policy name.
  2. Click Edit Policy Statements.
  3. In the existing statements:
    • Remove or rewrite lines that include:
      • all-resources
      • in tenancy when not needed (use specific compartments instead)
      • manage when lesser verbs like inspect/read/use suffice.

Example: Bad Policy

Allow dynamic-group governance-monitoring-dg to manage all-resources in tenancy

Example: More Restrictive Replacement

Adjust based on what you actually need. A typical least-privilege pattern might look like:

Allow dynamic-group governance-monitoring-dg to inspect all-resources in tenancy
Allow dynamic-group governance-monitoring-dg to use governance-rule-family in tenancy

Or, further compartment scoped:

Allow dynamic-group governance-monitoring-dg to inspect all-resources in compartment <governance-compartment>
Allow dynamic-group governance-monitoring-dg to use governance-rule-family in compartment <governance-compartment>

Key principles:

  • Replace manage all-resources with:
    • inspect all-resources where only read/visibility is needed, or
    • Resource-specific access (e.g., use governance-rule-family) where write is needed.
  • Scope from in tenancy down to the specific compartment(s) where Governance rules and targets are defined, if possible.
  1. After editing, click Save Changes.

4. Validate Governance Monitoring Still Works

  1. Go to Governance & Administration (or Security depending on tenant layout) → Governance Rules / Governance Monitoring.
  2. Run:
    • A manual evaluation or
    • Confirm scheduled evaluations run successfully and generate results.
  3. If evaluation fails with a permission error, revisit the policy and:
    • Add narrowly scoped inspect or use permissions only for the exact resource-type mentioned in the error.
    • Avoid reverting back to manage all-resources.

5. Clean Up Any Redundant or Legacy Policies

  1. In Identity & Security → Policies, review for older, unused, or overlapping policies that still grant:
    • manage all-resources
    • Very broad inspect all-resources in tenancy not needed by Governance.
  2. If confirmed unused:
    • Either delete the policy or
    • Comment out/replace the broad statements with more specific ones.

If you share a current policy statement you’re using for Governance Monitoring, I can rewrite it to a least-privilege version you can paste directly into the console.

Using CLI

Below is a practical, CLI‑only approach to identify and remediate overly permissive OCI IAM policies that violate “Governance Policies Should Not Grant Unrestricted Resource Access” (e.g., those used for Governance Monitoring / Cloud Guard or custom governance tooling).


1. Identify Overly Permissive Policies

Typical “unrestricted” patterns you want to flag:

  • allow group <name> to manage all-resources in tenancy
  • allow group <name> to inspect all-resources in tenancy
  • allow group <name> to read all-resources in tenancy
  • Any in tenancy with very broad verbs (manage) and wildcards.

1.1 List Policies in Your Tenancy

TENANCY_OCID="<your_tenancy_ocid>"

oci iam policy list \
--compartment-id "$TENANCY_OCID" \
--all \
--output table \
--query "data[].{Name:\"name\", OCID:\"id\", Description:\"description\"}"

If you know the compartment where governance/monitoring policies live, replace TENANCY_OCID with that compartment OCID.

1.2 Inspect Each Policy’s Statements

For a specific policy:

POLICY_OCID="<policy_ocid>"

oci iam policy get \
--policy-id "$POLICY_OCID" \
--query "data.{Name:name,Description:description,Statements:statements}" \
--output json

Look for statements that:

  • Use all-resources
  • Use in tenancy instead of a compartment
  • Grant manage at too broad a scope

Example of a problematic statement:

Allow group governance-monitors to inspect all-resources in tenancy

2. Decide the Correct Scope and Permissions

Before changing anything, decide:

  1. Which group truly needs what:
    e.g., governance-monitors.

  2. What access level is actually required for governance monitoring:
    Commonly:

    • inspect or read on specific services (e.g., audit-events-family, instances, volumes, buckets).
    • Rarely manage, and only for specific resource types if automation is needed.
  3. Where (tenancy vs compartment):
    Prefer compartment scoping (in compartment <compartment_name> or using compartment OCIDs) unless full‑tenancy visibility is absolutely necessary.

Example: For read‑only governance monitoring that just needs to see resources, you might use something like:

Allow group governance-monitors to inspect instances in tenancy
Allow group governance-monitors to inspect volumes in tenancy
Allow group governance-monitors to inspect buckets in tenancy
Allow group governance-monitors to inspect audit-events-family in tenancy

Still tenancy‑wide, but resource-specific, not all-resources.

If you can limit to a compartment:

Allow group governance-monitors to inspect all-resources in compartment <compartment-name>

3. Update the Policy via OCI CLI

You cannot partially edit a single statement; you replace the entire statement list.

3.1 Save the Existing Policy (Backup)

POLICY_OCID="<policy_ocid>"

oci iam policy get \
--policy-id "$POLICY_OCID" \
--query "data" \
--output json > policy-backup.json

This gives you name, description, statements, etc., in case you need to revert.

3.2 Prepare a New Statements File

Create a JSON file containing the new, least‑privilege list of statements, for example new-statements.json:

{
"statements": [
"Allow group governance-monitors to inspect instances in tenancy",
"Allow group governance-monitors to inspect volumes in tenancy",
"Allow group governance-monitors to inspect buckets in tenancy",
"Allow group governance-monitors to inspect audit-events-family in tenancy"
]
}

Or, if you can scope to a compartment (preferred):

{
"statements": [
"Allow group governance-monitors to inspect all-resources in compartment my-governance-compartment"
]
}

You can build this file from the backup, removing/replacing the problematic lines.

3.3 Apply the New Statements to the Policy

Extract the array from the JSON file and provide it to oci iam policy update:

NEW_STATEMENTS=$(jq -r '.statements' new-statements.json)

oci iam policy update \
--policy-id "$POLICY_OCID" \
--statements "$NEW_STATEMENTS" \
--force

If you also want to adjust the description to reflect that it’s restricted:

oci iam policy update \
--policy-id "$POLICY_OCID" \
--description "Governance monitoring policy with least-privilege access (no unrestricted all-resources)" \
--statements "$NEW_STATEMENTS" \
--force

Note: jq is used here to pass a proper JSON array to --statements. Ensure jq is installed, or manually inline the array string.


4. Verify the Remediation

4.1 Confirm the New Statements

oci iam policy get \
--policy-id "$POLICY_OCID" \
--query "data.statements" \
--output json

Verify that:

  • No statement uses all-resources in tenancy (unless contractually required and justified).
  • No statement uses overly broad manage where only inspect/read is needed.

4.2 Validate Governance Monitoring Still Works

  • Trigger or run your governance monitoring / Cloud Guard / custom governance jobs.
  • Check for any failures or missing visibility. If something fails, grant only the additional minimal actions required (e.g., add a specific inspect <service-family> statement) and repeat.

5. Optional: Automate Detection of Unrestricted Policies

If you want to programmatically detect problematic policies with CLI + jq:

oci iam policy list \
--compartment-id "$TENANCY_OCID" \
--all \
--output json \
| jq '.data[] | select(.statements[] | test("all-resources in tenancy"; "i")) | {name, id, statements}'

This shows policies where any statement contains all-resources in tenancy.

You can similarly search for manage all-resources or other patterns.


If you can share an example of the exact problematic policy statement you’re seeing for “OCI Governance Monitoring,” I can give you a minimal, concrete replacement statement set tailored to that use case.

Using Python

Below is a concise approach to detect and then remediate overly permissive OCI policies (granting unrestricted resource access) using Python and the OCI SDK, suitable for use in a “Governance Monitoring” style workflow.


1. What “Unrestricted Resource Access” Typically Looks Like

In OCI policy language, these are examples of overly broad statements:

  • Allow group <name> to manage all-resources in tenancy
  • Allow group <name> to inspect all-resources in tenancy
  • Allow group <name> to use all-resources in tenancy
  • Same patterns but in compartment <compartment-name> when the scope should be more granular.

Your goal: detect these and then replace them with more restrictive, service- or resource-specific statements.


2. Prerequisites

  1. Install SDK:
    pip install oci
  2. Configure ~/.oci/config with:
    [DEFAULT]
    user=ocid1.user.oc1..xxxx
    fingerprint=xx:xx:xx:xx
    key_file=/path/to/oci_api_key.pem
    tenancy=ocid1.tenancy.oc1..xxxx
    region=us-ashburn-1

3. Python: Detect Policies With Unrestricted Resource Access

This script:

  • Lists all compartments
  • Lists all IAM policies
  • Flags statements with all-resources or in tenancy patterns
import oci
import re

config = oci.config.from_file()
identity = oci.identity.IdentityClient(config)
tenancy_id = config["tenancy"]

# Regex patterns for "unrestricted" policies
ALL_RESOURCES_PATTERN = re.compile(r"\ball-resources\b", re.IGNORECASE)
TENANCY_SCOPE_PATTERN = re.compile(r"\bin tenancy\b", re.IGNORECASE)

def list_all_compartments(tenancy_id):
compartments = []
response = oci.pagination.list_call_get_all_results(
identity.list_compartments,
tenancy_id,
compartment_id_in_subtree=True
)
compartments.extend(response.data)
return compartments

def list_policies_for_compartment(compartment_id):
return oci.pagination.list_call_get_all_results(
identity.list_policies,
compartment_id
).data

def is_unrestricted_statement(statement: str) -> bool:
# Customize here to tighten rules if needed
if ALL_RESOURCES_PATTERN.search(statement) and TENANCY_SCOPE_PATTERN.search(statement):
return True
# Optionally also flag "manage all-resources in compartment"
if "manage all-resources" in statement.lower():
return True
return False

def main():
print("Scanning for overly permissive OCI policies...")
compartments = list_all_compartments(tenancy_id)
# Include root tenancy as a "compartment"
compartments.append(identity.get_tenancy(tenancy_id).data)

findings = []

for cmp in compartments:
cmp_id = cmp.id
cmp_name = getattr(cmp, "name", tenancy_id)

policies = list_policies_for_compartment(cmp_id)
for policy in policies:
for stmt in policy.statements:
if is_unrestricted_statement(stmt):
findings.append({
"compartment_id": cmp_id,
"compartment_name": cmp_name,
"policy_id": policy.id,
"policy_name": policy.name,
"statement": stmt
})

if not findings:
print("No unrestricted policies found.")
return

print("\nUnrestricted policy statements found:")
for f in findings:
print(f"Compartment: {f['compartment_name']} ({f['compartment_id']})")
print(f" Policy: {f['policy_name']} ({f['policy_id']})")
print(f" Statement: {f['statement']}")
print("-" * 80)

if __name__ == "__main__":
main()

Use this for continuous Governance Monitoring (run as a scheduled job, send results to a log/Lambda/function, etc.).


4. Remediation Strategy (Conceptual)

You should not blindly auto-edit policies; you must understand what each group actually needs. General pattern:

  • Replace:
    Allow group devs to manage all-resources in tenancy
  • With more specific:
    Allow group devs to manage instances in compartment dev-compartment
    Allow group devs to use virtual-network-family in compartment dev-compartment
    Allow group devs to use volume-family in compartment dev-compartment

Basic steps:

  1. For each flagged statement:

    • Identify the group or dynamic-group.
    • Identify what services/resources they truly require.
    • Draft new statements that:
      • Replace all-resources with specific verbs and resource-types (e.g. instances, volume-family, virtual-network-family).
      • Replace in tenancy with appropriate in compartment <name>.
  2. Update the policy using the OCI SDK.


5. Python: Example of Updating a Policy

Below is a template that:

  • Reads an existing policy
  • Rewrites statements using a mapping you control
  • Updates the policy

You must define rewrite_statement to encode your organization’s rules.

import oci

config = oci.config.from_file()
identity = oci.identity.IdentityClient(config)

def rewrite_statement(original_stmt: str) -> str | None:
"""
Custom logic to rewrite broad statements.
Return:
- new statement string if you want to replace it
- None if you want to remove the statement
- original_stmt if you want to keep it
"""
stmt_lower = original_stmt.lower()

# Example 1: devs have too-broad tenancy-level access
if "allow group devs to manage all-resources in tenancy" in stmt_lower:
# Replace with restricted dev access
return (
"Allow group devs to manage instances in compartment dev-compartment\n"
"Allow group devs to use virtual-network-family in compartment dev-compartment\n"
"Allow group devs to use volume-family in compartment dev-compartment"
)

# Example 2: generic "manage all-resources in tenancy" for any group – flag for manual review
if "manage all-resources in tenancy" in stmt_lower:
print(f"[MANUAL REVIEW NEEDED] {original_stmt}")
# Don't auto-change; return as-is or None depending on your policy
return original_stmt

# Default: no change
return original_stmt

def update_policy(policy_id: str):
# Get existing policy
existing = identity.get_policy(policy_id).data

new_statements = []
for stmt in existing.statements:
new_stmt = rewrite_statement(stmt)
if not new_stmt:
continue
# If rewrite returns multi-line, split into separate OCI statements
for s in new_stmt.splitlines():
if s.strip():
new_statements.append(s.strip())

# If no changes, skip
if new_statements == existing.statements:
print(f"No changes for policy {existing.name}")
return

details = oci.identity.models.UpdatePolicyDetails(
description=existing.description,
statements=new_statements,
version_date=existing.version_date,
freeform_tags=existing.freeform_tags,
defined_tags=existing.defined_tags
)

print(f"Updating policy {existing.name} ({policy_id})...")
identity.update_policy(policy_id, details)
print("Update complete.")

if __name__ == "__main__":
# Example: call with a known policy OCID you want to fix
POLICY_OCID = "ocid1.policy.oc1..xxxx"
update_policy(POLICY_OCID)

Important:

  • Test changes in a non-production tenancy or compartment first.
  • Consider exporting policies (e.g., into Git) before bulk edits for rollback.
  • For governance monitoring, usually you:
    • Detect problematic policies automatically.
    • Open tickets or send alerts to owners.
    • Apply changes manually or through a controlled pipeline.

6. Integrating with “OCI Governance Monitoring”

To make this part of a governance solution:

  • Run the detection script periodically (OCI Functions, scheduled job, CI pipeline).
  • Send findings to:
    • OCI Logging / Object Storage, or
    • A ticketing system (ServiceNow/Jira) via webhook, or
    • Email/Slack via your automation layer.
  • For high-risk cases (e.g., manage all-resources in tenancy), require manual review.
  • For low-risk patterns you’ve standardized, use the update script with a carefully controlled rule set.

If you share an example of a specific policy statement you have, I can give a concrete “before/after” rewrite and the exact Python logic to handle that pattern.

Using Terraform
resource "oci_governance_rules_tenancy_policy" "GOVERNANCE_POLICY_NAME" {
# Replace with the OCID of the tenancy where the governance policy is defined
compartment_id = var.TENANCY_OCID

# Replace with the governance tenancy policy display name
display_name = "GOVERNANCE_TENANCY_POLICY_DISPLAY_NAME"

# Replace with the description you want for the policy
description = "Hardened governance tenancy policy without wildcard admin access"

# Remediation: remove broad 'manage/use all-resources in tenancy' grants
# and scope permissions to specific resource families and compartments.
#
# BEFORE (vulnerable example, do NOT keep):
# "Allow group OPERATORS_GROUP to manage all-resources in tenancy"

statements = [
# Example of scoped permissions – adjust to the actual groups, verbs, and resources you require.
# PRINCIPAL: group OPERATORS_GROUP can administer compute instances
# SCOPE: only 'instance-family' resources
# LOCATION: only in a specific compartment
"Allow group OPERATORS_GROUP to manage instance-family in compartment COMPARTMENT_NAME",

# PRINCIPAL: group NETWORK_ADMINS_GROUP manages network resources
# SCOPE: only 'virtual-network-family'
# LOCATION: only in a specific compartment
"Allow group NETWORK_ADMINS_GROUP to manage virtual-network-family in compartment NETWORK_COMPARTMENT_NAME",

# PRINCIPAL: group READONLY_GROUP gets read-only access
# SCOPE: specific families instead of all-resources
# LOCATION: entire tenancy is acceptable for read-only, but verbs are limited to 'inspect'
"Allow group READONLY_GROUP to inspect instance-family in tenancy",
"Allow group READONLY_GROUP to inspect virtual-network-family in tenancy",
]
}

Substitute:

  • TENANCY_OCID with the target tenancy OCID.
  • GOVERNANCE_TENANCY_POLICY_DISPLAY_NAME with the existing governance tenancy policy display name.
  • OPERATORS_GROUP, NETWORK_ADMINS_GROUP, READONLY_GROUP with your actual OCI IAM group names.
  • COMPARTMENT_NAME, NETWORK_COMPARTMENT_NAME with the exact compartment names/OCIDs you want to scope access to.

This change updates the existing governance tenancy policy in place (no resource replacement), but it can immediately reduce privileges for affected groups once applied, so coordinate the change with application and operations owners.

For verification, terraform plan should show the oci_governance_rules_tenancy_policy.GOVERNANCE_POLICY_NAME resource with a change only in its statements attribute, removing any manage all-resources in tenancy / use all-resources in tenancy lines and replacing them with the more scoped statements you defined.