Home / OCI

OCIChecklistBeginner

Offboarding a user from OCI: a checklist for console access, API keys, tokens and owned resources

When an engineer leaves or changes team, remove their OCI access in the right order, revoke every credential type, and find the resources and automation that still depend on them.

Deepak Bhardwaj8 min read

Applies toOCI IAM with identity domains, Default domain users, federated users (Entra ID, Okta), OCI CLI 3.x

Goal

An engineer leaves the company or moves to a team that shouldn't have production access. You need to make sure they can't sign in to the Console, call the API, push images, send mail through Email Delivery or read Object Storage with old keys. You also need to make sure nothing breaks because a pipeline was quietly running under their personal API key.

Disabling the console login on its own isn't enough. API keys, auth tokens and customer secret keys are separate credentials and keep working until you delete them.

Work through the sections in order. Record each step in the ticket.

1. Before you remove anything: find what depends on the user

Do this first, while the user still exists. If you delete keys first, any automation using them fails in production and you'll be debugging it under pressure.

T=ocid1.tenancy.oc1..xxxx   # tenancy OCID (root compartment)
USER_NAME="jane.doe@contoso.com"

USER_ID=$(oci iam user list --compartment-id $T --all \
  --query "data[?name=='$USER_NAME'].id | [0]" --raw-output)
echo $USER_ID

Tip

oci iam user list returns users in the Default identity domain. For users in other domains, find them in the Console under Identity & Security → Domains → → Users. Federated users may show up with a prefix on the name, depending on how the federation is set up.

List each credential and check when it was last used:

oci iam user api-key list --user-id $USER_ID \
  --query 'data[].{fingerprint:fingerprint,created:"time-created",state:"lifecycle-state"}' --output table
oci iam auth-token list --user-id $USER_ID --output table
oci iam customer-secret-key list --user-id $USER_ID --output table
oci iam smtp-credential list --user-id $USER_ID --output table

Then use Audit to see what those credentials did recently. For example, these are calls made by the user in the last 7 days, excluding Console sessions:

oci audit event list --compartment-id $T --all \
  --start-time $(date -u -d '-7 days' +%FT%TZ) --end-time $(date -u +%FT%TZ) \
  --query "data[?data.identity.\"principal-name\"=='$USER_NAME'].{time:\"event-time\",event:\"event-type\",ip:data.identity.\"ip-address\",agent:data.identity.\"user-agent\"}" \
  --output table

Audit queries cover one compartment at a time. Repeat this for the compartments that matter, or search the _Audit log group in Logging Search across compartments.

What Audit shows Likely dependency Action
Regular API calls from a build server IP, user-agent with Terraform or an SDK A pipeline using the user's API key Move it to a service user or an instance/resource principal before revoking the key
docker or registry calls Image pushes and pulls with the user's auth token Create a token on a service user and update the CI secret or OKE image pull secret
S3-compatible API calls Backup tools or scripts using a customer secret key Issue a new key on a service user and update the tool
Email Delivery SMTP sends An application sending mail with the user's SMTP credentials Move it to a dedicated SMTP user
Console activity only No hidden automation Continue

Find resources the user created. OCI tag defaults usually put the creator in Oracle-Tags.CreatedBy, so search on that:

oci search resource structured-search --query-text \
  "query all resources where (definedTags.namespace = 'Oracle-Tags' && definedTags.key = 'CreatedBy' && definedTags.value = '$USER_NAME')" \
  --query 'data.items[].{type:"resource-type",name:"display-name",compartment:"compartment-id"}' --output table

The value format depends on your tenancy and domain. It may include the domain name, for example default/jane.doe@contoso.com. Look at one tagged resource to check the format first. Resources aren't deleted when their creator leaves, but you should assign an owner to each one.

2. Block sign-in

Do this first so no new Console session or federated sign-in can start.

  • Federated users (Entra ID, Okta and so on): disable the account in the identity provider. If SCIM provisioning is set up, the change syncs to the OCI identity domain. Check that the user shows as Deactivated in the domain.
  • Local identity domain users: in the Console, open the domain → Users → select the user → Deactivate. A deactivated user can't sign in and you can still reactivate the account if HR reverses the decision.
  • Active sessions: deactivation stops new sign-ins. For a hostile departure, also end their sessions in the domain if your domain version offers it, and rotate any break-glass passwords they knew.

Warning

oci iam user update-user-state --blocked only supports false (unblocking a user). You can't use it to block someone. Use deactivation in the identity domain, or the identity provider for federated users.

3. Revoke every credential

Deactivating the user doesn't revoke API signing keys and tokens. Delete each type explicitly once dependencies from step 1 have moved.

# API signing keys
for FP in $(oci iam user api-key list --user-id $USER_ID --query 'data[].fingerprint' --raw-output | tr -d '[]",'); do
  oci iam user api-key delete --user-id $USER_ID --fingerprint $FP --force
done

# Auth tokens (OCIR, Streaming Kafka, some integrations)
for ID in $(oci iam auth-token list --user-id $USER_ID --query 'data[].id' --raw-output | tr -d '[]",'); do
  oci iam auth-token delete --user-id $USER_ID --auth-token-id $ID --force
done

# Customer secret keys (S3-compatible API)
for ID in $(oci iam customer-secret-key list --user-id $USER_ID --query 'data[].id' --raw-output | tr -d '[]",'); do
  oci iam customer-secret-key delete --user-id $USER_ID --customer-secret-key-id $ID --force
done
  • API signing keys deleted
  • Auth tokens deleted
  • Customer secret keys deleted
  • SMTP credentials deleted (Console: user → SMTP credentials)
  • OAuth 2.0 client credentials and database passwords removed (Console: user → the matching credential pages, if your domain has them)
  • Run the list commands again and confirm each one returns nothing

4. Remove group memberships

Policies are attached to groups, so removing the user from groups is what takes away their permissions. Do this even after deactivation, because the account might be reactivated by mistake.

oci iam user list-groups --user-id $USER_ID --compartment-id $T \
  --query 'data[].{name:name,id:id}' --output table

for GID in $(oci iam user list-groups --user-id $USER_ID --compartment-id $T --query 'data[].id' --raw-output | tr -d '[]",'); do
  oci iam group remove-user --group-id $GID --user-id $USER_ID --force
done
  • Removed from all groups, including the Administrators group
  • No policy names the user directly. Policies normally reference groups, but check where request.user.id = ... conditions:
oci iam policy list --compartment-id $T --all \
  --query "data[?contains(join(' ', statements), '$USER_ID')].name"

Run this in child compartments too if policies are spread across them.

  • Removed from dynamic group rules or tag-based conditions that use their name or OCID

5. Shared secrets and access outside IAM

OCI IAM doesn't cover everything the person could access:

  • Pre-authenticated requests they created on Object Storage buckets. List PARs on sensitive buckets with oci os preauth-request list --bucket-name <bucket> and delete any you can't account for.
  • SSH keys they added to instances (~/.ssh/authorized_keys), and Bastion sessions still open under their name.
  • Database accounts: local users in Autonomous Database, Base Database or MySQL HeatWave. Lock them or drop them.
  • Vault secrets they knew the value of, such as application passwords or break-glass credentials. Rotate them.
  • Notification subscriptions using their personal email or phone number. Replace them with team endpoints.
  • Kubeconfig files for OKE. These use the user's OCI credentials, so they stop working once the keys are revoked. Check that cluster RBAC bindings don't name their user OCID directly.

6. Verify and close

  • Audit for the next 24 to 48 hours shows no successful calls as the user. Failed NotAuthenticated calls point to automation you missed. Trace them by source IP.
  • Pipelines and scheduled jobs that you moved in step 1 have run successfully under their new identity.
  • Owned resources have a new owner recorded in a tag such as Operations.Owner.
  • Delete the user once your retention policy allows it. Many teams keep the deactivated account for 30 to 90 days for investigations.

Prevent it next time

  • Don't let automation run as a person. Use instance principals, resource principals, OKE workload identity, or a dedicated service user whose keys sit in a vault.
  • Federate with your corporate identity provider and use SCIM provisioning. A disable in HR then flows through to OCI on its own.
  • Run a monthly report of API keys and auth tokens older than your rotation period, and of the users who own them.
  • Keep this checklist in the leaver process so it's triggered by HR, not by someone remembering.