The goal
A new teammate can log in to OCI but can't see anything. That's by design: in OCI, everything is denied until a policy allows it. Here you'll give someone access to one compartment, and no more.
You need admin rights for this. Find your tenancy OCID in ~/.oci/config, or in the console under your profile.
export T=ocid1.tenancy.oc1..your-tenancy-id
The parts
| Part | Purpose |
|---|---|
| User | A person or service account |
| Group | A set of users. Policies grant access to groups |
| Compartment | A logical container for resources |
| Policy | Statements saying which group can do what, and where |
Allow group <group> to <verb> <resource-type> in compartment <compartment>
That reads almost like a sentence, which makes policies easy to review.
Step 1: create a compartment
COMP=$(oci iam compartment create \
--compartment-id "$T" \
--name lab \
--description "Lab resources for training" \
--wait-for-state ACTIVE \
--query 'data.id' --raw-output)
echo "$COMP"
IAM changes are made in your home region. If you get a region error, add --region with your home region's name. See compartments and OCIDs for more.
Step 2: create a group and add a user
GROUP=$(oci iam group create \
--name lab-users \
--description "People who work in the lab compartment" \
--query 'data.id' --raw-output)
oci iam user list --compartment-id "$T" --all \
--query 'data[].{name:name, id:id}' --output table
oci iam group add-user --group-id "$GROUP" --user-id ocid1.user.oc1..teammate-id
Tip
In tenancies with identity domains, these
oci iam userandoci iam groupcommands work with the Default domain. Other domains are managed in the console, or withoci identity-domains. If your users don't appear, this is probably why. Your policy then names the group as'DomainName'/'lab-users'.
Step 3: pick the right verb
Policies use four verbs, each including the one before it:
| Verb | Allows | Typical person |
|---|---|---|
inspect | List resources, with limited metadata | Auditor |
read | inspect, plus get details and contents | Support engineer |
use | read, plus work with existing resources | Operator |
manage | Everything, including create and delete | Owner |
And these are the resource types you'll use most:
| Resource type | Covers |
|---|---|
instance-family | Compute instances, images and more |
virtual-network-family | VCNs, subnets, gateways |
volume-family | Block and boot volumes |
object-family | Buckets and objects |
all-resources | Everything. Use with care |
Step 4: write the policy
Start with read access to everything in the compartment, and add write access only for what the team runs:
oci iam policy create \
--compartment-id "$T" \
--name lab-users-policy \
--description "Access for the lab-users group" \
--statements '[
"Allow group lab-users to read all-resources in compartment lab",
"Allow group lab-users to manage instance-family in compartment lab",
"Allow group lab-users to manage volume-family in compartment lab",
"Allow group lab-users to use virtual-network-family in compartment lab"
]'
Where you attach the policy matters. It must sit in the compartment it names, or in a parent. Here, it's attached at the tenancy root, so it can name lab.
To launch an instance, a person needs more than instance-family: they also need to use the network and volumes. That's a common surprise, and it's why there are multiple statements above. The policy cheat sheet has more examples.
Warning
Avoid
Allow group x to manage all-resources in tenancy. It's effectively full admin. Grant at compartment level, and keep tenancy-wide admin to a small, named group with MFA.
Step 5: test it
Have your teammate run these using their own profile. You can't simulate a policy from your side.
oci iam compartment list --compartment-id "$T" --query 'data[].name'
oci compute instance list --compartment-id "$COMP"
oci network vcn list --compartment-id "$COMP"
They should also see an error when trying a compartment that they haven't been given.
When access fails
OCI returns the same error when something doesn't exist and when you can't access it. That's a deliberate choice:
NotAuthorizedOrNotFound: Authorization failed or requested resource not found.
Work through this list:
| Check | How |
|---|---|
| Is the OCID right, and in this region? | Check the compartment and --region |
| Is the user really in the group? | List the group's members (command below) |
| Does a statement cover this action? | Read the policy |
| Is the verb strong enough? | use can't create, for example |
| Is the policy at the right level? | It must be in that compartment or a parent |
| Is the group name correct, with the domain? | Non-default domains need 'Domain'/'group' |
List members and policies:
oci iam group list-users --group-id "$GROUP" --compartment-id "$T" --query 'data[].name'
oci iam policy list --compartment-id "$T" --all \
--query 'data[].{name:name, statements:statements}'
Note that policies in child compartments won't appear when you list the root. Search those too. Find out who changed what in the audit logs.
Limit access further with conditions
You can narrow a statement with a where clause:
Allow group lab-users to manage instance-family in compartment lab where request.operation != 'TerminateInstance'
Conditions are powerful but easy to get wrong. Test them carefully. See policy conditions and tags when you're ready.
Applications shouldn't use user keys
Scripts on an instance don't need a user's API key. Use an instance principal, which gives the instance its own identity through a dynamic group. See workload identity.
Clean up
oci iam policy delete --policy-id <policy-ocid> --force
oci iam group remove-user --group-id "$GROUP" --user-id ocid1.user.oc1..teammate-id
oci iam group delete --group-id "$GROUP" --force
oci iam compartment delete --compartment-id "$COMP" --force
A compartment can only be deleted when it's empty. If it won't go, see compartment won't delete.
Caution
Deleting a policy takes access away from everyone who relied on it, and there's no undo. Copy the statements first. If you've already removed one, see deleted policy recovery.
Prevent it next time
- Grant to groups, never one person at a time.
- Keep policies short, with one owner each, and store them as code.
- Use a separate compartment for each environment, and see the landing zone guide.
- Review who is in your admin groups every quarter.