OCI IAM Policies Explained with Real Examples

OCI IAM Policies

In Oracle Cloud Infrastructure (OCI), policies define who (groups) can access what resources (compartments/services) and how (permissions/verbs). They are written in a human-readable format like: “Allow group X to manage Y in compartment Z.”

Policies are attached at the tenancy or compartment level and follow a least-privilege model, ensuring users get only the access required to perform their tasks.

Policy syntax anatomy

OCI uses human-readable policy statements attached to compartments. Every OCI policy statement follows a strict grammar with five (sometimes six) components:




Example — basic policy => Allow group NetworkAdmins to manage virtual-network-family in compartment production


If you observe the above navigation, policies sits outside of the domains - This  ensures centralized access control, so a single policy can govern users across multiple domains and resources.
Identity domains manage users and groups, while policies control what those groups can do—keeping authentication (who you are) separate from authorization (what you can access). This separation improves scalability, consistency, and security across the environment.

The verb hierarchy

Verbs are cumulative — each level includes all permissions from the levels below it:

Verb hierarchy (least → most permissive)

  • inspect  →  list resources, view metadata
  • read     →  inspect + get resource contents
  • use      →  read + work with existing resources
  • manage   →  use + create, update, delete resources

Dynamic Groups — The Real Power of OCI IAM

Dynamic groups allow you to grant IAM policies to OCI resources (like compute instances, functions, or data science notebooks) rather than to human users or service accounts. 
This is how you avoid hardcoding credentials. A dynamic group is defined by a matching rule — an expression that determines which resources belong to the group based on their 
attributes.

Dynamic group matching rule syntax

Match all instances in a specific compartment 
All {instance.compartment.id = 'ocid1.compartment.oc1..aaaabbbbcccc'}

Match a specific instance by OCID
Any {instance.id = 'ocid1.instance.oc1.ap-mumbai-1..aaaabbbb'}

Match OCI Functions in a compartment (serverless)
All {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..xxxxxx'}
 
Match Data Science notebook sessions
All {resource.type = 'datasciencenotebooksession', resource.compartment.id = 'ocid1.compartment.oc1..xxxxxx'}



Example:-  Compute Instance → Object Storage Access

This is the most common pattern in OCI projects. Instead of baking access keys into your application code or instance user data, you use Instance Principal authentication.

  1. Create the dynamic group and matching rule
  2. Create the policy
  3. Use instance principal in application access code

Policy for compartment level access:- 

Cross-compartment access is where many developers hit a wall. The key insight: the policy must be written in the compartment that contains the resource being accessed, 
OR in a parent compartment that has authority over both.

-- This policy is attached to the ROOT TENANCY ---- (so it has authority over all compartments)  --

Allow group Developers to read secret-family in compartment security-compartment

-- OR: attach policy to security-compartment itself --

Allow group Developers to read secret-family in compartment id ocid1.compartment.oc1..security

Using Conditions (Where Clauses):-

Conditions let you add fine-grained filters to any policy statement. They support logical operators AND, OR, and comparison operators like =, !=, in.

Condition examples

-- Restrict to specific resource --
Allow group Auditors to read buckets in tenancy where target.bucket.name = 'audit-logs-bucket'

-- Require MFA for admin actions --
Allow group Admins to manage all-resources in tenancy where request.user.mfaTotpVerified = 'true'

-- Multiple conditions with AND, block deletes --
Allow group DataEngineers to manage objects in compartment analytics where all {target.bucket.name = 'raw-data', request.operation != 'DeleteObject'}


Refer to the below table for the common request and target variables using it in the condition.


Troubleshooting: Why Your Policy Isn't Working

  • Verify the policy is attached to the correct compartment (not just the user's compartment)
  • Check that the group name in the policy exactly matches the IAM group name (case-sensitive)
  • For dynamic groups, confirm the resource's OCID or compartment OCID matches the matching rule
  • Check OCI Audit logs for the actual error message and resource OCID that was denied
  • Wait 60 seconds after any policy change before retesting
  • Use the Policy Simulator (Identity → Policy → Simulate) to test before applying
  • Ensure there is no explicit DENY policy overriding your ALLOW (deny takes precedence)

Best Practices Checklist

  • Always follow least-privilege — grant only the verb and resource-type you actually need
  • Use dynamic groups + instance principals instead of API keys for OCI-to-OCI communication
  • Scope object storage access to specific buckets using where target.bucket.name
  • Require MFA for admin policies using where request.user.mfaTotpVerified = 'true'
  • Attach root-level policies only for cross-compartment access; keep other policies compartment-local
  • Use compartment OCID (not name) in policies for portability and to avoid name-collision bugs
  • Document every policy with a description explaining the business reason it exists
  • Audit policy list quarterly — remove access that is no longer needed
  • Never use manage all-resources in tenancy for anything other than the OCI administrator group

Summary:

OCI IAM policies become intuitive once you internalize three things: the policy must live near the resource (not the requester),  dynamic groups need an accompanying policy to do anything, and the verb hierarchy saves you from over-granting permissions.

No comments:

Post a Comment