DEV Community

Cover image for An Overview to OCI IAM Policies
Faris Durrani
Faris Durrani

Posted on

An Overview to OCI IAM Policies

An overview to Oracle Cloud's Identity Access and Management policies–syntax and usage

Oracle Cloud's IAM policies allow you granular control over who can access and manage resources in the cloud, using groups of users and resources to efficiently manage access security inside a complex online environment.

⚡️ Quick guide: resource policies

In general, the policies for most resources can be found here under Detailed Service Policy Reference.

Details for API Gateway

Not all resources are here. For example, Nosql, OSMH, OSMS, db-backups, databases, WAF... are not included and you'll have to find them manually.

💠 The syntax

See the following default policy that comes with every tenancy:

allow group Administrators to manage all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

As can be seen in the example before, all simple* OCI policies follow the non-case-sensitive pattern:

🔹 For OCI user accounts:

allow group <domain>/<group name> to <verb> <resource> in <compartment>
Enter fullscreen mode Exit fullscreen mode

🔹 For instance and resource principals:

allow dynamic-group <domain>/<dynamic group name> to <verb> <resource> in <location> [where <condition>]
Enter fullscreen mode Exit fullscreen mode

*There are some complex exceptions to replace Allow with Endorse, Admit, and Define, but we won't get into that here. There is no Deny in OCI policies.

Briefly explaining the components before we get deeper:

General policy components

Section Meaning
group type The type of IAM principal set this policy applies to--either group for OCI user accounts or dynamic-group for OCI resources
domain The IAM Domain of the group. If you're in the Default domain (most of the case), the name of the domain can be cimply left out
group name The name (or ID) of the group, e.g., Group-A
verb The level of control of the resource, e.g., manage, {INSTANCE_LAUNCH}
resource The type of resource, e.g., instances, virtual-network-family
Location The name (or ID) of the compartment where the policy applies
conditions The conditions this policy applies in, if any

Now let's dive more into each component:

1️⃣ Group Type

🔹 Simple user groups

Looking at the default administrator policy, we have:

allow group Administrators to manage all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

This is the simplest policy you have, with the group type group signifying that the group this policy applies to is a regular OCI users group. In this case, the tenancy administrators.

🔹 Multiple user groups

We can make additional groups such as Group A and Group B in the default identity domain and assign policies to those groups, individually or in combination:

allow group 'Group A', 'Group B' to inspect all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

Note that the quotes '' are needed here since there is a space in the group name. Both groups must be of the same type 'group' for this concise statement to work.

🔹 All users and service

To have your policy only be applied to any users and OCI services, use any-user or any-group:

allow any-user to inspect compartments in tenancy
Enter fullscreen mode Exit fullscreen mode

I find the below list to be helpful as a baseline when providing general necessary read access for all users to function:

allow any-user to inspect tenancies in tenancy
allow any-user to inspect compartments in tenancy
allow any-user to inspect instances in tenancy where request.operation = 'ListShapes'
allow any-user to read announcements in tenancy
allow any-user to read app-catalog-listing in tenancy
allow any-user to read tag-namespaces in tenancy
allow any-user to read objectstorage-namespaces in tenancy
allow any-user to use cloud-shell in tenancy
allow any-user to use cloud-shell-public-network in tenancy
allow any-user to manage objectstorage-namespaces in tenancy where any { request.operation='GetNamespace', request.operation='GetNamespaceMetadata' }
Enter fullscreen mode Exit fullscreen mode

🔹 Resource and Instance Principals

If the policy is meant to apply to an OCI resource or instance principals--like a group of instances--you will use dynamic-group instead:

allow dynamic-group compt1-instances to inspect all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

This is similar to AWS EC2 roles, which only work for internal resources. This is more secure than creating an OCI user account that may be accessed externally.

🔹 Group IDs instead of names

Instead of names, we can also use group OCIDs instead:

allow group id 'ocid1.group.oc1..aaaaaagfnrkyzjuwvrgjjirxmhgurao', 'ocid1.group.oc1..aaaaaagfnrkyzjuwvrgjjirxmhgurap' to inspect all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode
allow dynamic-group id 'ocid1.dynamicgroup.oc1..aaaaaagfnrkyzjuwvrgjjirxmhgurao', 'ocid1.dynamicgroup.oc1..aaaaaagfnrkyzjuwvrgjjirxmhgurap' to inspect all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

🔹 Services

The policy can also allow a specific internal OCI resource to access other OCI resources. For example,

allow service cloudguard to read virtual-network-family in tenancy
Enter fullscreen mode Exit fullscreen mode

allows the Cloud Guard resource to read your networking resources to identify misconfiguration.

Following a default-deny paradigm, no OCI service has access to manage any other OCI services, including the ones storing customer data.

Some services don't use the group type service but instead use the more general any-user type with exceptions carved out to identify the service.

This policy for example, allows the Virtual Network Path Analyzer service to read your VM instances:

allow any-user to read instances in tenancy where ALL { request.principal.type = 'vnpa-service' }
Enter fullscreen mode Exit fullscreen mode

2️⃣ Domain

If the group is not in the Default domain, you will have to specify the domain. Again, quotes are necessary if there is a space in the domain name:

allow group FederatedDomain/'Group A', FederatedDomain/'Group B' to inspect all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

3️⃣ Group name

Explained above.


4️⃣ Verb

Let us start with Verbs.

A Verb can either be, in decreasing order of privilege:

Verb General function
manage Full access to resource
use Allows to update the resource, but not create or delete
read Get detailed information on a resource
inspect List a collection of resources without detailed information

Policy access hierarchy


🔹 Simple Example

If you want to allow a group to update the details of a WAF like changing its name, but not delete anything, you would write the following policy:

allow group GroupA to use web-app-firewall in compartment compartmentA
Enter fullscreen mode Exit fullscreen mode

🔹 Granular Permissions

To discuss the Verb component, we first have to understand the difference between Verbs and Permissions.

A Verb represents a collection of policy Permissions. These permissions are spelled in UPPER_CASE and represent the granular policy permission that form the building blocks of the Verb.

In this example below involving the load-balancers resource, we see that inspect represents the LOAD_BALANCER_INSPECT permission only. And use represents the combination of LOAD_BALANCER_INSPECT + LOAD_BALANCER_READ + LOAD_BALANCER_UPDATE + LOAD_BALANCER_MOVE.

load-balances policy verbs


We can write the policy statement using either the more general Verb or the more specific Permission, e.g., to allow the user to update load balancer details:

allow group groupA to use load-balancers in compartment compA
Enter fullscreen mode Exit fullscreen mode
allow group groupA to {LOAD_BALANCER_UPDATE} load-balancers in compartment compA
Enter fullscreen mode Exit fullscreen mode

🔹 Verbs vs Permissions vs APIs

Diving deeper, we introduce another term within this component: API. An example is CreateSecret. Spelled in PascalCase.

The API is simply the name of the specific API call that performs the operation in the Oracle Cloud tenancy when you click on a button in the console UI, in a CLI command, or some other API calling method.

🔶 For example:

  1. Listing the vault secrets in a compartment ➡️ ListSecrets (Doc)
  2. Creating a new vault secret ➡️ CreateSecret (Doc).

To perform an API call, you need to be granted specific granular Permissions, which must be specified directly in the policy statement (e.g., SECRET_INSPECT) or using a Verb which contains the needed granular Permissions (e.g., inspect secrets).

We see below from the Details for Vault, Key Management, and Secrets page on the relationship between Verbs, Permissions, and APIs.

Relationship between policy verbs, permissions, operations

🔶 We notice:

  1. Verbs are a collection of Permissions
  2. Permissions allow you to call specific APIs
  3. At times, you need to be granted multiple Permissions to call some APIs, like how both SECRET_UPDATE and SECRET_MOVE is needed for the ChangeSecretCompartment API call
  4. At times, you need multiple Permissions of different resources to call some APIs, like how CreateSecret need the permissions SECRET_CREATE and use vaults (specifically, VAULT_CREATE_SECRET).

We see the original page of the Details for Vault, Key Management, and Secrets describing the relationship below:

Secrets policy verbs

I recommend using Permissions for granular permissions and the verbs inspect, read, use, manage for more general permissions (easier). Operations should be reserved since they relate more to the actual API function names.

🔶 For example, these four policies are approximately similar:

Details for logging
Details for Logging

allow group logAdmins to inspect log-groups in compartment comptA

allow group logAdmins to manage all-resources in compartment comptA where all { request.permission = /LOG_GROUP_*/, request.operation = /List*/ }

allow group logAdmins to manage all-resources in compartment comptA where all { request.permission = 'LOG_GROUP_INSPECT' }

allow group logAdmins to manage all-resources in compartment comptA where any { request.operation = 'ListLogGroups', request.operation = 'ListLogs' }
Enter fullscreen mode Exit fullscreen mode

5️⃣ Resource

The resource name can refer to either:

  • an aggregate resource type (e.g., instance-family)
  • an individual resource type (e.g., instances)

The aggregate resource type covers multiple individual resource types like the instance example below:

instance-family components

Source: Details for the Core Services


6️⃣ Location

The final mandatory part of an OCI policy determines in which compartment the policy applies to.

OCI policies cascade in the compartments they are declared for. If a policy is declared for a compartment, that compartment and all its descendant children compartments are included.

🔹 tenancy (all compartments)

This policy allows the administrators to manage all resources in the tenancy, i.e., the root compartment and all its descendant compartments:

allow group Administrators to manage all-resources in tenancy
Enter fullscreen mode Exit fullscreen mode

🔹 current compartment and its children

If you are declaring a policy in compartment compA and want the policy to also affect compartment compA, you would write the policy to affect compartment compA:

allow group groupA to manage load-balancers in compartment compA
Enter fullscreen mode Exit fullscreen mode

🔹 current compartment's children

If you are declaring a policy in compartment compA and want the policy to only affect one of compA's children (call it compB) and its descendants, but not compA itself, you would write the policy to affect compartment compB:

allow group groupA to manage load-balancers in compartment compB
Enter fullscreen mode Exit fullscreen mode

Affecting children compartment

🔹 nested compartment

Say the compartment hierarchy goes like this: root > compA > compB > compC > compD.

You are declaring a policy in compartment compA and want the policy to only affect compC and all its descendants. To accomplish this, you would use the colon : to specify the final compartment name:

allow group groupA to manage load-balancers in compartment compB:compC:compD
Enter fullscreen mode Exit fullscreen mode

Nested compartment applied to

🔹 compartment ID

And finally, you can declare the compartment OCID in lieu of a compartment name. This also has the added benefit of not having to nest the compartment hierarchy as above:

allow group groupA to manage load-balancers in compartment id ocid1.compartment.oc1..aaaaaxxxxxxx
Enter fullscreen mode Exit fullscreen mode

7️⃣ Conditions

Last, you can add restrictions and conditions to your policies to restrict when it applies.

🔹 Simple example

For a simple example, this policy allows the group to read everything in the tenancy but not secret contents in the vaults:

allow group groupA to read all-resources in tenancy where request.permission != 'SECRET_BUNDLE_READ'
Enter fullscreen mode Exit fullscreen mode

Accessible resources except secrets

🔹 Multiple conditions

You can use any and all to combine different conditions to create flexible policies:

allow any-user to read all-resources in tenancy where all { request.principal.group.tag.user_ts.user_role='auditors', request.permission != 'SECRET_BUNDLE_READ' }

allow group groupA to manage all-resources in compA where any {target.compartment.name='compB', target.compartment.name='compC'}

allow group comptA-admins to manage all-resources in compartment comptA where all { request.region = 'IAD', request.operation != 'CreateVault', request.permission != /POLICY*/, any { request.operation = /Create*/, request.operation = /Update*/, request.operation = /List*/, request.operation = /Get*/} }
Enter fullscreen mode Exit fullscreen mode

any vs all

🔹 Patterns

If not a strict string, you can use patterns like /hr*/ to create general conditions. See Policy Syntax

Allow group GroupAdmins to manage groups in tenancy where all {target.group.name=/A-*/, target.group.name!='A-Admins'}
Enter fullscreen mode Exit fullscreen mode

Some exception variables are general and apply to all policies. See here for general variable for policies.

General variables page

We can give some examples here:

🔹 tags

This policy allows Group A to manage all resources in a compartment that has the defined tag 'TagNamespaceA.editable = yes'. See Tags and Tag Namespace Concepts.

allow group 'FederatedDomain'/'Group A' to read all-resources in compartment compartmentA where all target.resource.tag.TagNamespaceA.editable = 'yes'
Enter fullscreen mode Exit fullscreen mode

Special notes about tags

To allow others to add or remove tags on a specific resource, simply allow them to use the resource:

allow group groupA to use instances in compartment comptA
Enter fullscreen mode Exit fullscreen mode

To allow others to add or delete tags to the tag namespace, use this policy:

allow any-user to use tag-namespaces in tenancy where target.tag-namespace.name='new-tag-namespace'
Enter fullscreen mode Exit fullscreen mode

🔹 compartment

Using the compartment ID or name, the user can restrict the policy to only apply to resources in a specific compartment. While you can do that using the location variable as stated above, this allows you to further restrict the policy to only one compartment rather than including its descendants. See Details for IAM with Identity Domains.

allow group groupA to manage all-resources in compA where target.compartment.name = 'compB'
Enter fullscreen mode Exit fullscreen mode
allow group groupA to {API_GATEWAY_READ} in compA where target.compartment.id = 'ocid1.compartment.oc1..ihyqrpbgzfhfrpggjqadirfcaihyqrpbgzfhfrpggjqadirfca'
Enter fullscreen mode Exit fullscreen mode

🔹 region

If your tenancy has been subscribed to multiple regions but you only want to restrict your users to only certain regions, use request.region:

allow dynamic-group 'Federated'/'dgrpA' to {VAULT_INSPECT, VAULT_READ} in compartment compB where request.region = 'iad'
Enter fullscreen mode Exit fullscreen mode

Reminder: iad is the airport code for Washington Dulles Airport, which is the short form for the Ashburn Eastern US region in OCI

🔹 network source IP

Here, you restrict who is granted permission within that policy through their origin IP address. Create a network source containing a list of whitelisted IP addresses and specify the policy to only allow for that network source.

See Allowing Access to Resources from Only Specified IP Addresses.

allow group CorporateUsers to manage object-family in tenancy where request.networkSource.name='corpnet'
Enter fullscreen mode Exit fullscreen mode

🔹 user

While it is recommended to apply a policy by the group rather than the individual user, you can restrict the policy by the requesting user ID:

allow group groupA to manage compartments where request.user.id = 'ocid1.user.oc1..aaaaaaxxx'
Enter fullscreen mode Exit fullscreen mode

🔹 group tag

Restrict who this policy applies to by the tag of their group.

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'
Enter fullscreen mode Exit fullscreen mode

Some resources allow you to further restrict policies using a relevant resource specifier. For example,

🔹 bucket / object name

Specific to the Object Storage OCI resource, you can craft policies that only allow the group to access a certain groups of bucket and objects according to their names (Policy Builder Policy Templates):

allow group test-group to manage objects in tenancy where target.bucket.name = 'test-bucket'
Enter fullscreen mode Exit fullscreen mode
allow group test-group to manage objects in tenancy where target.object.name = 'prod/*'
Enter fullscreen mode Exit fullscreen mode

Bucket/object access restrictions

You can also use the tags on the buckets—though we have previously discussed how to use tags in policies generally:

Allow group ObjectWriters to read buckets in compartment ABC
Allow group ObjectWriters to manage objects in compartment ABC where target.bucket.tag.MyTagNamespace.TagKey='MyTagValue'
Enter fullscreen mode Exit fullscreen mode

🔹 vault secret name

Specific to the Vault & Key Management Services resource, we can use target.secret.name to narrow down the specific secret name the user will have access to (Details for Vault, Key Management, and Secrets):

allow group SpecialSecretReaders to read secret-bundles in compA where target.secret.name = 'secret001'
Enter fullscreen mode Exit fullscreen mode

KMS Exception Variables

Note: the resources secrets and secret-bundles represent two different things. The first allows you to read the metadata of the secret object, while the second allows you to decrypt and read the contents.


References

  1. Oracle – Policy Syntax
  2. Details for IAM with Identity Domains
  3. Policy Builder Policy Templates

Safe harbor statement

The information provided on this channel/article/story is solely intended for informational purposes and cannot be used as a part of any contractual agreement. The content does not guarantee the delivery of any material, code, or functionality, and should not be the sole basis for making purchasing decisions. The postings on this site are my own and do not necessarily reflect the views or work of Oracle or Mythics, LLC.

This work is licensed under a Creative Commons Attribution 4.0 International License.

Top comments (0)