Configuring cloud detection and response for IBM Cloud
Enable cloud detection and response (CDR) for IBM Cloud to investigate suspicious activity in your cloud accounts in near real-time. Workload Protection ingests and analyzes IBM Cloud audit logs to detect potential threats.
The Workload Protection detection and response module supports IBM Cloud, multi-cloud environments (Amazon Web Services, Azure and Google Cloud), inside hosts, virtual machines (VSIs for VPC, VMware, PowerVS and IBM Z with Linux), Kubernetes, and OpenShift.
CDR monitors cloud workloads and activity in real time, detects threats using curated rules and behavioral techniques to identify a broad range of attacks such as privilege escalation and lateral movement.
With CDR, organizations can detect and respond to threats faster, reducing the impact of security incidents and minimizing downtime.
After you complete the enablement of detection and response for your IBM Cloud account, see Creating IBM Cloud Threat Detection policy to define the detections you want for you environment.
IBM Cloud Detection and Response Architecture
The CDR integration for IBM Cloud uses the following data flow:
-
Users and applications generate audit events with the actions in the IBM Cloud account. All creation, removals or updates are recorded and tracked.
-
Activity Tracker Event Routing captures audit events generated across your IBM Cloud account and routes them to a IBM Cloud Object Storage bucket through a configured target and route.
-
IBM Cloud Object Storage stores the auditing events from Activity Tracker Event Routing. A IBM Cloud Object Storage event subscription monitors the bucket and triggers a Code Engine application each time a new event file is written.
-
Code Engine runs the CDR notification application, which reads the event files from the Object Storage bucket using a trusted profile for authentication, and forwards the events to the Workload Protection ingestion endpoint.
-
Workload Protection receives and analyzes the forwarded events in near real-time, applying detection rules to identify threats such as privilege escalation, lateral movement, and suspicious API activity.
The connection between components is secured using two IAM objects: a trusted profile, which grants the Workload Protection instance identity access to read from the Object Storage bucket; and a Service ID with an API key, which authenticates the Code Engine application when forwarding events to the Workload Protection ingestion endpoint.
Prerequisites
Before you begin, ensure the following services and permissions are available in your IBM Cloud account.
- An existing Workload Protection instance and its CRN. It will be referenced later as
<workload-protection-instance-crn>. For more information, see Setting up Workload Protection. - Your Workload Protection must have CSPM enabled for your IBM Cloud account. For more information, see Implementing CSPM for IBM Cloud
- Permissions to manage the following services in your IBM Cloud account:
- Activity Tracker Event Routing: Editor or Administrator platform role.
- IBM Cloud Object Storage: Manager service role on the instance.
- IAM Identity (account management): Administrator role to create Service IDs, API keys, and Trusted Profiles.
- IAM Access Management (account management): Administrator role to create IAM policies and service-to-service authorizations.
- Code Engine: Editor or Manager service role.
- Container Registry: Reader service role — required for Code Engine to pull the CDR application image.
- Workload Protection: Editor or Administrator platform role on the instance.
Set up Activity Tracker Event Routing integration
The workflow sends auditing events from Activity Tracker Event Routing to Object Storage, which triggers a Code Engine application to forward events to Workload Protection for ingestion and analysis.
Configure a IBM Cloud Object Storage target
IBM Cloud Object Storage is used as target for Activity Tracker Event Routing events. Those events will be later collected by Workload Protection to analyze potential suspicious activity.
Follow the instructions for Configuring a Cloud Object Storage target.
After configuring the target, save the following values that will be used in later steps:
-
The Object Storage instance name. It will be referenced as
<your_cos_instance_name>. -
The Object Storage bucket name. It will be referenced as
<cos_bucket_name>. -
The Object Storage bucket region. It will be referenced as
<cos_bucket_region>.When you configure the Activity Tracker Event Routing route, ensure that the route rule includes the
globallocation in addition to your deployment region. IAM events such as account settings changes, MFA modifications, policy deletions, and context-based restriction changes are generated as global events and are not routed unlessglobalis explicitly included.Without the
globallocation, IAM mutation events will not reach the Object Storage bucket and will not be analyzed by Workload Protection.
Create a Service ID and API Key
Create the Service ID and one API key for the Code Engine application to send events to your Workload Protection instance.
ibmcloud iam service-id-create send-cdr-events-id --description "Service ID for CDR event forwarding"
ibmcloud iam service-api-key-create send-cdr-events-key send-cdr-events-id --description "API Key for CDR app"
Save the generated API key and the Service ID identifier (the ServiceId-xxx value returned by the first command). Both will be used in the following steps.
Grant the Service ID Reader access to the IBM Cloud® Container Registry so that Code Engine can pull the CDR application image:
ibmcloud iam service-policy-create send-cdr-events-id --roles Reader --service-name container-registry
Create the trusted profile for reading Object Storage events
Create the trusted profile (you can modify the name). Save the ID to be used later. It will be referenced later as <trusted_profile_id>:
ibmcloud iam trusted-profile-create ibmcdr-wp-cos --description "Trusted profile for Workload Protection interaction with Cloud Object Storage bucket"
Assign the trust relationship for the Workload Protection instance. Replace <workload-protection-instance-crn> with your Workload Protection CRN:
ibmcloud iam trusted-profile-identity-create ibmcdr-wp-cos --id <workload-protection-instance-crn> --id-type CRN
Assign the trust relationship for the Service ID created in step 2. Replace <service_id> with the Service ID identifier (ServiceId-xxx):
ibmcloud iam trusted-profile-identity-create ibmcdr-wp-cos --id <service_id> --id-type serviceid
Create the policy for the trusted profile for the IBM Cloud Object Storage reader. Replace <cos_bucket_name> with the bucket name created in the step 1:
ibmcloud iam trusted-profile-policy-create ibmcdr-wp-cos -r "Content Reader,Reader" --service-name cloud-object-storage --resource-type bucket --resource <cos_bucket_name>
Create the policy for the trusted profile for accessing the CDR Service ID. Replace <service_id> with the Service ID created in step 2:
ibmcloud iam trusted-profile-policy-create ibmcdr-wp-cos -r Viewer --service-name iam-identity --resource-type serviceid --resource <service_id>
Create Code Engine Project and Secrets
Create a secret in Code Engine to inject the api key securely.
Create your Code Engine Project:
ibmcloud ce project create --name <code_engine_project>
Create the Secret for the application (it will be used as variable). Replace <your_api_key> with the key generated in the previous step:
ibmcloud ce secret create --name cdr-secrets --from-literal API_KEY=<your_api_key>
Create the Secret for pulling images from Container Registry. Replace <your_api_key> with the key generated in the previous step:
ibmcloud ce secret create --name icr-secret --format registry --server icr.io --username iamapikey --password <your_api_key> --email noreply@cdr-app.ibm.cloud
Create Code Engine App
Make sure to replace the following variables in the command:
<target_account_id>with the IBM Cloud account ID.<trusted_profile_id>with the trusted profile created in step 3.<environment_url>with the Workload Protection endpoint for your region. For example, if your instance is in Dallas, replace<environment_url>withus-south.security-compliance-secure.cloud.ibm.com.<service_id>with the Service ID created in step 2.
ibmcloud ce application create \
--name "sccwp-cdr-app" \
--image icr.io/ext/sysdig/cdr-notification-app:latest \
--min-scale 1 \
--max-scale 10 \
--cpu 0.125 \
--memory 500M \
--request-timeout 60 \
--service-account default \
--env TARGET_ACCOUNT_ID=<target_account_id> \
--env TRUSTED_PROFILE_ID=<trusted_profile_id> \
--env FORWARD_URL="https://<environment_url>/api/cloudingestion/webhooks/ibm/v1/<service_id>" \
--env API_KEY=cdr-secrets:API_KEY \
--registry-secret icr-secret
The following table describes the key parameters used in the command:
| Parameter | Description |
|---|---|
--name |
Name of the Code Engine application. |
--image |
The CDR notification application image hosted in IBM Cloud Container Registry. It should always be icr.io/ext/sysdig/cdr-notification-app:latest |
--min-scale |
Minimum number of running instances. Set to 1 to ensure the app is always ready to receive Object Storage events. |
--max-scale |
Maximum number of instances the app can scale up to under load. |
--cpu / --memory |
Compute resources allocated per instance. |
--request-timeout |
Maximum time in seconds the app has to process an incoming request before it times out. |
TARGET_ACCOUNT_ID |
The IBM Cloud account ID whose auditing events are being forwarded via Activity Tracker Event Routing. |
TRUSTED_PROFILE_ID |
The trusted trofile ID created in step 3, used by the app to authenticate against Object Storage without long-lived credentials. |
FORWARD_URL |
The Workload Protection ingestion endpoint URL, including the Service ID as the identity token. |
--env-from-secret cdr-secrets |
Injects the Service ID API key into the app as an environment variable from the Code Engine secret created in step 4. |
--registry-secret icr-secret |
Registry credentials allowing Code Engine to pull the application image from IBM Cloud Container Registry. |
Connect IBM Cloud Object Storage Bucket to Code Engine
Set up an event subscription to connect Object Storage bucket events to Code Engine.
Grant Permissions to ensure Code Engine can manage notifications on the Object Storage instance. Replace <code_engine_project> with the Code Engine project created in step 4 and <your_cos_instance_name> with the IBM Cloud Object Storage instance name created in step 1:
ibmcloud iam authorization-policy-create codeengine cloud-object-storage "Notifications Manager" --source-service-instance-name <code_engine_project> --target-service-instance-name <your_cos_instance_name>
Create Subscription to ensure every time Activity Tracker Event Routing archives a log file to the bucket, the application is triggered. Replace <cos_bucket_name> with the bucket name from step 1:
ibmcloud ce subscription cos create --name cdr-cos-sub \
--bucket <cos_bucket_name> \
--destination sccwp-cdr-app \
--event-type write
Enable CDR for your account in Workload Protection
Make sure to replace the following variables in the command:
<wp_instance_name>with your Workload Protection instance name or GUID. Using the GUID is recommended to avoid ambiguity if multiple instances share the same name.<cos_bucket_region>with the region of the Object Storage bucket created in step 1.<cos_bucket_name>with the Object Storage bucket name created in step 1.<trusted_profile_id>with the trusted profile ID saved in step 3.<environment_url>with the Workload Protection endpoint for your region.<service_id>with the Service ID identifier (theServiceId-xxxvalue) from step 2.<target_account_id>with the IBM Cloud account ID.
ibmcloud resource service-instance-update "<wp_instance_name>" -p '{"enable_cdr": true, "target_cdr_accounts": [{"cdr_bucket_region": "<cos_bucket_region>","cdr_bucket_name": "<cos_bucket_name>","cdr_trusted_profile_id": "<trusted_profile_id>","cdr_service_id": "<service_id>", "cdr_ingestion_url": "https://<environment_url>/api/cloudingestion/webhooks/ibm/v1/<service_id>", "account_id":"<target_account_id>"}]}' -g Default
If you have any error, review Why is my IBM Cloud account not ingested audit events
Creating IBM Cloud Threat Detection policy
You can create a new threat detection policy to detect and respond to suspicious activity in your IBM Cloud environments. Policies specify where to apply rules and how to respond to security violations, such as sending notifications to Slack, Microsoft Teams, email, or an incident management tool.
To create a threat detection policy, follow these steps:
Create the threat detection rules
Copy the following content and paste it under Custom Rules under Policies > Detection & Response Policies > Rules Editor and click on Save.
- required_engine_version: 51
- rule: IBM Cloud IAM Policy Deleted
desc: >
Detects successful deletion of an IAM access policy. Removing policies
weakens authorization controls and may indicate an attacker impairing
defenses. Filters to outcome=success since failed deletions do not
change security posture.
condition: >
jevt.value[/action] = "iam-am.policy.delete"
and jevt.value[/outcome] = "success"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
IAM policy %ibm.target.name was deleted by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: WARNING
source: ibm_activitytracker
tags: [ibm, iam, defense-evasion, T1562.001]
- rule: IBM Cloud IAM Service ID Deleted
desc: >
Detects successful deletion of an IAM service ID. Removing a service ID
destroys a non-human identity along with its associated policies and API
keys, denying access to any workloads or users that depended on it.
Filters to outcome=success since failed deletions do not change security
posture.
condition: >
jevt.value[/action] = "iam-identity.account-serviceid.delete"
and jevt.value[/outcome] = "success"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
Service ID %ibm.target.name was deleted by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: NOTICE
source: ibm_activitytracker
tags: [ibm, iam, impact, T1531]
- rule: IBM Cloud IAM Service ID API Key Created
desc: >
Detects creation of an API key on a service ID. Service ID API keys
are a persistence technique -- they are stealthier than user API keys
since service IDs typically receive less scrutiny.
condition: >
jevt.value[/action] = "iam-identity.serviceid-apikey.create"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
An API key %ibm.target.name was created by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: WARNING
source: ibm_activitytracker
tags: [ibm, iam, persistence, T1098.001]
- rule: IBM Cloud IAM User API Key Created
desc: >
Detects creation of a user API key. User API keys grant persistent
access that survives session expiration, making them a common
persistence mechanism for maintaining access to IBM Cloud.
condition: >
jevt.value[/action] = "iam-identity.user-apikey.create"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
A user API key %ibm.target.name was created by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: WARNING
source: ibm_activitytracker
tags: [ibm, iam, persistence, T1098.001]
- rule: IBM Cloud IAM Service ID Created
desc: >
Detects creation of a new IAM service ID. Service IDs are non-human
identities that can hold their own policies and API keys. Creating
one establishes a new identity that can be used for persistent access.
condition: >
jevt.value[/action] = "iam-identity.account-serviceid.create"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
Service ID %ibm.target.name was created by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: NOTICE
source: ibm_activitytracker
tags: [ibm, iam, persistence, T1136.003]
- rule: IBM Cloud IAM Account Settings Updated
desc: >
Detects updates to IAM account-wide security settings. These settings
control MFA policy, session lifetimes, IP restrictions, and allowed
authentication methods for the entire account. Changes weaken the
security posture for every identity in the account.
condition: >
jevt.value[/action] = "iam-identity.account-settings.update"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
IAM account settings were updated by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: WARNING
source: ibm_activitytracker
tags: [ibm, iam, defense-evasion, T1562]
- rule: IBM Cloud IAM Access Group Settings Updated
desc: >
Detects updates to IAM access group settings. These settings control
who can create access groups and whether groups can be made public.
Loosening these restrictions enables broader group membership or
unauthorized group creation, expanding access beyond intended scope.
condition: >
jevt.value[/action] = "iam-groups.account-settings.update"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
IAM access group settings were updated by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: NOTICE
source: ibm_activitytracker
tags: [ibm, iam, persistence, T1098]
- rule: IBM Cloud IAM User API Key Deleted
desc: >
Detects deletion of a user API key. Deleting API keys used during
an attack removes evidence of the credential that was used. Pairs
with the User API Key Created rule to track the full lifecycle of
user credentials.
condition: >
jevt.value[/action] = "iam-identity.user-apikey.delete"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
A user API key was deleted by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: NOTICE
source: ibm_activitytracker
tags: [ibm, iam, defense-evasion, T1070]
- rule: IBM Cloud User Removed
desc: >
Detects removal of a user from the IBM Cloud account. Removing a
user locks out defenders and legitimate admins. This is irreversible
without re-inviting the user. Denies access to legitimate responders
during an incident.
condition: >
jevt.value[/action] = "user-management.user.delete"
and jevt.value[/outcome] = "success"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
A user was removed from the account by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: WARNING
source: ibm_activitytracker
tags: [ibm, user-management, defense-evasion, T1531]
- rule: IBM Cloud User Settings Updated
desc: >
Detects updates to individual user settings. These settings control
a user's IP restrictions and allowed authentication methods. Changing
them weakens security controls at the individual user level, enabling
access from previously restricted locations or methods.
condition: >
jevt.value[/action] = "user-management.user.update"
and jevt.value[/outcome] = "success"
exceptions:
- name: user_action
fields: ["ibm.initiator.id", "ibm.action"]
- name: user_account
fields: ["ibm.initiator.id", "ibm.accountId"]
- name: user_target
fields: ["ibm.initiator.id", "ibm.target.id"]
- name: user_action_contains
fields: ["ibm.initiator.id", "ibm.action"]
comps: [contains, "="]
output: >
User settings were updated by %ibm.initiator.name
(user=%ibm.initiator.name,
user_id=%ibm.initiator.id,
credential=%ibm.initiator.credential.type,
source_ip=%ibm.initiator.host.address,
target=%ibm.target.name,
target_id=%ibm.target.id,
action=%ibm.action,
outcome=%ibm.outcome,
message=%ibm.message,
account=%ibm.accountId,
region=%ibm.region)
priority: NOTICE
source: ibm_activitytracker
tags: [ibm, user-management, defense-evasion, T1562]
These rules are examples for detecting suspicious activity and poor security hygiene targeting Cloud Identity and Access Management.
Find all the rule references and details in Reference Library for IBM Cloud CDR Threat Detection Rules
Create and enable the threat detection policy
Go to Policies > Detection & Response Policies > Runtime Policies and click on Add Policy. Select the IBM Activity Tracker policy.
Choose the rules you want to use by clicking on Managed & Import under Policy Rules.
Define Actions to be taken if the policy rules are breached, such as Notify an email or Slack channel. The notification channel needs to be created before this step.
Enable and save the policy.