Skip to main content

OCI Governance Should Have Custom Compartments Created

More Info:

Enforce the CIS landing zone architecture by requiring custom compartments. Resources should never be deployed directly into the root tenancy compartment to ensure strict administrative boundary isolation

Risk Level

High

Address

Compliance, Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • Cloudanix Best Practice
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Using Console

To meet the “OCI Governance Should Have Custom Compartments Created” requirement using the OCI Console, you just need to create at least one non-root compartment (and typically more, aligned to your governance model). Here are the steps:


1. Sign in and choose the right tenancy/root compartment

  1. Sign in to the OCI Console.
  2. In the top-left, open the hamburger menu.
  3. Make sure you are in the correct tenancy and region (top-right of the console).
  4. In the Compartment selector (usually above the main pane), confirm you are viewing the root compartment (the tenancy name).

2. Navigate to Compartments

  1. Open the hamburger menu.
  2. Go to Identity & SecurityCompartments.

3. Create a custom compartment

  1. On the Compartments page, click Create Compartment.
  2. Fill in:
    • Name: e.g., prod, nonprod, network, logging, etc.
    • Description: brief description of its purpose.
    • Parent Compartment:
      • Usually the root compartment for top-level governance compartments, or
      • Another compartment if building a hierarchy (e.g., prod > prod-network).
  3. (Optional but recommended) Add Tags if your governance model uses tag-based organization.
  4. Click Create Compartment.

Repeat this for all compartments required by your governance standards (e.g., separate compartments for environments, business units, shared services, security/logging).


4. Attach or verify IAM policies for the new compartments

To make the compartments actually usable under your governance model:

  1. Go to Identity & SecurityPolicies.
  2. Create or edit policies in the root compartment (or appropriate parent) that:
    • Grant groups access to use/manage resources in the new compartments.
    • Example policy (pseudo):
      Allow group Network-Admins to manage virtual-network-family in compartment prod-network
      Allow group App-Admins to manage all-resources in compartment prod
  3. Click Create or Save changes.

5. (If applicable) Move resources into the new compartments

If you already have resources in the root compartment that should be governed:

  1. Navigate to the resource type (e.g., Compute → Instances, Networking → VCNs).
  2. For each resource, open its Details page.
  3. Click Move resource (or equivalent).
  4. Choose the appropriate target compartment and confirm.

6. Confirm remediation for Governance Monitoring

  1. Go back to your Governance/Compliance/Cloud Guard or Monitoring page where the finding was raised.
  2. Wait for the next evaluation cycle (or trigger a rescan if supported).
  3. Verify the finding “OCI Governance Should Have Custom Compartments Created” is Resolved/Closed.

If you tell me your intended structure (environments, BUs, or projects), I can give a minimal recommended compartment tree and example policies tailored to that.

Using CLI

To satisfy “OCI Governance Should Have Custom Compartments Created” using the OCI CLI, you need to create at least one compartment under the root tenancy (not use only the root compartment).

Below are the minimal step-by-step CLI instructions.


1. Ensure OCI CLI is configured

If not already done:

oci setup config

Follow prompts (tenancy OCID, user OCID, region, etc.).


2. Get your tenancy OCID (root compartment ID)

If you don’t know your tenancy OCID, you can fetch it via:

oci iam compartment list --compartment-id-in-subtree false --access-level ACCESSIBLE

Look for the compartment with "name": "tenancy" (or your tenancy name). Its "id" is the root compartment OCID.
You can also see it in the web console under: Profile icon → Tenancy OCID.

Assume:

TENANCY_OCID="<your-tenancy-ocid>"

3. Create a custom compartment

Use oci iam compartment create with the root compartment as the parent:

COMPARTMENT_NAME="custom-governance-comp"
COMPARTMENT_DESC="Custom compartment for governance / resource segregation"

oci iam compartment create \
--compartment-id "$TENANCY_OCID" \
--name "$COMPARTMENT_NAME" \
--description "$COMPARTMENT_DESC"

This returns JSON including the new compartment "id" and "lifecycle-state": "CREATING" or "ACTIVE".


4. (Optional) Verify the compartment exists and is ACTIVE

oci iam compartment list \
--compartment-id "$TENANCY_OCID" \
--access-level ANY \
--compartment-id-in-subtree false \
--all \
| jq '.data[] | {name, id, "lifecycle-state"}'

Ensure your new compartment is listed and lifecycle-state is ACTIVE.


5. Wait for governance monitoring to re-evaluate

OCI governance/posture tools (Cloud Guard / Security Zones / Governance Monitoring) usually re-check on a schedule. After the compartment is created and ACTIVE, the “Custom Compartments Created” requirement should pass on the next evaluation cycle.

If you need more than one custom compartment (e.g., by environment), repeat step 3 with different names:

for env in dev test prod; do
oci iam compartment create \
--compartment-id "$TENANCY_OCID" \
--name "comp-$env" \
--description "Compartment for $env environment"
done

That’s all that’s required from the CLI side to remediate this specific control.

Using Python

Below is a concise, stepwise way to remediate the finding “OCI Governance Should Have Custom Compartments Created” using Python and the OCI SDK.

1. Prerequisites

  1. Install OCI Python SDK:

    pip install oci
  2. Configure your OCI CLI profile (used by the SDK):

    oci setup config

    This creates ~/.oci/config. Note your:

    • tenancy
    • user
    • fingerprint
    • key_file
    • region
    • profile name (e.g., DEFAULT)
  3. Have appropriate IAM permissions on the tenancy root to create compartments:

    • inspect compartments in tenancy
    • use tenancy
    • manage compartments in tenancy (or equivalent policy)

2. Decide the Compartment Structure

Define the custom compartments you want for governance/monitoring. Common patterns:

  • security-governance-root
    • security-monitoring
    • compliance-logs
    • audit-archive

You can represent this as a list of desired compartments with parent-child relations.


3. Python Script to Ensure Custom Compartments Exist

This script will:

  1. Connect using your OCI config profile.
  2. Look up the tenancy OCID.
  3. Check if the target compartments already exist.
  4. Create any that are missing under the correct parent.
import oci
from oci.identity import IdentityClient

# ------------ CONFIGURATION ------------
OCI_CONFIG_FILE = "~/.oci/config"
OCI_PROFILE = "DEFAULT" # change if needed

# Desired compartment structure
# Each entry is: { name, description, parent_key }
# parent_key 'TENANCY_ROOT' means direct child of tenancy
DESIRED_COMPARTMENTS = [
{"key": "SEC_GOV_ROOT", "name": "security-governance-root",
"description": "Root compartment for security & governance resources",
"parent_key": "TENANCY_ROOT"},

{"key": "SEC_MONITORING", "name": "security-monitoring",
"description": "Compartment for governance and security monitoring services",
"parent_key": "SEC_GOV_ROOT"},

{"key": "COMPLIANCE_LOGS", "name": "compliance-logs",
"description": "Compartment for compliance-related logs and artifacts",
"parent_key": "SEC_GOV_ROOT"},
]


def get_compartment_by_name(identity_client, parent_ocid, name):
"""
Return the first ACTIVE compartment with a given name under a parent,
or None if not found.
"""
comps = oci.pagination.list_call_get_all_results(
identity_client.list_compartments,
parent_ocid,
compartment_id_in_subtree=False,
access_level="ANY"
).data

for c in comps:
if c.name == name and c.lifecycle_state == "ACTIVE":
return c
return None


def main():
# Load config
config = oci.config.from_file(OCI_CONFIG_FILE, OCI_PROFILE)

# Create Identity client
identity_client = IdentityClient(config)

tenancy_id = config["tenancy"]

# Cache map: key -> compartment_ocid
compartment_ids = {}

# The tenancy root is a special "parent"
compartment_ids["TENANCY_ROOT"] = tenancy_id

# Process in multiple passes until all parents are resolved
# This allows children to reference parents defined earlier in the list
remaining = DESIRED_COMPARTMENTS.copy()

# Continue until all compartments created or no more progress
while remaining:
progress_made = False
still_remaining = []

for item in remaining:
parent_key = item["parent_key"]

if parent_key not in compartment_ids:
# Parent not yet created/resolved
still_remaining.append(item)
continue

parent_ocid = compartment_ids[parent_key]
name = item["name"]
description = item["description"]

# Check if compartment already exists
existing = get_compartment_by_name(identity_client, parent_ocid, name)

if existing:
print(f"[INFO] Compartment '{name}' already exists: {existing.id}")
compartment_ids[item["key"]] = existing.id
else:
print(f"[INFO] Creating compartment '{name}' under parent {parent_ocid}...")
create_details = oci.identity.models.CreateCompartmentDetails(
compartment_id=parent_ocid,
name=name,
description=description
)
response = identity_client.create_compartment(create_details)
new_comp = response.data
print(f"[INFO] Created compartment '{name}' with OCID: {new_comp.id}")
compartment_ids[item["key"]] = new_comp.id

progress_made = True

if not progress_made:
raise RuntimeError(
"Could not resolve parents for some compartments; "
"check 'parent_key' values and ordering."
)

remaining = still_remaining

print("\n[SUMMARY] Final compartment mapping:")
for k, v in compartment_ids.items():
print(f" {k}: {v}")


if __name__ == "__main__":
main()

4. Connect These Compartments to Governance Monitoring

After creating the custom compartments:

  1. Update your Governance/Monitoring policies so that the monitoring service (or your monitoring user/group/dynamic group) can:

    • Read from monitored compartments.
    • Write logs/metrics into the new governance compartments (e.g., security-monitoring, compliance-logs).

    Example policies (adjust OCIDs/names):

    allow dynamic-group governance-monitoring-dg to read all-resources in compartment security-governance-root
    allow dynamic-group governance-monitoring-dg to manage log-groups in compartment security-monitoring
    allow dynamic-group governance-monitoring-dg to manage log-content in compartment compliance-logs
  2. In your governance/monitoring code or Terraform/Resource Manager stacks, reference the new compartment OCIDs (printed by the script) when:

    • Creating log groups.
    • Creating alarms.
    • Creating notifications channels.

5. Automate Execution

Integrate the script into your CI/CD or governance bootstrap process so it:

  • Runs on initial tenancy onboarding.
  • Optionally verifies the compartments remain present and active.
Using Terraform
# Create a custom compartment instead of using the root tenancy
resource "oci_identity_compartment" "APP_COMPARTMENT" {
# Replace with your tenancy OCID (root)
compartment_id = "ocid1.tenancy.oc1..ROOT_TENANCY_OCID"

name = "APP_COMPARTMENT_NAME" # e.g. "prod-apps"
description = "Application resources compartment for PROD"
enable_delete = false
}

# Example: place governed resources into the custom compartment,
# not directly into the root tenancy.
resource "oci_core_vcn" "APP_VCN" {
# Previously this was set to the tenancy OCID (root); that is what
# triggered the governance finding. It must point to a custom compartment.
compartment_id = oci_identity_compartment.APP_COMPARTMENT.id

cidr_block = "10.0.0.0/16"
display_name = "APP_VCN"
dns_label = "appvcn"
}

# Repeat the same pattern for every OCI resource that is currently
# using the root tenancy OCID as compartment_id:
# - Change compartment_id from "ocid1.tenancy.oc1..ROOT_TENANCY_OCID"
# to oci_identity_compartment.APP_COMPARTMENT.id (or other custom compartment).
#
# Example for an OCI Logging log group used by Governance Monitoring:
resource "oci_logging_log_group" "GOV_MONITORING_LOG_GROUP" {
compartment_id = oci_identity_compartment.APP_COMPARTMENT.id

display_name = "gov-monitoring-logs"
description = "Log group for governance / CIS monitoring"
}

# NOTE: Moving existing resources between compartments is effectively a move
# operation in OCI. When you change compartment_id in Terraform for resources
# that already exist, OCI may treat it as a move or a replace depending on
# the resource type; confirm impact before applying in production.

A terraform plan that remediates the finding should show:

  • A new oci_identity_compartment.APP_COMPARTMENT to be created.
  • For each governed resource currently in the root tenancy, an update where compartment_id changes from the root tenancy OCID to the new compartment’s OCID (or, for some resources, a destroy-and-recreate reflecting the move).