This page covers Oracle Cloud Infrastructure logging and detection across the surfaces that decide whether the tenancy can observe what its workloads and identities are doing, surface unsafe state, and reject unsafe state at request time. Scope is the commercial OCI realms (OC1); OCI Government Cloud and dedicated-region tenancies inherit the same controls but expose realm-specific endpoints, Identity Domain federation constraints, and (for Cloud Guard) different reporting-region availability — re-verify region availability and the relevant docs.oracle.com realm-endpoint documentation before applying any of the IaC below to a sovereign or dedicated-region deployment. CIS sub-IDs and NIST / ISO mappings throughout this page reference the CIS Oracle Cloud Infrastructure Foundations Benchmark v2.0.0 (accessed 2026-05) unless explicitly annotated as a post-v2.0.0 feature or a best-practice recommendation that the v2.0.0 benchmark has not yet codified. CIS published the Oracle Cloud Infrastructure Foundations Benchmark v3.1.0 in 2026; this site cites v2.0.0 throughout the corpus for consistency with the locked compliance-table contract, and Cloud Guard's detector pack is certified against v2.0.0 — v3.1.0 evaluation requires Vulnerability Scanning Service plus manual compartment-policy checks until OCI ships the v3.1.0 detector recipe. The crosswalk page at compliance frameworks describes how the seven pinned framework columns relate to each other.
The OCI logging and detection model is the product of several distinct surfaces and each one has to be configured correctly because none of them is on-by-default in a useful way. The Audit service records every management-plane API call across the tenancy (write and read) into the tenancy-wide audit log group; it is enabled by default but the retention period defaults to 365 days (the maximum the Audit service itself stores) and an export to Object Storage is required for any compliance window longer than that. The Logging service (distinct from the Audit service — the equivalent discipline to Phase 8 GCP Cloud Audit Logs Admin vs Data Access is in play here) carries compartment-scoped service logs (Object Storage data events, KMS key use, VCN Flow Logs, Functions invocations) and custom application logs, organised into Log Groups and Logs; service logs are opt-in per service per category. Logging Analytics is OCI's SIEM-adjacent product (parser, dashboards, saved searches) — referenced in prose because it is the natural sink for high-volume log analysis, but not deep-dived per scope. Cloud Guard is the tenancy-scope detective posture engine — managed detector recipes evaluate configuration and activity, problems surface in the Cloud Guard problems view, and responder recipes wire the responsive pair to oci-ir-02-cloud-guard-remediation. Vulnerability Scanning Service (VSS) is the workload-scope detective engine — host scan recipes scan Compute instance OS for CVEs and open ports, container scan recipes scan Container Registry images on push. Security Zones is the tenancy-scope preventive engine — a compartment designated a Security Zone rejects non-compliant resource-creation API calls at request time using a Security Recipe (Maximum Security Recipe is Oracle-managed). Notifications is the topic-and-subscription fan-out service (with Events as the rules layer) that turns audit / Cloud Guard / Vault events into operator-visible alerts. Severity is assigned from the methodology severity rubric; equivalence callouts at the bottom of each control point at the matching control on the AWS, Azure, and GCP sibling pages. The cross-cutting principles — what to log, log integrity, centralization, retention, SIEM and detection engineering, and alerting — are owned by the General Logging & Detection page; this page maps them to OCI primitives.
Three anti-conflation callouts up front, because Cloud Guard, Vulnerability Scanning Service, and Security Zones are frequently confused as "the one OCI security posture thing" and each has a distinct scope and control-type that matters for both audit reporting and remediation design. This mirrors the Phase 7 Microsoft Defender for Cloud three-surface (regulatory dashboard / threat protection / Secure Score) discipline and the Phase 8 Security Command Center Premium three-surface (CSPM / threat detection / IAM Recommender) discipline. The three statements below are not optional flavour text — they are the load-bearing scope definitions that downstream auditors and incident responders rely on, and the page-level G13 gate enforces their presence with positive-grep.
Cloud Guard is DETECTIVE at tenancy scope. Cloud Guard monitors the tenancy for misconfigurations and suspicious activity using Oracle-managed detector recipes (Configuration detector for misconfigured resources, Activity detector for suspicious API patterns), responds to findings via responder recipes (which integrate with Notifications and Functions for custom playbooks), and surfaces problems in the Cloud Guard problems view for triage. Scope is the tenancy root compartment subtree — Cloud Guard is the cross-tenancy detection plane and the home of oci-log-03. Cloud Guard does not block resource creation; it observes unsafe state after it occurs. The responsive pair (responder recipes auto-remediating findings) lives canonically on oci-ir-02-cloud-guard-remediation; do not re-author here.
Vulnerability Scanning Service (VSS) is DETECTIVE on workloads. VSS host scan recipes scan Compute instance operating systems for CVEs and open ports on a schedule; container scan recipes scan Container Registry (OCIR) images on push (and on schedule) for CVEs in OS and language packages. Findings are surfaced both in the VSS console and into Cloud Guard via the VSS detector (so a tenancy that ships both gets a single problem-triage view). VSS is the workload-level CVE detection surface — distinct from Cloud Guard's tenancy-level misconfiguration detection scope. The closest cross-provider analog is AWS GuardDuty / Amazon Inspector, Azure Defender for Servers / Defender for Containers, and GCP Security Command Center Premium threat detection plus Container Analysis. The anchor literal oci-log-04-cloud-guard-detectors is historical (sibling-anchors.tsv lock from Phase 6); the functional Title for this control on this page is "Vulnerability Scanning Service" because it gives the cleanest cross-provider functional analog. See oci-log-04 for the full treatment.
Security Zones is PREVENTIVE via compartment policy. A compartment designated as a Security Zone rejects non-compliant resource-creation API calls at request time: a Public Object Storage bucket cannot be created in a Security Zone (the API call returns a 4xx, not a Cloud Guard problem after the fact); an unencrypted Block Volume cannot be created (must reference a Vault key); a Compute instance with a public IP cannot be created. The Maximum Security Recipe is the Oracle-managed default that bundles these rules; custom Security Recipes (cloned from Maximum Security Recipe and edited) handle environments where a strict Maximum Security Recipe rule legitimately conflicts (a static-website public bucket use case is the canonical example). Security Zones is distinct from Cloud Guard's detective scope — Security Zones blocks unsafe creation; Cloud Guard surfaces unsafe state. See oci-log-05 for the full treatment. The anchor literal oci-log-05-cloud-guard is historical (sibling-anchors.tsv lock); the functional Title for this control on this page is "Security Zones".
Order and scope matter. Controls 01–02 establish the management-plane and data-plane audit invariants: tenancy-wide Audit retention (365 days service + 2-year Object Storage archive with LOCKED retention rule) and per-service opt-in data-plane logging (Object Storage GetObject / PutObject, KMS Encrypt / Decrypt / Generate, Functions invocations). Control 03 enables Cloud Guard at the tenancy root for detective posture. Control 04 enables Vulnerability Scanning Service for workload-level CVE detection. Control 05 designates production compartments as Security Zones for preventive enforcement. Control 06 turns on VCN Flow Logs across every VNIC and subnet. Control 07 wires Notifications topics and subscriptions plus Events rules to the canonical tenancy-critical security events. Control 08 closes the forensic loop by archiving audit logs to Object Storage with a LOCKED 2-year retention rule. The compartment hierarchy primitive is owned by the OCI IAM page (Phase 5) and cross-referenced where relevant; do not re-author it here.
oci-log-01-audit-tenancy!CRITICALDETECTIVE
The OCI Audit service records every management-plane API call across the tenancy (write and read, success and failure, with the calling principal, source IP, request body where it does not contain secrets, and the affected resource OCIDs) into a tenancy-wide audit log; this is the OCI equivalent of AWS CloudTrail org-trail and Azure Activity Log centralisation. Set the Audit service retention to its 365-day maximum (CIS OCI v2.0.0 §4.x codifies the 365-day minimum), centralise audit events into a dedicated logging compartment, and archive every audit event to an Object Storage bucket with a LOCKED retention rule of 2 years (730 days) — this is the two-tier pattern that mirrors Phase 6 AWS CloudTrail plus S3 Object Lock Compliance mode and Phase 8 GCP aggregated sinks plus BigQuery audit. Without the archive tier the compliance window is bounded at 365 days; without the LOCKED retention rule the archive itself can be deleted by any principal with OBJECT_DELETE permission, which is the exact attacker profile incident response cares about (Oracle Cloud Infrastructure — Audit Service overview (accessed 2026-05)). The principle traces back to General Logging — log integrity: an audit log an attacker can shorten is not an audit log; immutability and chain-of-custody require write-once retention. CRITICAL because in the absence of tenancy-wide audit the organisation cannot detect, scope, or close out any incident touching the management plane — a Cloud Guard finding, a Vault key deletion, an Identity Domain group mutation, all become unobservable.
Remediation — OCI CLI
# oci CLI (v3.x)
# Step 1: set the Audit service retention to its 365-day maximum.
oci audit configuration update \
--compartment-id "$TENANCY_OCID" \
--retention-period-days 365
# Step 2: create the dedicated logging compartment and the audit-archive Object Storage bucket.
oci os bucket create \
--compartment-id "$LOGGING_COMPARTMENT_OCID" \
--name audit-archive-prod \
--namespace-name "$OS_NAMESPACE" \
--versioning Enabled \
--kms-key-id "$VAULT_KEY_OCID"
# Step 3: apply a LOCKED 2-year retention rule on the archive bucket.
# time_amount=730 days; time_rule_locked transitions immutable after 14-day grace.
oci os retention-rule create \
--bucket-name audit-archive-prod \
--namespace-name "$OS_NAMESPACE" \
--display-name compliance-2y \
--duration '{"timeAmount":730,"timeUnit":"DAYS"}' \
--time-rule-locked "$(date -u -d '+14 days' +%Y-%m-%dT%H:%M:%SZ)"
# Step 4: configure a Service Connector Hub to ship the tenancy Audit log into the archive bucket.
oci sch service-connector create \
--compartment-id "$LOGGING_COMPARTMENT_OCID" \
--display-name audit-to-archive \
--source '{"kind":"logging","logSources":[{"compartmentId":"'"$TENANCY_OCID"'","logGroupId":"_Audit","logId":"_Audit"}]}' \
--target '{"kind":"objectStorage","bucketName":"audit-archive-prod","namespaceName":"'"$OS_NAMESPACE"'"}'
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-01-audit-tenancy" \
--display-name "oci-log-01-audit-tenancy" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-01-audit-tenancy" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Remediation — Pulumi (TypeScript)
import * as pulumi from "@pulumi/pulumi";
import * as oci from "@pulumi/oci";
// Tenancy-wide Audit retention extension to 365 days (default is 90).
const cfg = new pulumi.Config();
const tenancyOcid = cfg.require("tenancyOcid");
const auditRetention = new oci.audit.Configuration("tenancy-audit-365d", {
compartmentId: tenancyOcid,
retentionPeriodDays: 365, // max-365 at the audit-service tier; archive longer via Logging
});
// Forward Audit events to a tenancy-level Logging service log group for long-term archive.
const auditArchiveGroup = new oci.logging.LogGroup("audit-archive", {
compartmentId: tenancyOcid,
displayName: "audit-archive-7yr",
description: "Long-term Audit event archive — exported via Service Connector to Object Storage",
});
const auditLog = new oci.logging.Log("audit-tenancy-forward", {
logGroupId: auditArchiveGroup.id,
displayName: "audit-tenancy",
logType: "SERVICE",
isEnabled: true,
configuration: {
source: {
sourceType: "OCISERVICE",
service: "audit",
resource: tenancyOcid,
category: "all",
},
},
retentionDuration: 180, // 6 mo at the Logging tier; Service Connector exports daily to OSS
});
export const auditLogOcid = auditLog.id;
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
3.1; 3.2
5.1.x
2.1; 2.2
4.x (verify)
AU-2; AU-3; AU-6; AU-9; AU-11
A.8.15; A.5.28
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' and 'Service Name' = 'audit' with eventName = 'UpdateConfiguration' reducing retentionPeriodDays below the 365-day baseline.
Audit-configuration deltas at the tenancy compartment that flip the Audit retention from the documented compliance window to the OCI minimum of 90 days.
Ingestion-rate drop on the tenancy-root Audit log group of more than 30% week-over-week — surfaces silent log-source detachments.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'audit'
and eventName = 'UpdateConfiguration'
| eval new_retention = data.request.payload.retentionPeriodDays
| where new_retention < 365
| stats count by 'User Name', 'Compartment Name', new_retention
The Audit retention setter is a single tenancy-scoped REST call; any successful invocation reducing the value is unambiguous.
Alert threshold
Any UpdateConfiguration setting retentionPeriodDays below 365 — page; this is the tenancy's compliance-window guard.
Week-over-week ingestion drop on the tenancy-root Audit log group exceeding 30% during steady-state hours — page; correlate with infrastructure changes.
Initial response
Restore the retention value to 365 days via oci audit config update; OCI Audit accepts the change instantly without backfill.
Snapshot the current Audit log archive to Object Storage with Object Lifecycle Management retention-rule in compliance mode so the historical window is preserved independently of the live setting.
Document the rollback per general/ir.html and update the tenancy compliance dashboard.
The OCI Audit service records management-plane API calls — bucket create, key rotate, policy update — but it does not record data-plane events (the GetObject and PutObject calls into individual buckets, the Encrypt and Decrypt and GenerateDataKey calls into individual Vault keys, the Function invocations) by default. Data-plane events are equivalent to the AWS CloudTrail "Data Events" tier and the Azure Storage Diagnostic Logs tier — they answer "who read the customer-data bucket between 02:00 and 04:00 UTC the night of the incident" and they are required for any forensic investigation of data exfiltration. Enable service logs explicitly for Object Storage read and write categories, for Vault key use, and for Functions invocations, organised into a per-service Log Group inside the dedicated logging compartment, and ship the resulting logs into Logging Analytics or via Service Connector Hub into Object Storage for long-term retention (OCI — Logging Service overview (accessed 2026-05)). The cost model is per-GB-ingested into the Logging service (with archival economics if you ship to Object Storage), so noisy services like Functions warrant a sampling policy decision rather than blanket 100% capture. HIGH because the absence of data-plane events makes data-exfiltration incidents un-investigable — the management-plane Audit log shows the bucket existed and the IAM policy permitted read, but not who read what and when.
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-02-data-events" \
--display-name "oci-log-02-data-events" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-02-data-events" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
3.x
5.x
2.x
4.x (verify)
AU-2; AU-12
A.8.15
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' with eventName in (UpdateLog, DeleteLog) targeting any service log resource (logType = SERVICE) backing Object Storage data events or Function invocation logs.
UpdateLogGroup events that move data-event log emitters out of the centralized log group, severing the pipeline to Logging Analytics.
Configuration deltas on individual service-log resources where isEnabled flips from true to false.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'logging'
and eventName in ('UpdateLog', 'DeleteLog')
| eval is_data_event = if(data.target.log.logType = 'SERVICE' and data.target.log.configuration.source.category in ('read', 'write'), 'YES', 'NO')
| where is_data_event = 'YES'
| stats count by 'User Name', data.target.log.displayName, eventName
Service logs are individually addressed; the inventory of data-event-emitting service logs is bounded and known per compartment.
Alert threshold
Any disable or delete of a data-event service log on Object Storage, KMS, or Functions resources — page; data-event visibility is required for forensic granularity.
An UpdateLogGroup moving a data-event log into a non-archival log group — page.
Initial response
Re-enable the service log via oci logging log update --is-enabled true; OCI Logging restarts the data-event pipeline within a minute.
Reconcile the log's parent group binding via Resource Manager so the central pipeline routes match the documented topology.
Backfill data-event coverage for the gap window from the resource's native audit feeds (Object Storage access via the bucket's own access log; KMS via tenancy-root Audit) per general/ir.html.
Cloud Guard is DETECTIVE at tenancy scope. Cloud Guard is OCI's cross-tenancy detection plane: enable it at the tenancy root with Oracle-managed detector recipes (the Configuration detector evaluates resource configurations against a library of checks — public buckets, weak NSG rules, IAM policies that grant manage all-resources, Vault keys without rotation; the Activity detector evaluates suspicious API call patterns — instance launched in unusual region, IAM policy created from anomalous source IP, MFA bypassed), set the target to the tenancy root compartment so detection covers the entire subtree, and attach the Oracle-managed responder recipe (which integrates with Notifications and Functions; the auto-remediation behaviour is canonically owned by oci-ir-02-cloud-guard-remediation on the OCI IR page). Problems surface in the Cloud Guard problems view with severity Critical / High / Medium / Minor / Low; integrate the problems stream into the organisation's SIEM or ticketing via Notifications topics for triage tracking. Cloud Guard's scope is tenancy posture (CSPM) — it observes unsafe state and surfaces findings; it does not block resource creation (Security Zones at oci-log-05 is the preventive surface) and it does not scan workloads for CVEs (Vulnerability Scanning Service at oci-log-04 is the workload-scope detective surface). The detector pack is certified against CIS OCI v2.0.0; v3.1.0 evaluation requires VSS findings plus manual compartment-policy checks until OCI ships the v3.1.0 detector pack (OCI — Cloud Guard documentation (accessed 2026-05)). The principle traces back to General Logging — SIEM and detection engineering: a posture engine that finds the issues nobody is configured to look for, with managed detector recipes that ship with the platform rather than being authored by the customer.
Remediation — OCI CLI
# oci CLI (v3.x)
# Step 1: enable Cloud Guard at the tenancy root with a reporting region.
# (Reporting region is the region where Cloud Guard stores problems; one per tenancy.)
oci cloud-guard configuration update \
--compartment-id "$TENANCY_OCID" \
--status ENABLED \
--reporting-region us-ashburn-1
# Step 2: create the tenancy-root target so detection covers the entire compartment subtree.
oci cloud-guard target create \
--compartment-id "$TENANCY_OCID" \
--display-name tenancy-root \
--target-resource-type COMPARTMENT \
--target-resource-id "$TENANCY_OCID"
# Step 3: attach the Oracle-managed detector + responder recipes to the target.
# (Recipe OCIDs are tenancy-specific; query with oci cloud-guard detector-recipe list.)
oci cloud-guard target-detector-recipe create \
--target-id "$TARGET_OCID" \
--detector-recipe-id "$ORACLE_MANAGED_CONFIG_DETECTOR_OCID"
oci cloud-guard target-responder-recipe create \
--target-id "$TARGET_OCID" \
--responder-recipe-id "$ORACLE_MANAGED_RESPONDER_OCID"
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-03-cloud-guard" \
--display-name "oci-log-03-cloud-guard" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-03-cloud-guard" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
3.x (Config)
2.x (Defender)
2.x (SCC)
(best-practices)
CM-8; CM-3; SI-4
A.8.9; A.8.16
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' and 'Service Name' = 'cloud-guard' with eventName = 'UpdateConfiguration' whose payload flips status from ENABLED to DISABLED.
Tenancy-root Cloud Guard configuration deltas where the reportingRegion changes — surfacing reporting-region migrations that interrupt finding flow.
Cloud Guard problem-stream gap longer than 15 minutes during steady-state operating hours.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'cloud-guard'
and eventName = 'UpdateConfiguration'
| eval cg_status = data.request.payload.status
| where cg_status = 'DISABLED'
| stats count by 'User Name', 'Compartment Name'
Cloud Guard tenancy enablement is a single boolean; disable events are exceptional and ticketed.
Alert threshold
Any tenancy Cloud Guard status transition to DISABLED — page immediately; this disables every detector and responder simultaneously.
Problem-stream gap exceeding 15 minutes on the tenancy-root reporting region during business hours — page.
Initial response
Re-enable Cloud Guard at the tenancy via oci cloud-guard configuration update --status ENABLED; detectors resume scanning within minutes.
Re-attach detector and responder recipes to the tenancy-root target if the disable cycle reset the binding state.
Replay the disabled window against the tenancy Audit log feed using the same JMESPath the Cloud Guard activity detector evaluates, and triage the surfaced events per general/ir.html.
Vulnerability Scanning Service (VSS) is DETECTIVE on workloads. The anchor literal oci-log-04-cloud-guard-detectors is preserved for sibling-provider link stability (sibling-anchors.tsv lock from Phase 6 — every AWS, Azure, and GCP logging page emits a graceful-then-STRICT href pointing at this anchor literal); the functional Title for this control on this page is "Vulnerability Scanning Service" because VSS provides the cleanest cross-provider functional analog to AWS GuardDuty / Amazon Inspector, Azure Defender for Servers and Defender for Containers, and GCP Security Command Center Premium threat detection plus Container Analysis. Configure two recipe surfaces: host scan recipes scan the operating system of Compute instances for CVEs and open ports on a schedule (the Cloud Agent must be running on the instance and the Vulnerability Scanning plugin must be enabled); container scan recipes scan Container Registry (OCIR) images on push and on a schedule for CVEs in OS and language packages. Findings surface in the VSS console with severity Critical / High / Medium / Low and also flow into Cloud Guard via the VSS detector, so a tenancy that ships both oci-log-03 and this control gets a single problem-triage view (OCI — Vulnerability Scanning Service (accessed 2026-05)). Remediation feedback flows back to OS Management Hub for patching workflows (oci-work-08-os-management-hub on the OCI Workloads page). VSS is distinct from Cloud Guard — VSS is workload-level CVE detection (the workloads themselves and the images they run); Cloud Guard is tenancy-level misconfiguration detection (the IAM policy, the bucket ACL, the NSG rule). Cross-reference oci-work-04-vulnerability-scanning: the work-level control is the host-scan recipe attached to a specific Compute instance fleet; this log-level control is the umbrella that covers all VSS recipes across the tenancy. CRITICAL because CVE detection in production OS and container images is the same severity as posture detection — an unpatched pre-auth RCE in a workload is the same root attack surface as an over-broad IAM policy, and going without is a CRITICAL gap.
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-04-cloud-guard-detectors" \
--display-name "oci-log-04-cloud-guard-detectors" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-04-cloud-guard-detectors" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Remediation — Pulumi (TypeScript)
import * as pulumi from "@pulumi/pulumi";
import * as oci from "@pulumi/oci";
// Cloud Guard detector recipes — Configuration + Activity detectors enabled.
const cfg = new pulumi.Config();
const tenancyOcid = cfg.require("tenancyOcid");
const reportingRegion = cfg.require("reportingRegion");
const cloudGuardConfig = new oci.cloudguard.CloudGuardConfiguration("cg-enable", {
compartmentId: tenancyOcid,
reportingRegion: reportingRegion,
status: "ENABLED",
selfManagedResources: false, // Oracle-managed detector definitions
});
// Clone Oracle-managed Configuration detector recipe + customise.
const configDetectorRecipe = new oci.cloudguard.DetectorRecipe("config-detector", {
compartmentId: tenancyOcid,
displayName: "hardening-config-detector",
detector: "IAAS_CONFIGURATION_DETECTOR",
sourceDetectorRecipeId: cfg.require("oracleConfigRecipeOcid"),
description: "Detect mis-configured public buckets, open SGs, unencrypted volumes",
}, { dependsOn: [cloudGuardConfig] });
// Bind detector recipe to a Cloud Guard Target at the tenancy root.
const tenancyTarget = new oci.cloudguard.Target("tenancy-target", {
compartmentId: tenancyOcid,
displayName: "tenancy-root-target",
targetResourceType: "COMPARTMENT",
targetResourceId: tenancyOcid,
targetDetectorRecipes: [{ detectorRecipeId: configDetectorRecipe.id }],
});
export const detectorRecipeOcid = configDetectorRecipe.id;
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
4.x (GuardDuty)
2.x (Defender)
2.x (SCC Premium)
(best-practices)
SI-4; SI-4(2); RA-5
A.8.16; A.8.8
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' with eventName = 'UpdateDetectorRecipe' whose request payload flips a Configuration detector rule with risk-level HIGH or CRITICAL to isEnabled = false.
Detector-recipe deletion events targeting any recipe attached to the tenancy-root Cloud Guard target.
Activity-detector rule risk-level downgrades from CRITICAL to lower bands — surface via Cloud Guard problem audit events.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'cloud-guard'
and eventName in ('UpdateDetectorRecipe', 'DeleteDetectorRecipe')
| eval rule = data.request.payload.detectorRules
| where rule like '%isEnabled":false%' and (rule like '%HIGH%' or rule like '%CRITICAL%')
| stats count by 'User Name', data.target.detectorRecipe.id
Detector recipes are layered (Oracle-managed base + custom overrides); the gate fires on either layer when a HIGH/CRITICAL rule is disabled.
Alert threshold
Any HIGH or CRITICAL detector rule disabled outside the documented Cloud Guard tuning window — page on first event.
Deletion of a detector recipe currently bound to the tenancy-root target — page.
Initial response
Re-enable the disabled rule via the recipe REST endpoint; Cloud Guard re-evaluates against current resource inventory within the next scan cycle.
Re-attach any deleted recipe from the Resource Manager state; recipe bindings are recoverable from the stack output.
Diff the active recipe ruleset against the documented baseline ruleset and reconcile any other rule-state drift discovered during triage.
Security Zones is PREVENTIVE via compartment policy. The anchor literal oci-log-05-cloud-guard is preserved for sibling-provider link stability (sibling-anchors.tsv lock from Phase 6); the functional Title for this control on this page is "Security Zones" — the preventive enforcement surface that is distinct from Cloud Guard's detective scope at oci-log-03. A compartment designated as a Security Zone rejects non-compliant resource-creation API calls at request time using a Security Recipe: the call to create a public-read Object Storage bucket returns a 4xx response, not a Cloud Guard problem after the fact; the call to create a Block Volume without a Vault key reference is rejected; the call to launch a Compute instance with a public IP in the wrong subnet is rejected. The Oracle-managed Maximum Security Recipe is the default starting point (RESEARCH Open Q #5 resolution) — it bundles the canonical hardening rules: buckets must be private, Block Volumes must be CMEK-encrypted with a Vault key, Compute instances must not have public IPs, only approved Vault keys may be used, and so on. For environments where a Maximum Security Recipe rule legitimately conflicts (the canonical example is a static-website public bucket use case where the rule "buckets must be private" cannot hold), clone the Maximum Security Recipe and edit the conflicting rule into a Custom Security Recipe; the recommendation is to scope the custom recipe to one compartment and keep the Maximum Security Recipe on every other production compartment (OCI — Security Zones documentation (accessed 2026-05)). Security Zones blocks unsafe creation at request time; Cloud Guard surfaces unsafe state after the fact — the two surfaces are complementary, and a tenancy that ships both gets both prevention and detection across the same compartment subtree. The principle traces back to General Logging — what to log and to the broader preventive-vs-detective distinction codified in methodology — control-type labelling: a control that rejects unsafe state at the API request boundary is preventive by definition, even when the underlying engine (Cloud Guard) also has a detective surface. HIGH severity because Security Zones is the strongest preventive surface OCI exposes for compartment-scoped policy enforcement; not CRITICAL because the rules it enforces are also enforced by the corresponding individual controls (no-public-bucket lives on oci-data-01-object-storage-private, CMEK on Block Volumes lives on oci-data-03-block-volume-encryption) — Security Zones is the belt-and-braces enforcement layer on top.
Remediation — OCI CLI
# oci CLI (v3.x)
# Step 1: list the Oracle-managed Maximum Security Recipe OCID.
oci cloud-guard security-recipe list \
--compartment-id "$TENANCY_OCID" \
--owner ORACLE \
--query 'data.items[?contains("display-name", `Maximum`)] | [0].id'
# Step 2 (optional): clone the Maximum Security Recipe as the starting point for a Custom Recipe.
# (Skip this step and use the Oracle-managed OCID directly if no rule exceptions are required.)
oci cloud-guard security-recipe create \
--compartment-id "$SECURITY_COMPARTMENT_OCID" \
--display-name custom-recipe-static-site \
--owner USER \
--security-policies "[\"$MAX_SECURITY_POLICY_1\", \"$MAX_SECURITY_POLICY_2\"]"
# Step 3: designate the production compartment as a Security Zone bound to the recipe.
oci cloud-guard security-zone create \
--compartment-id "$PROD_COMPARTMENT_OCID" \
--display-name prod-zone \
--security-zone-recipe-id "$RECIPE_OCID"
Remediation — Terraform
# Terraform OCI provider ~> 5.0
# Source: Oracle Security Zones docs (accessed 2026-05)
# Reference the Oracle-managed Maximum Security Recipe via data source.
data "oci_cloud_guard_security_recipes" "managed" {
compartment_id = var.tenancy_ocid
display_name = "OracleSecurityZoneRecipeMaxSecurity"
}
# OPTIONAL: clone the Maximum Security Recipe for a per-compartment exception.
# Most production compartments should use the Oracle-managed recipe OCID directly
# without cloning — only clone when a specific rule legitimately conflicts
# (canonical example: static-website public bucket use case).
resource "oci_cloud_guard_security_recipe" "custom" {
compartment_id = var.security_compartment_id
display_name = "custom-recipe-static-site"
owner = "USER"
security_policies = data.oci_cloud_guard_security_recipes.managed.security_recipe_collection[0].items[0].security_policies
}
# Designate the production compartment as a Security Zone — preventive enforcement.
# Resource-creation API calls into this compartment are evaluated against the recipe
# at request time; non-compliant calls return a 4xx response.
resource "oci_cloud_guard_security_zone" "prod" {
compartment_id = var.prod_compartment_id
display_name = "prod-zone"
security_zone_recipe_id = data.oci_cloud_guard_security_recipes.managed.security_recipe_collection[0].items[0].id
}
Remediation — OCI Resource Manager
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-05-cloud-guard" \
--display-name "oci-log-05-cloud-guard" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-05-cloud-guard" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
n/a (SCP analog)
2.x (Defender)
2.x (Org Policy)
(best-practices)
CM-7; CM-2; AC-3
A.8.9; A.5.15
CLD.9.5.1
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' with eventName = 'DeleteTarget' targeting the tenancy-root Cloud Guard target — removal breaks the scanning surface for the whole subtree.
UpdateTarget events whose payload shrinks the targetResourceType coverage or removes the tenancy compartment from scope.
Managed-list mutation events (UpdateManagedList) that strip IOC indicators from the curated risk-list bound to detector rules.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'cloud-guard'
and eventName in ('DeleteTarget', 'UpdateTarget', 'UpdateManagedList')
| eval scope = data.target.target.targetResourceType
| where eventName = 'DeleteTarget'
or scope is null
| stats count by 'User Name', data.target.target.id, eventName
Target deletions are exceptional events; their absence in the Audit feed is itself a tenancy-health signal.
Alert threshold
Any DeleteTarget on the tenancy-root Cloud Guard target — page immediately.
Managed-list update reducing entry count by more than 25% in a single edit — page; bulk IOC removal is uncommon outside list rotation.
Initial response
Re-create the tenancy-root target via Resource Manager and re-bind the documented detector and responder recipes; Cloud Guard backfills missed problem detections on the next scan cycle.
Restore the managed-list contents from the version-controlled IOC source-of-truth pipeline; managed lists support bulk JSON import.
Triage any problems that surfaced during the target-down window and escalate per general/ir.html.
VCN Flow Logs capture L3/L4 metadata (5-tuple, action ACCEPT or REJECT, byte and packet counts) for every flow that traverses a VNIC or subnet on which Flow Logs are enabled; they are the OCI equivalent of AWS VPC Flow Logs, Azure NSG Flow Logs, and GCP VPC Flow Logs, and they are the foundational network-detection surface for any anomaly-driven SIEM rule. Enable Flow Logs on every subnet (the subnet-level surface aggregates over every VNIC in the subnet — the right default for breadth) with sampling at 100% for security-critical subnets (database tier, management subnets, anything carrying customer data) and a reduced sampling rate (1% or 0.1%) for high-volume non-sensitive subnets where the cost of 100% sampling is not justified by the detection value; aggregate the resulting logs into a centralised Log Group in the dedicated logging compartment, and export to Object Storage via Service Connector Hub for long-term retention (OCI — VCN Flow Logs (accessed 2026-05)). The principle traces back to General Logging — what to log: the network plane is the second-to-last forensic surface before the workload itself, and the cost of not having Flow Logs is paid only once — during an incident, when there is no time to backfill them. MEDIUM severity (not HIGH) because Flow Logs alone don't prevent or detect specific known-bad behaviours; they are the substrate on which detection rules and forensic queries operate.
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-06-vcn-flow-logs" \
--display-name "oci-log-06-vcn-flow-logs" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-06-vcn-flow-logs" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
3.x (VPC FL)
5.x (NSG FL)
2.x (VPC FL)
4.x (verify)
AU-2; AU-12; SC-7
A.8.15; A.8.16
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' with eventName = 'DeleteLog' targeting any log resource of category flowlogs.
VCN subnet update events where the subnet's flow-log configuration reference is removed or pointed at a deleted log OCID.
Flow-log ingestion volume drop on a per-subnet basis greater than 50% week-over-week — silent flow-log detachments often happen at the subnet layer.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' = 'logging'
and eventName in ('UpdateLog', 'DeleteLog')
| eval cat = data.target.log.configuration.source.category
| where cat in ('flowlogs', 'all') and (eventName = 'DeleteLog' or data.target.log.isEnabled = 'false')
| stats count by 'User Name', data.target.log.displayName, eventName
VCN flow logs are emitted per-subnet via service logs; the inventory is bounded and discoverable via oci logging log list --log-type SERVICE.
Alert threshold
Any flow-log delete or disable on a subnet flagged as production in the resource tag inventory — page.
Subnet-level flow-log ingestion volume drop greater than 50% over a 7-day rolling baseline — page.
Initial response
Re-create the flow-log resource and re-attach it to the affected subnet via Resource Manager; OCI emits flow records within the next scrape interval.
Cross-check VCN Flow Logs ingestion against the subnet inventory tag to identify any other subnets running without flow-log coverage and bulk-remediate.
Brief the network team and update the flow-log coverage dashboard per general/ir.html.
The OCI Notifications service is the topic-and-subscription fan-out primitive (a topic-per-event-class, subscribers via Email, PagerDuty, Slack, HTTPS, or OCI Functions for custom playbooks) and the Events service is the rule-evaluation layer that filters audit events and emits matching events onto Notifications topics. Together they are the wire that turns the canonical tenancy-critical security events — Identity Domain policy create / update / delete, group membership mutations, Vault key delete or rotation, Audit configuration update, Cloud Guard Critical or High problems, federated IdP configuration change — into operator-visible alerts in the channels the SOC actually watches. Without this wire, the events are captured in the Audit log but nobody is paged on them, which means the median time-to-detect-and-respond stretches from minutes to whatever the SOC's batch-log-review cadence is. Configure one topic per event class (so an Email-only subscriber for low-criticality changes does not page the on-call channel that handles Vault-key deletes) and bind Events rules to event types via the Oracle event type schema — for example com.oraclecloud.identitycontrolplane.updatepolicy, com.oraclecloud.keymanagement.deletekey, com.oraclecloud.cloud-guard.problemdetected (OCI — Notifications Service (accessed 2026-05); OCI — Events Service (accessed 2026-05)). The principle traces back to General Logging — alerting: capture-without-alerting is detection theatre; an event nobody is paged on is not detected, only recorded.
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-07-notifications" \
--display-name "oci-log-07-notifications" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-07-notifications" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
4.x
5.x
2.x
4.x (verify)
AU-6; SI-4
A.8.16
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' and 'Service Name' = 'ons' with eventName in (DeleteTopic, DeleteSubscription) targeting topics or subscriptions on the detection-pipeline fan-out path.
Service Connector Hub events (UpdateServiceConnector) that drop a Notifications-sink target from a connector wiring Cloud Guard problems into operator paging.
Notifications topic publish-rate drop greater than 75% week-over-week on operator-paging topics — surface silent connector breaks.
Query
'Log Source' = 'OCI Audit Logs'
and 'Service Name' in ('ons', 'sch')
and eventName in ('DeleteTopic', 'DeleteSubscription', 'UpdateServiceConnector')
| eval target_topic = data.target.topic.name
| where target_topic like '%paging%' or target_topic like '%cloud-guard%'
| stats count by 'User Name', target_topic, eventName
Tag operator-paging topics with a defined-tag NotificationRole = paging so the saved search filters by tag rather than name pattern.
Alert threshold
Any delete on a topic or subscription tagged NotificationRole = paging — page on the secondary channel (the primary channel just broke).
Service Connector Hub edit that drops a Notifications sink from a Cloud Guard fan-out connector — page.
Initial response
Re-create the topic and subscription via Resource Manager; OCI ONS preserves the subscription endpoint format and re-confirms the channel automatically for email/HTTPS subscribers.
Re-wire the Service Connector Hub target list to include the restored topic OCID; SCH back-pressure replays buffered events.
Page on the secondary channel during the rebuild, since the primary path was the disrupted channel; document the rollback per general/ir.html.
The Audit service stores tenancy-wide management-plane events for 365 days; anything beyond that is the responsibility of an archive. Ship the Audit log to an Object Storage bucket via Service Connector Hub, encrypt the bucket with a Vault key (so the archive is part of the same key-policy boundary as the live audit stream, and key destruction destroys both — which is the correct invariant for incident response, because an archive an attacker can delete is not an archive), apply a LOCKED retention rule of 2 years (730 days) so the archive becomes immutable after the 14-day grace window and cannot be reduced or deleted even by tenancy-admin. This is the two-tier mirror of oci-log-01: oci-log-01 enforces the live retention configuration; this control owns the immutable forensic archive. The forensic search workflow during an incident is to query Logging Analytics or Audit search against the live 365-day window for current activity, and against the Object Storage archive (via OCI Storage Gateway or via a Functions-driven re-ingest) for activity older than 365 days. Cross-reference oci-data-08-object-retention — the retention-rule pattern itself is owned by the Object Storage page; this control composes it with the Audit-to-bucket pipeline (OCI — exporting Audit log files (accessed 2026-05)). Typed RESPONSIVE not DETECTIVE because the archive's value is forensic — it is searched only after an incident is declared, and its presence does not by itself surface alerts or block unsafe state. MEDIUM severity because operating without the archive is recoverable up to the 365-day live retention horizon; below that horizon, evidence is gone.
Remediation — OCI CLI
# oci CLI (v3.x)
# Step 1: create the audit-archive bucket KMS-encrypted with a Vault key.
oci os bucket create \
--compartment-id "$LOGGING_COMPARTMENT_OCID" \
--name audit-archive-forensic \
--namespace-name "$OS_NAMESPACE" \
--versioning Enabled \
--kms-key-id "$VAULT_KEY_OCID"
# Step 2: apply the 2-year LOCKED retention rule.
oci os retention-rule create \
--bucket-name audit-archive-forensic \
--namespace-name "$OS_NAMESPACE" \
--display-name forensic-2y-locked \
--duration '{"timeAmount":730,"timeUnit":"DAYS"}' \
--time-rule-locked "$(date -u -d '+14 days' +%Y-%m-%dT%H:%M:%SZ)"
# Step 3: create the Service Connector from the tenancy Audit log to the archive bucket.
oci sch service-connector create \
--compartment-id "$LOGGING_COMPARTMENT_OCID" \
--display-name audit-to-forensic-archive \
--source '{"kind":"logging","logSources":[{"compartmentId":"'"$TENANCY_OCID"'","logGroupId":"_Audit","logId":"_Audit"}]}' \
--target '{"kind":"objectStorage","bucketName":"audit-archive-forensic","namespaceName":"'"$OS_NAMESPACE"'"}'
# Submit the Terraform block above to OCI Resource Manager via a configured
# Git source-provider. Variables are entered through the Console UI (schema-driven
# by an optional schema.yaml); state is stored in OCI Object Storage automatically.
# This is an INVOCATION snippet — the .tf body is the existing Terraform block
# on this same control-box (do NOT duplicate HCL here).
oci resource-manager stack create-from-git-provider \
--compartment-id "$COMPARTMENT_OCID" \
--config-source-provider-id "$CONFIG_SRC_PROVIDER_OCID" \
--repository-url "https://example.com/org/hardening-iac" \
--branch-name "main" \
--working-directory "modules/oci-log-08-audit-archive" \
--display-name "oci-log-08-audit-archive" \
--terraform-version "1.5.x"
# Plan + apply via the ORM job lifecycle (state stored in OCI automatically).
STACK_OCID=$(oci resource-manager stack list \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "oci-log-08-audit-archive" \
--query 'data[0].id' --raw-output)
PLAN_JOB_OCID=$(oci resource-manager job create-plan-job \
--stack-id "$STACK_OCID" --query 'data.id' --raw-output)
oci resource-manager job create-apply-job \
--stack-id "$STACK_OCID" \
--execution-plan-strategy FROM_PLAN_JOB \
--execution-plan-job-id "$PLAN_JOB_OCID"
Compliance mapping
CIS AWS Foundations v3.0.0
CIS Microsoft Azure Foundations v3.0.0
CIS GCP Foundation v4.0.0
CIS OCI Foundation v2.0.0
NIST SP 800-53 rev5
ISO/IEC 27001:2022
ISO/IEC 27017:2015
3.x (Lake)
5.x (Sentinel)
2.x (BQ sink)
(best-practices)
AU-11; IR-4(7)
A.8.15; A.5.28
CLD.12.4.5
Log signals
OCI Logging Analytics records where 'Log Source' = 'OCI Audit Logs' with eventName in (UpdateBucket, DeleteBucket) targeting the Object Storage bucket configured as the long-term audit archive sink.
Service Connector Hub deletion events removing the connector that copies Audit events into the archive bucket.
Object Storage Object Lifecycle Management rule deletions on the archive bucket — surface immutability-policy weakening.
Query
'Log Source' = 'OCI Audit Logs'
and (
('Service Name' = 'object-storage' and eventName in ('UpdateBucket','DeleteBucket','UpdateRetentionRule','DeleteRetentionRule')
and data.target.bucket.name like '%audit-archive%')
or
('Service Name' = 'sch' and eventName in ('DeleteServiceConnector','UpdateServiceConnector')
and data.target.serviceConnector.displayName like '%audit-archive%')
)
| stats count by 'User Name', eventName, 'Compartment Name'
Tag the archive bucket and the connector with AuditArchive = primary so the JMESPath substring filter can pivot to a tag-based filter when the resource inventory grows.
Alert threshold
Any retention-rule delete or weakening on the archive bucket — page; archive immutability is a tenancy-compliance guard.
Any SCH connector delete on the audit-archive pipeline — page.
Initial response
Re-apply the bucket retention rule and connector definition via Resource Manager; OCI Object Storage and SCH accept the change online.
Verify the archive bucket's most recent object-prefix matches the expected timestamp cadence; if there is a gap, replay from the Logging Analytics live store via SCH backfill.
Confirm the bucket policy still denies non-archive identities; reconcile any policy drift per general/ir.html.