Skip to content

Instantly share code, notes, and snippets.

@asheliahut
Created March 13, 2026 18:17
Show Gist options
  • Select an option

  • Save asheliahut/8475c516df33df3325595946435e462c to your computer and use it in GitHub Desktop.

Select an option

Save asheliahut/8475c516df33df3325595946435e462c to your computer and use it in GitHub Desktop.
Oracle Policy Syntax Guide Simplified

Oracle Cloud Infrastructure (OCI) — IAM Policy Syntax

Overview

OCI IAM policies control who can access which resources, how, and under what conditions. All resources have an implicit deny by default — access must be explicitly granted via policy statements. Policies are collections of one or more statements written in a human-readable language.


Basic Syntax

Allow <subject> to <verb> <resource-type> in <location> [where <condition>]

Every standard policy statement begins with Allow. The where clause is optional.

Element Description
subject Who is being granted access (group, dynamic group, etc.)
verb Level of access (inspect, read, use, manage)
resource-type The OCI resource being targeted
location A compartment or the full tenancy
condition Optional filter to further restrict access

Note: Policy syntax is case-insensitive. Allow, allow, and ALLOW are all valid.


Subjects

The subject defines who the policy applies to.

# Named group (default identity domain)
Allow group Developers to ...

# Group with spaces in name (use single quotes)
Allow group 'Dev Team' to ...

# Group by OCID
Allow group id ocid1.group.oc1..aaaaaaaaqjihfhvxmumrl3isyrjw3n6c4rzwskaawuc7i5xwe6s7qmnsbc6a to ...

# Multiple groups (comma-separated)
Allow group A-Admins, B-Admins to ...

# Group in a non-default identity domain
Allow group FederatedDomain/Engineers to ...

# Dynamic group (for compute instances / service principals)
Allow dynamic-group MyInstanceGroup to ...

# Dynamic group in a specific identity domain
Allow dynamic-group MyDomain/MyInstanceGroup to ...

# All users in the tenancy (use sparingly)
Allow any-user to ...

# All groups in the tenancy
Allow any-group to ...

Tip: Use single quotes around group names that contain spaces.


Verbs

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

Verb Access Level Typical Capabilities
inspect Lowest List resources, get basic metadata
read Low All of inspect + get full resource details/contents
use Medium All of read + modify/work with existing resources
manage Highest All of read + use + create and delete resources
# Read-only: list and view instances
Allow group Auditors to read instances in tenancy

# Use: work with existing volumes (but not create/delete)
Allow group AppTeam to use volumes in compartment Production

# Full control
Allow group StorageAdmins to manage buckets in tenancy

Resource Types

Individual resource type

Allow group Developers to manage instances in compartment Dev
Allow group Developers to manage volumes in compartment Dev

Family resource type (grouped related resources)

# instance-family covers: instances, images, volume attachments, console connections
Allow group Developers to manage instance-family in compartment Dev

# virtual-network-family covers: VCNs, subnets, security lists, route tables, etc.
Allow group NetAdmins to manage virtual-network-family in tenancy

# volume-family covers: volumes, volume attachments, volume backups
Allow group StorageOps to manage volume-family in compartment Prod

# object-family covers: buckets and objects
Allow group StorageAdmins to manage object-family in tenancy

All resources

Allow group ProjectAdmins to manage all-resources in compartment Project-A

Location

Specifies the compartment or tenancy the policy applies to. Policies inherit downward — access granted at a parent compartment applies to all child compartments.

# Entire tenancy
Allow group Admins to manage all-resources in tenancy

# Specific compartment by name
Allow group Developers to manage instance-family in compartment Dev

# Compartment by OCID
Allow group Developers to manage instance-family in compartment id ocid1.compartment.oc1..aaaaaaaaexampleocid

# Nested compartment path (colon separator)
Allow group TeamA to use object-family in compartment Prod:TeamA:Storage

Note: IAM resources (users, groups, policies) live in the tenancy (root compartment), so their policies reference tenancy not compartment.


{} Curly Braces — A Complete Guide

Curly braces {} serve two distinct purposes in OCI IAM policy language, and understanding when to use each form is critical to writing correct policies.


Use Case 1: Granular Permission Sets (in the verb position)

Curly braces replace a verb with a named set of specific atomic permissions. Instead of granting all the permissions bundled into inspect, read, use, or manage, you can list exactly which individual permissions are granted.

Permissions are always written in ALL_CAPS_WITH_UNDERSCORES.

Allow <subject> to {PERMISSION_ONE, PERMISSION_TWO, ...} <resource-type> in <location>

Examples

# Grant ONLY the ability to inspect and read vault details — not create/delete
Allow any-user to {VAULT_INSPECT, VAULT_READ} vaults in compartment open-vault

# Grant update permission on load balancers without granting full "use" access
Allow group NetOps to {LOAD_BALANCER_UPDATE} load-balancers in compartment Production

# Grant specific secret permissions (without granting all "use" permissions)
Allow group AppGroup to {SECRET_INSPECT, SECRET_READ} secrets in compartment Prod

# Creating a secret also requires permission on the vault itself
Allow group SecretCreators to {SECRET_CREATE} secrets in compartment Prod
Allow group SecretCreators to use vaults in compartment Prod

When to use permission sets vs. verbs

Approach Use When
verb (e.g., use) General access for a role — simpler and maintainable
{PERMISSION_SET} Auditor/security requirements demand least-privilege with surgical precision

Note: Some API operations require multiple permissions, and those permissions may span different resource types. For example, CreateSecret needs SECRET_CREATE on secrets and VAULT_CREATE_SECRET on vaults. Always check the service-specific policy reference.


Use Case 2: Condition Grouping (all {} and any {})

Curly braces are used to group multiple conditions when combined with all or any. This is the where clause equivalent of AND / OR logic.

where all { condition1, condition2, ... }   -- ALL must be true (AND)
where any { condition1, condition2, ... }   -- ANY must be true (OR)

Examples

# AND: both conditions must be true
Allow group Contractors to use instances in compartment Dev
  where all {request.region = 'us-ashburn-1', request.utcHours >= 8}

# OR: either condition grants access
Allow dynamic-group AppInstances to read objects in compartment Prod
  where any {target.bucket.name = 'logs-bucket', target.bucket.name = 'config-bucket'}

# Nested: AND of (two OR conditions)
Allow any-user to manage network-family in compartment Network
  where all {
    any {
      request.principal.group.tag.Operations.lifecycle = target.resource.tag.Operations.lifecycle,
      request.principal.group.tag.Operations.lifecycle = target.resource.compartment.tag.Operations.lifecycle
    },
    request.user.domain.name = 'Default'
  }

Dynamic group matching rules also use {} with any/all

Dynamic group membership rules (not policy statements) also use this syntax:

# Instance belongs to dynamic group if it is in EITHER of these compartments
Any {
  instance.compartment.id = 'ocid1.compartment.oc1..aaaaaaaacompartment1',
  instance.compartment.id = 'ocid1.compartment.oc1..aaaaaaaacompartment2'
}

# Instance must be tagged AND in a specific compartment
All {
  instance.compartment.id = 'ocid1.compartment.oc1..aaaaaaaaxxx',
  tag.Operations.Env.value = 'Production'
}

Summary of {} Usage

Context Syntax Meaning
Verb position to {PERM_A, PERM_B} resource-type Grant only these specific atomic permissions
Condition all where all {cond1, cond2} ALL conditions must be true (AND)
Condition any where any {cond1, cond2} ANY condition must be true (OR)
Dynamic group rule Any {rule1, rule2} Membership matches if ANY rule is true

Conditions & Variables

Common request.* variables

Variable Description Example Value
request.region Region of the API call 'us-phoenix-1'
request.ad Availability domain 'US-ASHBURN-AD-1'
request.networkSource.name Named IP allowlist 'CorpNetwork'
request.user.id OCID of the requesting user 'ocid1.user.oc1...'
request.user.domain.name Identity domain name 'Default'
request.utcHours Current UTC hour (0–23) 9
request.utcTimestamp Full UTC timestamp '2025-01-01T09:00:00Z'
request.principal.type Type of principal making the request 'instance', 'service'
request.operation Specific API operation name 'GetObject'
request.permission The permission being requested 'PAR_MANAGE'

Common target.* variables

Variable Description
target.compartment.id OCID of the target compartment
target.compartment.name Name of the target compartment
target.group.name Name of the target group
target.bucket.name Name of an Object Storage bucket
target.resource.tag.<namespace>.<key> A defined tag on the target resource
target.domain.name Identity domain name of target

Condition operators

Operator Meaning
= Equals (case-sensitive)
!= Not equals
=~ Case-insensitive equals
in ('a', 'b') Matches any value in the list
/glob*/ Wildcard/glob pattern match

Condition Examples

# Restrict to a specific region
Allow group PHX-Admins to manage all-resources in tenancy
  where request.region = 'us-phoenix-1'

# Exclude a specific compartment
Allow group NetAdmins to manage virtual-network-family in tenancy
  where target.compartment.id != 'ocid1.compartment.oc1..aaaaaaaaexampleocid'

# Wildcard group name match
Allow group GroupAdmins to manage groups in tenancy
  where target.group.name = /A-Users-*/

# Multiple AND conditions
Allow group GroupAdmins to manage groups in tenancy
  where all {target.group.name = /A-*/, target.group.name != 'A-Admins'}

# Time-based access window (9am–5pm UTC)
Allow group Contractors to use instances in compartment Dev
  where all {request.utcHours >= 9, request.utcHours < 17}

# Specific timestamp range
Allow group AuditTeam to read audit-events in tenancy
  where all {
    request.utcTimestamp > '2025-01-01T00:00:00Z',
    request.utcTimestamp < '2025-12-31T23:59:59Z'
  }

# IP allowlist via network source
Allow group CorpUsers to manage all-resources in tenancy
  where request.networkSource.name = 'CorpNetwork'

# Tag-based access control (ABAC)
Allow group TeamA to manage instances in tenancy
  where target.resource.tag.Operations.Project = 'Alpha'

# Restrict to user's own resources (tag must match group tag)
Allow any-user to manage network-family in compartment Network
  where request.principal.group.tag.Operations.lifecycle = target.resource.tag.Operations.lifecycle

# Restrict to a specific OCI service making the call
Allow any-user to read instances in tenancy
  where request.principal.type = 'vnpa-service'

# Restrict a policy to only apply to one specific user within a group
Allow group groupA to manage compartments in tenancy
  where request.user.id = 'ocid1.user.oc1..aaaaaaxxx'

Cross-Tenancy Policies — Endorse / Admit / Define

Cross-tenancy policies use three special statement keywords instead of Allow. Both tenancies must define matching policies — one side alone grants nothing.

Keyword Where it lives Purpose
Endorse Source tenancy Declares what your group can do in other tenancies
Admit Destination tenancy Grants access to an external group from another tenancy
Define Either tenancy Creates a local alias for an OCID (for readability)

Simple cross-tenancy example

Source tenancy (the group trying to access another tenancy's resources):

Define tenancy DestinationTenancy as ocid1.tenancy.oc1..<unique_ID>
Endorse group StorageAdmins to manage object-family in tenancy DestinationTenancy

Destination tenancy (the tenancy granting access):

Define tenancy SourceTenancy as ocid1.tenancy.oc1..<unique_ID>
Define group StorageAdmins as ocid1.group.oc1..<unique_ID>
Admit group StorageAdmins of tenancy SourceTenancy to manage object-family in tenancy

Cross-tenancy with a dynamic group (instance principals)

Source tenancy:

Define tenancy DestCompanyABC as ocid1.tenancy.oc1..aaaaaaaaabc
Endorse dynamic-group oci_la_dg to manage loganalytics-resources-family in tenancy DestCompanyABC
Endorse dynamic-group oci_la_dg to read compartments in tenancy DestCompanyABC

Destination tenancy:

Define tenancy VendorA as ocid1.tenancy.oc1..aaaaavendora
Define dynamic-group oci_la_dg as ocid1.dynamicgroup.oc1..aaaaaaaavendora
Admit dynamic-group oci_la_dg of tenancy VendorA to manage loganalytics-resources-family in tenancy
Admit dynamic-group oci_la_dg of tenancy VendorA to read compartments in tenancy

Open endorse (any tenancy)

# Source tenancy: allow StorageAdmins to manage objects in ANY tenancy
Endorse group StorageAdmins to manage object-family in any-tenancy

Scoped to a specific compartment

Define tenancy SourceTenancy as ocid1.tenancy.oc1..<unique_ID>
Define group StorageAdmins as ocid1.group.oc1..<unique_ID>
Admit group StorageAdmins of tenancy SourceTenancy to manage object-family in compartment SharedBuckets

Note: Cross-tenancy policies must be attached at the root (tenancy) level on both sides. Both tenancies must also be subscribed to the same regions.


Niche & Advanced Language Features

Groups with spaces in names

Use single quotes around any name containing spaces.

Allow group 'Dev Team', 'Ops Team' to use instances in compartment Production

Referring to a compartment that is not a direct child

Use : as a path separator to traverse the hierarchy.

# Policy attached to tenancy, targeting a deeply nested compartment
Allow group TeamA to manage instances in compartment Root:Project-A:SubTeam

Multiple compartments (requires separate statements)

There is no multi-value syntax for location — write one statement per compartment.

Allow group Developers to manage instance-family in compartment Project-A
Allow group Developers to manage instance-family in compartment Project-B

Referencing everything by OCID

You can replace any name with id <ocid> for robustness against renames.

Allow group id ocid1.group.oc1..aaaaaaaagroupocid to manage instance-family
  in compartment id ocid1.compartment.oc1..aaaaaaaacompartmentocid

any-user vs any-group

  • any-user — covers all users, resource principals, instance principals, and service principals in the tenancy. Use with caution.
  • any-group — covers all users and instance principals, but not service principals.
# Prefer any-group over any-user for least privilege
Allow any-group to inspect all-resources in tenancy

# Carve out a specific service using request.principal.type to safely use any-user
Allow any-user to read instances in tenancy
  where request.principal.type = 'vnpa-service'

Service principals

OCI services can be authorized to act on resources. This is done using any-user with a condition that scopes the principal to the specific service type.

# Authorize the Virtual Network Path Analyzer to read instances
Allow any-user to read instances in tenancy
  where request.principal.type = 'vnpa-service'

# Authorize a Data Integration workspace (disworkspace) to access objects
Allow any-user to manage objects in compartment XYZData
  where all {request.principal.type = 'disworkspace'}

Identity domain-qualified group names

When groups exist in a non-default identity domain, prefix the group with the domain name.

# Group in a named domain
Allow group FederatedDomain/Engineers to manage instances in compartment Dev

# Group in a domain with spaces
Allow group 'My Domain'/'Dev Group' to use buckets in compartment Staging

# Works with Endorse too
Endorse group domainA/xt_db_users to use database-connections in tenancy DestinationTenancy

Restricting access by tag on the requesting principal's group

This is a powerful ABAC (Attribute-Based Access Control) pattern — access is determined by comparing a tag on the requesting group against a tag on the target resource or compartment.

# Users can only manage resources that share their group's lifecycle tag
Allow any-user to manage network-family in compartment Network
  where request.principal.group.tag.Operations.lifecycle = target.resource.tag.Operations.lifecycle

Time-bounded policies

Use UTC timestamps in ISO 8601 format. Allow for a ~5 minute clock skew.

# Allow access only during business hours (UTC)
Allow group Contractors to use instances in compartment Dev
  where all {request.utcHours >= 9, request.utcHours < 17}

# Allow access within a specific date range
Allow group AuditTeam to read audit-events in tenancy
  where all {
    request.utcTimestamp >= '2025-06-01T00:00:00Z',
    request.utcTimestamp <= '2025-06-30T23:59:59Z'
  }

Granular {PERMISSION} sets with conditions combined

You can combine permission sets and conditions in the same statement.

# Allow vault inspection only to users from a specific group tag
Allow any-user to {VAULT_INSPECT, VAULT_READ, VAULT_CREATE_SECRET} in compartment open-vault
  where request.principal.group.tag.users_ts.user_role = 'admin-users'

Policies do not apply to the compartment they are attached to — only to their location clause

A policy attached to compartmentA but with in compartment compartmentB only applies to compartmentB. The attachment determines who can modify the policy, not where it applies.

The inspect verb is sometimes more powerful than expected

For network resources, inspect returns not just metadata but the full contents of security lists, route tables, and VCN configurations — not just names and OCIDs. For policies, inspect returns the full text of all policy statements.

Implicit inspect requirement with conditional manage

When using manage with a condition that targets a named resource (like target.group.name), list operations don't carry the target value, so the condition always evaluates as "not applicable" and denies the list. You must add a separate inspect statement without the condition.

# Without this, GroupAdmins can't list groups to find "A-Users-*" ones
Allow group GroupAdmins to manage groups in tenancy
  where target.group.name = /A-Users-*/
Allow group GroupAdmins to inspect groups in tenancy   -- Required!

Common Policy Recipes

Full compartment admin

Allow group ProjectA-Admins to manage all-resources in compartment Project-A

Auditor (read-only across tenancy)

Allow group Auditors to inspect all-resources in tenancy
Allow group Auditors to read instances in tenancy
Allow group Auditors to read audit-events in tenancy

Help desk (manage users only)

Allow group HelpDesk to manage users in tenancy
Allow group HelpDesk to manage groups in tenancy

Network administrator

Allow group NetAdmins to manage virtual-network-family in tenancy

Object Storage — full admin

Allow group StorageAdmins to manage buckets in tenancy
Allow group StorageAdmins to manage objects in tenancy

Launch compute instances (requires network + storage access too)

Allow group Developers to manage instance-family in compartment Dev
Allow group Developers to use volume-family in compartment Dev
Allow group Developers to use virtual-network-family in compartment Dev

Dynamic group — instance reads its own compartment's secrets

Allow dynamic-group AppServers to read secret-family in compartment Production

Write-only bucket access (e.g. log shipping)

Allow group LogShippers to inspect buckets in compartment Logging
Allow group LogShippers to manage objects in compartment Logging
  where all {
    target.bucket.name = 'app-logs',
    any {request.permission = 'OBJECT_CREATE', request.permission = 'OBJECT_INSPECT'}
  }

Key Rules & Gotchas

  • Policies always start with Allow (or Endorse/Admit/Define for cross-tenancy). There is no explicit Deny.
  • Implicit deny: if no policy grants access, access is denied.
  • A policy can only be attached to one compartment. Attachment determines who can edit/delete the policy.
  • Changes take effect within ~10 seconds in the home region, but can take several minutes to replicate across all regions.
  • The built-in Administrators group policy cannot be changed or deleted.
  • Users can always change their own password and API signing keys without any policy.
  • When referencing IAM resources (users, groups, policies), use tenancy as the location.
  • Policy names must be unique within a compartment and are immutable after creation.
  • Deleting and recreating a policy with the same name produces a different OCID — they are treated as different policies.
  • Policies attached to a parent compartment apply to all child compartments via inheritance. There is no way to block inheritance.
  • any-user includes service and resource principals — prefer any-group or scope with request.principal.type conditions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment