Skip to main content

OCI Monitoring Should Have Event Rule For Route Table

More Info:

Route table modifications must generate OCI Events. Unapproved routing changes can facilitate man-in-the-middle attacks or traffic exfiltration paths.

Risk Level

Medium

Address

Compliance, Security

Compliance Standards

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

Triage and Remediation

Remediation

Using Console

Below are concise, console-based steps to set up an OCI Events rule and alert for Route Table changes:


1. Prepare a Notification Channel (if you don’t already have one)

  1. In the OCI Console, open the Navigation menuDeveloper ServicesNotifications.
  2. Click Create topic.
    • Name: e.g., route-table-change-topic
    • Description: e.g., Alert on Route Table changes
  3. After creation, open the topic and click Create subscription.
    • Protocol: e.g., Email
    • Enter your email address.
  4. Confirm the subscription from the email you receive (must be done before alerts will be delivered).

2. Create an Events Rule for Route Table Changes

  1. Open the Navigation menuObservability & ManagementEvents ServiceRules.

  2. Click Create rule.

  3. Rule details

    • Name: e.g., route-table-change-rule
    • Description: Trigger on Route Table create/update/delete
    • Compartment: choose the compartment where your route tables reside.
  4. Condition (Event Pattern)

    • Under Event type, choose:
      • Service: Virtual Cloud Network (VCN) or Networking (name can vary slightly).
      • For Event Type, select the events related to route tables, such as:
        • Route Table - Create
        • Route Table - Update
        • Route Table - Delete
      • If only a generic filter is available, use the JSON pattern and ensure it includes something like:
        {
        "eventType": [
        "com.oraclecloud.virtualnetwork.createRouteTable",
        "com.oraclecloud.virtualnetwork.updateRouteTable",
        "com.oraclecloud.virtualnetwork.deleteRouteTable"
        ]
        }
    • Scope by Compartment and/or VCN if desired, to limit noise.
  5. Actions

    • In Actions, click Add actionNotifications.
    • Select the topic you created earlier (route-table-change-topic).
  6. Click Create rule.


3. (Optional) Test the Rule

  1. Make a controlled change to a Route Table:
    • NetworkingVirtual Cloud Networks → select VCN → Route Tables.
    • Edit a route table (e.g., add a test route) or create/delete a test route table.
  2. Wait a few minutes and verify that the email (or other channel) alert is received.

This completes setting up OCI Monitoring/Alerting for Route Table changes via the OCI console.

Using CLI

Below are step‑by‑step instructions to create an OCI Events rule (via OCI CLI) that alerts on any Route Table changes and sends notifications (e.g., email) using OCI Monitoring/Alerting.


0. Prerequisites

  1. OCI CLI installed and configured (oci setup config completed).
  2. You know:
    • Your compartment OCID (where VCN/route tables live).
    • An email address (for notifications).

1. Create a Notifications Topic (for alerts)

oci ons topic create \
--compartment-id "<COMPARTMENT_OCID>" \
--name "route-table-change-topic" \
--description "Alerting on route table changes"

Note the id from the output (this is the topic OCID), e.g.:

"data": {
"topic-id": "ocid1.onstopic.oc1...."
}

2. Create a Subscription to the Topic (email alert)

oci ons subscription create \
--compartment-id "<COMPARTMENT_OCID>" \
--topic-id "<TOPIC_OCID_FROM_STEP_1>" \
--protocol "EMAIL" \
--endpoint "you@example.com"

Check your email and confirm the subscription.


3. Create the Event Rule Actions JSON

Create a file route-table-rule-actions.json:

{
"actions": [
{
"actionType": "ONS",
"isEnabled": true,
"topicId": "ocid1.onstopic.oc1..xxxxxx"
}
]
}

Replace topicId with the OCID from step 1.


4. Create the Event Rule for Route Table Changes

Use the Events service rule to catch create/update/delete of Route Tables.

Known event types for VCN route tables:

  • com.oraclecloud.virtualnetwork.createroutetable
  • com.oraclecloud.virtualnetwork.updateroutetable
  • com.oraclecloud.virtualnetwork.deleteroutetable

Run:

oci events rule create \
--display-name "Detect Route Table Changes" \
--description "Triggers on create/update/delete of route tables" \
--compartment-id "<COMPARTMENT_OCID>" \
--is-enabled true \
--condition '{
"eventType": [
"com.oraclecloud.virtualnetwork.createroutetable",
"com.oraclecloud.virtualnetwork.updateroutetable",
"com.oraclecloud.virtualnetwork.deleteroutetable"
]
}' \
--actions file://route-table-rule-actions.json

Note the returned rule id for future management.


5. (Optional) Narrow Scope to Specific Compartment/VCN

If you want to restrict to a specific compartment or VCN, you can extend the --condition JSON. Example (filter by compartment):

oci events rule create \
--display-name "Detect Route Table Changes (Compartment Scoped)" \
--description "Triggers on route table changes in a specific compartment" \
--compartment-id "<COMPARTMENT_OCID>" \
--is-enabled true \
--condition '{
"eventType": [
"com.oraclecloud.virtualnetwork.createroutetable",
"com.oraclecloud.virtualnetwork.updateroutetable",
"com.oraclecloud.virtualnetwork.deleteroutetable"
],
"data": {
"compartmentId": [
"<COMPARTMENT_OCID>"
]
}
}' \
--actions file://route-table-rule-actions.json

6. Verify the Rule

List rules to confirm:

oci events rule list \
--compartment-id "<COMPARTMENT_OCID>"

You should see your Detect Route Table Changes rule in the output.


Once this is in place, any create/update/delete of a Route Table in that compartment will generate an Event, trigger the rule, and send a notification via the configured topic/subscription.

Using Python

Below is how to remediate this in OCI using Python: you’ll:

  1. Create (or reuse) a Notifications topic
  2. (Optionally) add an Email subscription
  3. Create an Events rule that triggers on Route Table changes and publishes to that topic

All via the OCI Python SDK.


1. Prerequisites

  • oci Python SDK installed:
    pip install oci
  • A working OCI config file (e.g. ~/.oci/config) with:
    • tenancy, user, fingerprint, key_file, region
  • Proper IAM permissions to:
    • Manage events-rules
    • Use ons-topics and ons-subscriptions
    • Read/inspect network resources

2. Event Filter for Route Table Changes

We want to match route table changes. For VCN Route Tables the eventType patterns are:

  • com.oraclecloud.virtualnetwork.createRouteTable
  • com.oraclecloud.virtualnetwork.updateRouteTable
  • com.oraclecloud.virtualnetwork.deleteRouteTable
  • (optional) com.oraclecloud.virtualnetwork.changeRouteTableCompartment

Filter pattern (Events rule) example:

{
"eventType": [
"com.oraclecloud.virtualnetwork.createRouteTable",
"com.oraclecloud.virtualnetwork.updateRouteTable",
"com.oraclecloud.virtualnetwork.deleteRouteTable",
"com.oraclecloud.virtualnetwork.changeRouteTableCompartment"
]
}

You can also restrict by compartmentId if needed:

{
"data": {
"compartmentId": ["<TARGET_COMPARTMENT_OCID>"]
},
"eventType": [
"com.oraclecloud.virtualnetwork.createRouteTable",
"com.oraclecloud.virtualnetwork.updateRouteTable",
"com.oraclecloud.virtualnetwork.deleteRouteTable",
"com.oraclecloud.virtualnetwork.changeRouteTableCompartment"
]
}

3. Python Script – Create Topic, Subscription, and Event Rule

Adjust uppercase placeholders and run.

import oci
import json
import time

# -----------------------------
# CONFIG
# -----------------------------
CONFIG_FILE = "~/.oci/config"
CONFIG_PROFILE = "DEFAULT"

COMPARTMENT_ID = "<COMPARTMENT_OCID_FOR_RULE_AND_TOPIC>"

TOPIC_NAME = "rt-change-alerts-topic"
TOPIC_DESCRIPTION = "Alerts for VCN route table changes"

SUBSCRIPTION_PROTOCOL = "EMAIL"
SUBSCRIPTION_ENDPOINT = "<ALERT_EMAIL_ADDRESS>" # e.g. "security-team@example.com"

EVENT_RULE_DISPLAY_NAME = "RouteTableChangeRule"
EVENT_RULE_DESCRIPTION = "Triggers when VCN route tables are created/updated/deleted"

# If you want to filter only specific compartment for the route tables:
FILTER_COMPARTMENT_ID = COMPARTMENT_ID # or another compartment OCID

# -----------------------------
# SETUP CLIENTS
# -----------------------------
config = oci.config.from_file(CONFIG_FILE, CONFIG_PROFILE)

ons_client = oci.ons.NotificationDataPlaneClient(config)
ons_mgmt_client = oci.ons.NotificationControlPlaneClient(config)
events_client = oci.events.EventsClient(config)

# -----------------------------
# 1. CREATE NOTIFICATION TOPIC
# -----------------------------
def create_topic_if_not_exists():
# Check existing topics
list_resp = ons_mgmt_client.list_topics(compartment_id=COMPARTMENT_ID)
for topic in list_resp.data:
if topic.name == TOPIC_NAME:
print(f"Using existing topic: {topic.name} ({topic.topic_id})")
return topic.topic_id

details = oci.ons.models.CreateTopicDetails(
name=TOPIC_NAME,
compartment_id=COMPARTMENT_ID,
description=TOPIC_DESCRIPTION,
)
resp = ons_mgmt_client.create_topic(details)
topic_id = resp.data.topic_id
print(f"Created topic: {TOPIC_NAME} ({topic_id})")
return topic_id

# -----------------------------
# 2. CREATE SUBSCRIPTION
# -----------------------------
def create_subscription_if_not_exists(topic_id):
list_resp = ons_mgmt_client.list_subscriptions(compartment_id=COMPARTMENT_ID)
for sub in list_resp.data:
if sub.topic_id == topic_id and sub.protocol == SUBSCRIPTION_PROTOCOL and sub.endpoint == SUBSCRIPTION_ENDPOINT:
print(f"Using existing subscription: {sub.id}")
return sub.id

details = oci.ons.models.CreateSubscriptionDetails(
compartment_id=COMPARTMENT_ID,
topic_id=topic_id,
protocol=SUBSCRIPTION_PROTOCOL.lower(), # "email"
endpoint=SUBSCRIPTION_ENDPOINT
)
resp = ons_mgmt_client.create_subscription(details)
sub_id = resp.data.id
print(f"Created subscription: {sub_id}")
print("NOTE: For EMAIL, you must confirm the subscription from the email.")
return sub_id

# -----------------------------
# 3. CREATE EVENTS RULE
# -----------------------------
def create_events_rule_if_not_exists(topic_id):
# Check existing rules
list_resp = events_client.list_rules(compartment_id=COMPARTMENT_ID)
for rule in list_resp.data:
if rule.display_name == EVENT_RULE_DISPLAY_NAME:
print(f"Using existing events rule: {rule.id}")
return rule.id

# Build the filter pattern
filter_pattern = {
"data": {
"compartmentId": [FILTER_COMPARTMENT_ID]
},
"eventType": [
"com.oraclecloud.virtualnetwork.createRouteTable",
"com.oraclecloud.virtualnetwork.updateRouteTable",
"com.oraclecloud.virtualnetwork.deleteRouteTable",
"com.oraclecloud.virtualnetwork.changeRouteTableCompartment"
]
}

# Action to publish to Notifications topic
action = oci.events.models.CreateStreamingServiceActionDetails( # placeholder? Actually for Notifications use CreateNotificationServiceActionDetails
)

We must correct: For events rule action to Notifications, OCI SDK uses CreateNotificationServiceActionDetails. Continue.

Let's complete script correctly.

# Action to publish to Notifications topic
action = oci.events.models.CreateNotificationServiceActionDetails(
action_type="ONS",
is_enabled=True,
description="Send alert to Notifications topic on route table changes",
topic_id=topic_id
)

details = oci.events.models.CreateRuleDetails(
compartment_id=COMPARTMENT_ID,
display_name=EVENT_RULE_DISPLAY_NAME,
description=EVENT_RULE_DESCRIPTION,
is_enabled=True,
condition=json.dumps(filter_pattern),
actions=oci.events.models.ActionList(
actions=[action]
)
)

resp = events_client.create_rule(details)
rule_id = resp.data.id
print(f"Created events rule: {rule_id}")
return rule_id

# -----------------------------
# MAIN
# -----------------------------
if __name__ == "__main__":
topic_id = create_topic_if_not_exists()
create_subscription_if_not_exists(topic_id)
create_events_rule_if_not_exists(topic_id)
print("Setup complete. Route table changes will trigger Notifications.")

4. Notes

  • For EMAIL subscriptions, the recipient must confirm via the link they receive before alerts start.
  • You can change the filter to be broader/narrower (remove compartmentId if you want all route tables in the tenancy).
  • To integrate with OCI Monitoring/Alarms instead of email, point the Notifications topic to your existing alerting pipeline or use a function that pushes to Monitoring metrics.
Using Terraform
# OCI Events rule to emit notifications on any Route Table change
resource "oci_events_rule" "route_table_changes" {
compartment_id = VAR_COMPARTMENT_OCID # replace with the OCID of the compartment containing the route tables
display_name = "route-table-change-events"
description = "Generate events for create/update/delete operations on OCI Route Tables"
is_enabled = true

# Event pattern for Route Table changes
condition = jsonencode({
"eventType" : [
"com.oraclecloud.virtualnetwork.createroutetable",
"com.oraclecloud.virtualnetwork.updateroutetable",
"com.oraclecloud.virtualnetwork.deleteroutetable"
],
"data" : {
"resourceType" : [
"RouteTable"
]
}
})

actions {
actions = [
{
# Send the event to an OCI Notifications topic, which Monitoring/Alerting can use
action_type = "ONS"
is_enabled = true
topic_id = VAR_NOTIFICATIONS_TOPIC_OCID # replace with an oci_ons_notification_topic OCID
}
]
}
}

Changing the condition or actions on oci_events_rule is in‑place and does not force replacement of the rule.

To verify, terraform plan should show either:

  • creation of oci_events_rule.route_table_changes with the above condition, or
  • an in‑place update of the existing oci_events_rule where only the condition (and possibly actions) arguments change to match this configuration.