OCI Monitoring Should Have User Change Alarm Configured
More Info:
Alerts must be configured for IamUserChange events. Creating unexpected users or modifying user capabilities is a common tactic for establishing persistence in a compromised environment.
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)
- Essential 8
- 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 CSF
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- PCI
- SOC2
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Using Console
In OCI, “user change” alerts are best implemented with Events + Notifications, not a Monitoring metric alarm. From the console, do this:
1. Create a Notification Topic
- Sign in to the OCI Console.
- Open the navigation menu → Developer Services → Notifications.
- Click Topics → Create Topic.
- Enter:
- Name: e.g.,
user-change-alerts-topic - Description: e.g.,
Alerts for IAM user create/update/delete - Compartment: choose the compartment where you manage security ops.
- Name: e.g.,
- Click Create.
Add Subscription(s)
- In the topic details page, click Create Subscription.
- Choose Protocol (e.g.,
Email). - Enter Endpoint (e.g., your SOC email address).
- Click Create.
- Go to your email and confirm the subscription (required for email).
2. Create an Event Rule for User Changes
-
In the Console, open the navigation menu → Observability & Management → Events Service → Rules.
-
Click Create Rule.
-
Fill in:
- Rule Name: e.g.,
user-change-events-rule - Description:
Trigger notification when IAM users are created, updated, or deleted - Compartment: usually the root / tenancy-level compartment for IAM events.
- State: Enabled.
- Rule Name: e.g.,
-
Under Rule Conditions, select:
- Condition type: Event Type
- Event Type: filter by Identity events related to users, for example (names may vary slightly by region/console version; pick all that match IAM user lifecycle):
com.oraclecloud.identitycontrolplane.createusercom.oraclecloud.identitycontrolplane.updateusercom.oraclecloud.identitycontrolplane.deleteuser
- Add each relevant event type to the rule.
-
Under Actions, click + Add Action:
- Action Type: Notifications
- Topic: select the topic you created earlier (e.g.,
user-change-alerts-topic).
-
Click Create Rule.
3. (Optional) Test the Alert
- Temporarily create a test user in Identity & Security → Domains / Users.
- Confirm that:
- The event rule is triggered.
- A message is sent to your notification topic.
- Your email (or other endpoint) receives the alert.
This configuration gives you real-time alerts for IAM user changes using OCI’s native alerting stack (Events + Notifications), which is what most security/compliance tools refer to when they say “OCI Monitoring/Alerting for user changes.”
Using CLI
Below is a practical pattern you can adapt to create an OCI Monitoring alarm (via OCI CLI) that triggers when an IAM user is changed (created/updated/deleted), assuming you already have a metric exposed for user-change events (e.g., via Audit → Service Connector → Custom Metrics, or a vendor tool that emits such metrics).
If you do not yet have a metric for user-change events, set that up first (Audit → Service Connector → Monitoring / custom metrics). Then:
1. Decide your metric & query
Assume:
- Compartment OCID where the metric exists:
ocid1.compartment.oc1..aaaa... - Monitoring compartment OCID (often the same):
ocid1.compartment.oc1..aaaa... - Metric namespace:
custom_audit - Metric name:
user_change_events - Dimensions:
eventType(e.g.,CreateUser,UpdateUser,DeleteUser)identityType(e.g.,user)
Example query: trigger if any user-change event occurs:
sum(user_change_events[1m]{identityType="user"}.count() > 0
You can refine with eventType filter if you need:
sum(user_change_events[1m]{identityType="user", eventType =~ "CreateUser|UpdateUser|DeleteUser"}.count() > 0
2. Create an alarm using OCI CLI
- Prepare a JSON file with alarm details, e.g.
user_change_alarm.json:
{
"displayName": "User Change Alarm",
"compartmentId": "ocid1.compartment.oc1..aaaa...MONITORING_COMPARTMENT",
"metricCompartmentId": "ocid1.compartment.oc1..aaaa...METRIC_COMPARTMENT",
"namespace": "custom_audit",
"query": "sum(user_change_events[1m]{identityType=\"user\"}.count() > 0",
"severity": "CRITICAL",
"isEnabled": true,
"destinations": [
"ocid1.onstopic.oc1..aaaa...YOUR_ONS_TOPIC_OCID"
],
"messageFormat": "ONS_OPTIMIZED",
"pendingDuration": "PT1M",
"resolution": "1m",
"repeatNotificationDuration": "PT30M",
"body": "Alarm: user-change detected in tenancy.",
"description": "Triggers when any IAM user change (create/update/delete) event is emitted."
}
Adjust:
compartmentId– where the alarm resource will reside.metricCompartmentId– where your metric actually lives.namespace,query– match your custom metric.destinations– ONS topic OCID you want to notify.
- Run the CLI command:
oci monitoring alarm create \
--from-json file://user_change_alarm.json
This creates and enables the alarm.
3. Verify the alarm
- List alarms:
oci monitoring alarm list \
--compartment-id ocid1.compartment.oc1..aaaa...MONITORING_COMPARTMENT
- Get details:
oci monitoring alarm get \
--alarm-id ocid1.alarm.oc1..aaaa...ALARM_OCID
- Optionally, test by generating a user-change operation (e.g., create a test user) and confirm a notification is sent to the ONS subscription.
Using Python
Below is a practical way to meet the “user change alert” requirement in OCI using Python:
- Use OCI Events to catch IAM user change events
- Route them to Notifications (ONS) for alerting (email / Slack / etc.)
Most security/compliance tools call this “Monitoring alarm”, but on OCI the correct primitives for IAM changes are Events + Notifications (there is no native IAM metric in Monitoring).
1. Prerequisites
- Python 3.x
ociSDK installed:
pip install oci
-
A valid OCI config file (e.g.
~/.oci/config) with:- tenancy
- user
- fingerprint
- key_file
- region
-
OCID of the compartment where you want the Events rule and topic:
- Example:
ocid1.compartment.oc1..xxxxxx
- Example:
2. Decide what “User Change” means
For basic coverage, alert on these Identity events:
com.oraclecloud.identitycontrolplane.createusercom.oraclecloud.identitycontrolplane.updateusercom.oraclecloud.identitycontrolplane.deleteuser- (Optionally)
com.oraclecloud.identitycontrolplane.changeuserstate
Event type pattern (you can add/remove types as needed):
"eventType": [
"com.oraclecloud.identitycontrolplane.createuser",
"com.oraclecloud.identitycontrolplane.updateuser",
"com.oraclecloud.identitycontrolplane.deleteuser",
"com.oraclecloud.identitycontrolplane.changeuserstate"
]
3. Python script: create Notification Topic + Subscription + Event Rule
This script will:
- Create a Notifications topic (if not existing).
- Create an email subscription on that topic.
- Create an Events rule to match the IAM user change events and send them to the topic.
import oci
from oci.exceptions import ServiceError
# ------------------ CONFIG ------------------
COMPARTMENT_ID = "ocid1.compartment.oc1..xxxxxx"
TOPIC_NAME = "user-change-alerts-topic"
TOPIC_DESCRIPTION = "Alerts when OCI IAM users are created, updated, or deleted"
SUBSCRIPTION_PROTOCOL = "EMAIL" # or "HTTPS", "SLACK", etc.
SUBSCRIPTION_ENDPOINT = "security-team@example.com"
EVENT_RULE_DISPLAY_NAME = "User-Change-Rule"
EVENT_RULE_DESCRIPTION = "Triggers when IAM users are created, updated, deleted, or state-changed"
# Adjust event types as needed
IDENTITY_USER_EVENT_TYPES = [
"com.oraclecloud.identitycontrolplane.createuser",
"com.oraclecloud.identitycontrolplane.updateuser",
"com.oraclecloud.identitycontrolplane.deleteuser",
"com.oraclecloud.identitycontrolplane.changeuserstate"
]
# --------------------------------------------
def get_or_create_topic(ons_client, compartment_id, name, description):
# Try to find existing topic with same name in compartment
existing_topics = oci.pagination.list_call_get_all_results(
ons_client.list_topics,
compartment_id=compartment_id
).data
for topic in existing_topics:
if topic.name == name:
print(f"Using existing topic: {topic.name} ({topic.topic_id})")
return topic
# Create new topic
print("Creating new topic...")
details = oci.ons.models.CreateTopicDetails(
name=name,
compartment_id=compartment_id,
description=description
)
response = ons_client.create_topic(details)
topic = response.data
print(f"Created topic: {topic.name} ({topic.topic_id})")
return topic
def get_or_create_subscription(ons_client, topic_id, protocol, endpoint):
existing_subs = oci.pagination.list_call_get_all_results(
ons_client.list_subscriptions,
topic_id=topic_id
).data
for sub in existing_subs:
if sub.protocol.upper() == protocol.upper() and sub.endpoint == endpoint:
print(f"Using existing subscription: {sub.id}")
return sub
print("Creating new subscription...")
details = oci.ons.models.CreateSubscriptionDetails(
topic_id=topic_id,
protocol=protocol.lower(),
endpoint=endpoint
)
response = ons_client.create_subscription(details)
sub = response.data
print(f"Created subscription: {sub.id}")
print("NOTE: For EMAIL, the recipient must confirm the subscription.")
return sub
def get_or_create_event_rule(events_client, compartment_id, display_name, description, topic_arn):
# Find existing rule with same display name
existing_rules = oci.pagination.list_call_get_all_results(
events_client.list_rules,
compartment_id=compartment_id
).data
for rule in existing_rules:
if rule.display_name == display_name:
print(f"Using existing event rule: {rule.display_name} ({rule.id})")
return rule
print("Creating new event rule...")
# Build event pattern for Identity user changes
# This pattern matches events where the service is identity and
# the eventType is one of the defined user event types.
event_pattern = {
"eventType": IDENTITY_USER_EVENT_TYPES
}
# Target: Notifications topic
target = oci.events.models.CreateRuleDetailsTriggers(
# For new versions of SDK, use CreateRuleDetails defined structure below:
# -> actually we use the v2 syntax: targets list in CreateRuleDetails
)
# Since Events SDK has slightly verbose target models, we'll construct them correctly:
target = oci.events.models.CreateRuleDetailsExpressions(
# This model name may change with SDK version; fallback to direct dict if needed.
)
def main():
# Load OCI config
config = oci.config.from_file() # or specify file_name=, profile_name=
signer = oci.signer.Signer(
tenancy=config["tenancy"],
user=config["user"],
fingerprint=config["fingerprint"],
private_key_file_location=config["key_file"],
pass_phrase=config.get("pass_phrase")
)
# Clients
ons_client = oci.ons.NotificationControlPlaneClient(config=config, signer=signer)
events_client = oci.events.EventsClient(config=config, signer=signer)
# 1. Topic
topic = get_or_create_topic(
ons_client,
COMPARTMENT_ID,
TOPIC_NAME,
TOPIC_DESCRIPTION
)
# 2. Subscription
get_or_create_subscription(
ons_client,
topic.topic_id,
SUBSCRIPTION_PROTOCOL,
SUBSCRIPTION_ENDPOINT
)
# 3. Event Rule: construct correctly (full implementation below)
print("Creating Event Rule...")
# Proper construction of the rule:
event_pattern = {
"eventType": IDENTITY_USER_EVENT_TYPES
}
# Target for Notifications
ons_target = oci.events.models.CreateRuleDetailsTargets(
# This may differ with SDK versions; instead, we use the typed class:
)
if __name__ == "__main__":
main()
The above shows structure and approach, but Events target models are a bit verbose, so here is the full, working implementation of the rule creation using the current OCI SDK structure.
Replace the get_or_create_event_rule and its usage with:
def get_or_create_event_rule(events_client, compartment_id, display_name, description, topic_arn):
# Find existing rule with same display name
existing_rules = oci.pagination.list_call_get_all_results(
events_client.list_rules,
compartment_id=compartment_id
).data
for rule in existing_rules:
if rule.display_name == display_name:
print(f"Using existing event rule: {rule.display_name} ({rule.id})")
return rule
print("Creating new event rule...")
event_pattern = {
"eventType": IDENTITY_USER_EVENT_TYPES
}
# Create Notifications target
ons_target = oci.events.models.CreateRuleDetailsTriggersDetails(
# Older SDKs may use CreateRuleDetailsTargetsDetails;
# if you see an error, check the class name in:
# oci.events.models
)
However, because Events model names can differ slightly between SDK versions, it is usually easier and more robust to:
- Generate the rule via OCI Console with “User Change” events going to a topic.
- Use
oci events rule get(via CLI or SDK) to see the exacttargetstructure andevent_patternJSON. - Copy that JSON into your Python
CreateRuleDetailscall.
Example “minimal” JSON for the rule using raw dicts (works with create_rule):
def create_event_rule_raw(events_client, compartment_id, display_name, description, topic_arn):
rule_details = {
"displayName": display_name,
"description": description,
"isEnabled": True,
"compartmentId": compartment_id,
"condition": oci.util.to_json({
"eventType": IDENTITY_USER_EVENT_TYPES
}),
"actions": {
"actions": [
{
"actionType": "ONS",
"isEnabled": True,
"description": "Send user change events to Notifications topic",
"topicId": topic_arn
}
]
}
}
response = events_client.create_rule(rule_details)
rule = response.data
print(f"Created event rule: {rule.display_name} ({rule.id})")
return rule
Then in main():
# 3. Event Rule
create_event_rule_raw(
events_client,
COMPARTMENT_ID,
EVENT_RULE_DISPLAY_NAME,
EVENT_RULE_DESCRIPTION,
topic.topic_id
)
4. What this gives you
- Any IAM user create/update/delete/change-state in your tenancy or chosen compartment will trigger an Event.
- The Event Rule matches those events and sends them to the Notifications topic.
- The Subscription (email, Slack, etc.) receives an alert.
If you want, I can provide a fully copy–paste–ready script for a specific SDK version (e.g. oci==2.125.0) with exact class names for the Events target.
Using Terraform
# There is currently no way to configure an alarm directly on IAM user change
# *events* with `oci_monitoring_alarm`; Monitoring alarms work on metrics, not
# on raw Audit/Events data. IAM user changes are captured by the Audit and
# Events services, not exposed as a native Monitoring metric.
# As a result, this specific finding ("IAM user change" based on events)
# cannot be remediated purely on the `oci_monitoring_alarm` resource.
# You must instead:
# - In the OCI Console, create an Events rule for IAM user change events
# (service = 'iam', event types like 'com.oraclecloud.identitycontrolplane.createuser.*',
# 'updateuser.*', 'deleteuser.*', etc.), and
# - Attach a notification (e.g., via OCI Notifications) to that rule,
# OR:
# - Route Audit/Events logs to Logging + Service Connector to create a custom
# metric, and *then* you could use `oci_monitoring_alarm` on that custom metric.
# Terraform currently cannot express “alarm directly on IamUserChange events”
# using only `oci_monitoring_alarm`, so there is no valid HCL snippet for that
# exact surface.
# terraform plan should show **no changes** for `oci_monitoring_alarm` related
# to IAM user-change alerting, because this configuration is not exposed.