Skip to content

Add Oracle Cloud Infrastructure (OCI) integration - #108

Open
allamiro wants to merge 1 commit into
wazuh:mainfrom
allamiro:feat/oracle-cloud-oci-integration
Open

Add Oracle Cloud Infrastructure (OCI) integration#108
allamiro wants to merge 1 commit into
wazuh:mainfrom
allamiro:feat/oracle-cloud-oci-integration

Conversation

@allamiro

@allamiro allamiro commented Aug 6, 2026

Copy link
Copy Markdown

What this is

Wazuh ships native cloud wodles for AWS, Azure and GCP. There is no OCI equivalent, so every Oracle Cloud user has to write the collector themselves. This adds a complete community integration for the path Oracle actually supports:

OCI service  ->  Logging + Audit  ->  Connector Hub  ->  Streaming or Object Storage  ->  Wazuh

It grew out of a community thread where a user asked how to forward logs from eleven OCI services and was correctly told there is no native integration, then pointed at Connector Hub with "write a script that reads from that endpoint". This is that script, plus the ruleset that turns the logs into alerts.

Related

Relates to wazuh/wazuh#31146 — a request for OCI parity with AWS/Azure/GCP, closed as NOT_PLANNED with the note that there are "no official OCI integration documentation or tested procedures". This does not close that request: it is a community contribution, not a native module. It does provide a tested procedure in the meantime.

That thread suggested the S3-compatible route as a stopgap. This takes the native OCI SDK route instead, so there is no S3 compatibility shim between Wazuh and Object Storage.

Why one connector covers all eleven services

OCI Audit records the control plane for every service, so a single connector on the _Audit log group covers all of them. Only four also emit data-plane service logs:

Service Audit (control plane) Service log (data plane)
Virtual Cloud Network (VCN) Yes Yes — Flow Logs
Object Storage Yes Yes — Read/Write Access Events
API Gateway Yes Yes — Access + Execution
Email Delivery Yes Yes — outbound accepted/relayed/suppressed
Dynamic Routing Gateway (DRG) Yes No — traffic appears in the attached subnets' flow logs
Block Storage Yes No
Autonomous Database / ATP Yes No — in-database auditing needs Data Safe
Oracle APEX Yes, via its ADB No — APEX_ACTIVITY_LOG lives in the database
Data Integration Yes Check your tenancy
Integration Service (OIC) Yes Check your tenancy

The README documents the Data Safe and UNIFIED_AUDIT_TRAIL routes for getting in-database visibility on ADB/ATP/APEX, which Audit alone cannot give you.

What's included

  • oci-logs.py — reads from Object Storage (checkpointed by object name) or Streaming (consumer groups, server-side offsets). Outputs to the analysisd socket, or to JSON lines for a <localfile> block when running on an agent. Auth via API key, instance principal or resource principal, so no private key need sit on disk. Handles gzip, JSON arrays and NDJSON, since Connector Hub has used all three.
  • ruleset/rules/oracle_cloud_oci_rules.xml — 35 rules in the free 112000-112099 range. No custom decoder needed; the events are JSON.
  • sample_logs.txt — 21 representative records, and --source local to replay them. The whole normalise-and-alert chain can be validated with wazuh-logtest before a tenancy is wired up.
  • README following the CONTRIBUTING template, config.example, systemd service + timer.

Two design notes worth reviewing

1. Normalised values are emitted twice — deliberately.

srcip, srcuser, action, status, url appear both at the top level and mirrored under oci.*. The top-level copies land on Wazuh's static decoder fields, which is what populates data.srcip in the alert and what <same_source_ip /> correlates on. But analysisd matches static fields with a plain strcmp for <action> and with OSMatch for <status> — neither supports the regex these rules need, and <field name="status"> is rejected outright because the name is reserved. The oci.* mirror is a dynamic field, where <field> gets full OS_Regex. New rules should match on oci.action / oci.status.

2. Rule 112019 gates the per-service rules on a successful call.

analysisd does not evaluate sibling rules in file order, so "was this operation denied?" cannot be settled by rule placement. Without the gate, a denied CreateUser fired 112005 "identity object modified" at level 10 — alerting that a user was created when the create was refused. Splitting success from failure on oci.status makes it order-independent.

Testing

Verified on Wazuh manager 4.14.7 (Ubuntu 22.04, aarch64, installed from packages.wazuh.com/4.x/apt):

  • Ruleset loads clean (wazuh-analysisd -t)
  • All 21 samples land on the expected rule and level under wazuh-logtest
  • Both ingestion paths alert end to end — analysisd socket (location: oci) and a file tailed by <localfile> (location: /var/ossec/logs/oci/oci.json)
  • All 5 frequency rules fire, including same_source_ip and same_field correlation
  • All 35 rules exercised — 25 fire directly from the samples, the other 10 are parents traversed on the way. None unreachable.

Not yet verified: the live Streaming and Object Storage code paths have not run against a real tenancy. OCI record shapes vary by service and region, and the service-log field names (bucketName, clientIp, responseTimeInMs) come from Oracle's documentation rather than captured data. The collector is defensive about this — it searches alias lists rather than assuming a single shape, and always preserves the original record under oci.data so a rule can reach any field even if the collector does not hoist it. Feedback from anyone with a tenancy is very welcome, and is called out in the README's support boundary.

Relationship to the existing OCI integrations

This is purely additive — it removes nothing and touches no existing integration. The repository already has two OCI entries; this adds a third rather than replacing either, and how they should be consolidated is a call for the maintainers, not for this PR.

Approach Ships rules? Dashboard?
Oracle_Cloud_Infrastructure_streaming/ (#55, @j0serca) Streaming via Logstash + Kafka Yes Yes
Oracle-Integration-(OCI)/ (#51, @fnxaw) Streaming via the OCI SDK No — one example rule in README prose No
oracle_cloud_oci/ (this PR) Object Storage or Streaming via the OCI SDK Yes — 35 rules Not yet

The collector here is new code rather than a modification of #51, though that PR established the consumer-group approach and is credited in the provenance block. Practical note: the rules file is named oracle_cloud_oci_rules.xml rather than oci_rules.xml, so it cannot overwrite the file shipped by #55 when both are installed to /var/ossec/etc/rules/.

If maintainers would prefer these consolidated, happy to follow up in a separate PR.

Checklist

  • Directory name is lowercase and underscore-separated
  • README follows the CONTRIBUTING template
  • Provenance and maintenance block included
  • Rule IDs in a free range (112000-112099, verified against the repo)
  • Ruleset loads on a real manager
  • Sample logs included

Wazuh has no native OCI module. This collects OCI logs via the path Oracle
supports -- Logging/Audit -> Connector Hub -> Streaming or Object Storage --
and forwards them to the Wazuh manager.

oci-logs.py reads from either delivery target, normalises the records, and
writes to the analysisd socket or to JSON lines for a <localfile> block. It
also replays a local file offline so the chain can be validated without a
tenancy. Auth supports API keys, instance principals and resource principals.

Audit covers the control plane for every OCI service, including the ones with
no data-plane log: DRG, Block Storage, Autonomous Database/ATP, APEX, Data
Integration and Integration Service. VCN flow logs, Object Storage access,
API Gateway access and Email Delivery arrive through the same connector.

Adds 35 rules in the 112000-112099 range. No custom decoder is needed; the
events are JSON. The rules file is named oracle_cloud_oci_rules.xml so it
cannot overwrite the oci_rules.xml shipped by the existing
Oracle_Cloud_Infrastructure_streaming integration once both are installed.

Normalised values are emitted twice, at the top level and mirrored under oci.*.
The top-level copies land on Wazuh's static decoder fields, which populate
data.srcip in the alert and drive same_source_ip correlation. But analysisd
matches static fields with strcmp for <action> and OSMatch for <status>, so
neither supports the regex the rules need, and <field name="status"> is
rejected because the name is reserved. The oci.* mirror is dynamic, where
<field> gets full OS_Regex. Rule 112019 gates the per-service rules on a
successful call, because analysisd does not evaluate siblings in file order and
a denied operation would otherwise be reported as a completed one.

Verified on Wazuh manager 4.14.7: the ruleset loads, all 21 samples land on the
expected rule and level under wazuh-logtest, both the analysisd socket and
<localfile> paths produce alerts end to end, and all five frequency rules fire
including same_source_ip and same_field correlation. All 35 rules are
exercised. The live Streaming and Object Storage paths have not run against a
real tenancy.

This is purely additive. It removes nothing and touches no existing
integration; how the three OCI integrations should relate is left to the
maintainers, and the README documents how they differ.
@allamiro
allamiro force-pushed the feat/oracle-cloud-oci-integration branch from 4c112d4 to 2d23b37 Compare August 6, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant