Claude-code-plugins-plus-skills oraclecloud-security-basics
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/oraclecloud-pack/skills/oraclecloud-security-basics" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-oraclecloud-security-basics && rm -rf "$T"
plugins/saas-packs/oraclecloud-pack/skills/oraclecloud-security-basics/SKILL.mdOracle Cloud Security Basics
Overview
OCI IAM policy syntax (
Allow group X to manage Y in compartment Z) is the number one enterprise complaint. One wrong policy locks you out of your own resources. One missing verb and your automation silently fails with a 404 NotAuthorizedOrNotFound that looks like a missing resource. This skill is the IAM policy cheat sheet with tested patterns for common access scenarios.
Purpose: Write correct IAM policies, manage API keys securely, and understand the OCI permission model.
Prerequisites
- OCI Python SDK —
pip install oci - OCI config file at
with valid credentials (user, fingerprint, tenancy, region, key_file)~/.oci/config - Tenancy administrator access (to create policies) or membership in a group with
permissionmanage policies - Python 3.8+
Instructions
Step 1: Understand the Policy Verb Hierarchy
OCI uses four verbs in ascending order of privilege. Each higher verb includes all lower verbs:
| Verb | Capabilities | Typical Use Case |
|---|---|---|
| List resources, get metadata only | Auditors, read-only dashboards |
| Inspect + get full resource details/contents | Monitoring tools, reporting |
| Read + act on existing resources (start/stop, attach) | Developers, operators |
| Use + create, delete, move resources | Admins, automation service accounts |
Critical:
use does NOT include create or delete. This trips up every new OCI team.
Step 2: IAM Policy Syntax
Every OCI policy statement follows this exact structure:
Allow <subject> to <verb> <resource-type> in <location> [where <conditions>]
Subject types:
— IAM user groupgroup <group-name>
— resource principals (instances, functions)dynamic-group <dg-name>
— every authenticated user (use with extreme caution)any-user
Location types:
— entire tenancy (root-level policy only)tenancy
— specific compartmentcompartment <name>
— by OCID (for automation)compartment id <ocid>
Step 3: Common Policy Patterns
Copy these tested patterns directly. Replace group names and compartment names with your values:
import oci config = oci.config.from_file("~/.oci/config") identity = oci.identity.IdentityClient(config) # Create a policy with multiple statements tenancy_id = config["tenancy"] # --- Pattern 1: Full admin for a compartment --- admin_policy = identity.create_policy( oci.identity.models.CreatePolicyDetails( compartment_id=tenancy_id, name="compartment-admins", description="Full admin access to the dev compartment", statements=[ "Allow group DevAdmins to manage all-resources in compartment dev" ] ) ) # --- Pattern 2: Read-only access (auditors) --- readonly_policy = identity.create_policy( oci.identity.models.CreatePolicyDetails( compartment_id=tenancy_id, name="auditor-readonly", description="Read-only access for auditors", statements=[ "Allow group Auditors to read all-resources in compartment prod" ] ) ) # --- Pattern 3: Compute-only operators --- compute_policy = identity.create_policy( oci.identity.models.CreatePolicyDetails( compartment_id=tenancy_id, name="compute-operators", description="Manage compute, read networking", statements=[ "Allow group ComputeOps to manage instance-family in compartment prod", "Allow group ComputeOps to use virtual-network-family in compartment prod", "Allow group ComputeOps to read volume-family in compartment prod" ] ) ) # --- Pattern 4: Network admins --- network_policy = identity.create_policy( oci.identity.models.CreatePolicyDetails( compartment_id=tenancy_id, name="network-admins", description="Network management only", statements=[ "Allow group NetAdmins to manage virtual-network-family in compartment prod", "Allow group NetAdmins to manage load-balancers in compartment prod", "Allow group NetAdmins to read instance-family in compartment prod" ] ) ) # --- Pattern 5: Restrict deletes (protect production) --- no_delete_policy = identity.create_policy( oci.identity.models.CreatePolicyDetails( compartment_id=tenancy_id, name="no-delete-prod", description="Allow manage but block deletes in production", statements=[ "Allow group DevOps to manage all-resources in compartment prod where request.permission != 'INSTANCE_DELETE'", "Allow group DevOps to manage all-resources in compartment prod where request.permission != 'BUCKET_DELETE'" ] ) ) print("Policies created successfully")
Step 4: Key Resource Family Types
Policies use resource families, not individual resource types:
| Resource Family | Includes |
|---|---|
| Everything (use sparingly) |
| Instances, instance configurations, instance pools |
| Block volumes, volume backups, volume groups |
| VCNs, subnets, route tables, security lists, NSGs |
| Buckets, objects, pre-authenticated requests |
| DB systems, autonomous databases, backups |
| Load balancers, backend sets, listeners |
| Functions, applications, invocations |
| OKE clusters, node pools |
Step 5: API Key Management
Generate and upload API keys for secure programmatic access:
# Generate a 2048-bit RSA key pair mkdir -p ~/.oci openssl genrsa -out ~/.oci/oci_api_key.pem 2048 chmod 600 ~/.oci/oci_api_key.pem # Extract the public key (upload this to OCI Console) openssl rsa -pubout -in ~/.oci/oci_api_key.pem -out ~/.oci/oci_api_key_public.pem # Get the key fingerprint (needed for ~/.oci/config) openssl rsa -pubout -outform DER -in ~/.oci/oci_api_key.pem | openssl md5 -c
Upload the public key in OCI Console: Identity > Users > Your User > API Keys > Add API Key.
Step 6: Configure ~/.oci/config
[DEFAULT] user=ocid1.user.oc1..exampleuniqueID fingerprint=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99 tenancy=ocid1.tenancy.oc1..exampleuniqueID region=us-ashburn-1 key_file=~/.oci/oci_api_key.pem
Verify the config:
import oci config = oci.config.from_file("~/.oci/config") oci.config.validate_config(config) identity = oci.identity.IdentityClient(config) user = identity.get_user(config["user"]).data print(f"Authenticated as: {user.name} ({user.email})")
Output
Successful completion produces:
- IAM policies granting appropriate access levels per group/role
- An API key pair with the public key uploaded to OCI Console
- A validated
file with correct user, fingerprint, tenancy, region, and key_file~/.oci/config - Verified authentication confirmed by a successful Identity API call
Error Handling
| Error | Code | Cause | Solution |
|---|---|---|---|
| NotAuthenticated | 401 | Bad API key, wrong fingerprint, or expired key | Regenerate key pair and re-upload public key |
| NotAuthorizedOrNotFound | 404 | Missing IAM policy — OCI returns 404, not 403 | Add policy for the group/resource/compartment |
| InvalidParameter | 400 | Policy syntax error | Check verb, resource-type, and compartment name spelling |
| TooManyRequests | 429 | Rate limited on Identity API | Back off; Identity has ~10 req/sec limit |
| InternalError | 500 | OCI service error | Retry after 30s; check https://ocistatus.oraclecloud.com |
| CERTIFICATE_VERIFY_FAILED | — | SSL certificate issue | Update CA certificates: |
Important: OCI returns
404 NotAuthorizedOrNotFound for both "resource doesn't exist" and "you don't have permission." Always check IAM policies first.
Examples
List all policies in a compartment:
import oci config = oci.config.from_file("~/.oci/config") identity = oci.identity.IdentityClient(config) policies = identity.list_policies(compartment_id=config["tenancy"]).data for p in policies: print(f"\n{p.name}:") for stmt in p.statements: print(f" {stmt}")
Quick policy validation via CLI:
# List all policies in the tenancy root oci iam policy list --compartment-id <tenancy-ocid> --all # Check what a specific group can do oci iam policy list --compartment-id <tenancy-ocid> --all \ | python3 -c "import sys,json; [print(s) for p in json.load(sys.stdin)['data'] for s in p['statements'] if 'DevOps' in s]"
Resources
- IAM Policy Reference — complete verb and resource-type list
- IAM Policy Syntax — syntax rules and conditions
- Common Policies — Oracle's recommended patterns
- API Key Management — key generation and upload
- Python SDK Reference — IdentityClient API
Next Steps
After IAM policies are in place, see
oraclecloud-enterprise-rbac for compartment hierarchy design and dynamic groups, or oraclecloud-multi-env-setup for profile-based environment separation.