Forwarding to Sentinel
Prerequisites
Event forwards originate from region-specific IPs. For the full list of outbound IPs by region, see SaaS Regions and IP Ranges. Update your firewall and allow inbound requests from these IP addresses to enable Sysdig to handle event forwarding.
To successfully integrate Sentinel with Sysdig’s event forwarding, you must have access to the Log Analytics Workspace that Sentinel uses. You need to configure the Logs Ingestion API in Azure Monitor so Sysdig can send data to Microsoft Sentinel. You can configure it through the Azure portal or CLI by following the steps below, or use a Terraform script for a more automated setup:
Create a Data Collection Endpoint to expose an HTTPS endpoint that Sysdig can send data to. Take note of the Logs Ingestion URI.
Create a custom DCR-based Log Analytics table to collect data received from Sysdig. Schema:
TimeGenerated(datetime)EventType(string)EventURL(string)RawEvent(dynamic)
Create a Data Collection Rule to define the DCE-to-Analytics pipeline:
- Select the DCE created in step 1.
- Define the stream with the same schema as the table in step 2 (used for both input and output). Take note of the name you give it.
- Set the Log Analytics table as the destination.
- Define a simple data flow that links the DCE, the destination table, and the input and output streams. Once created, take note of the Immutable ID.
Create an App Registration in Microsoft Entra, and note its Application ID.
For the App Registration, create Client secret credentials, and note the Secret value.
Allow the App Registration to send data to the Logs Ingestion endpoint. Open the DCR you created at step 3, go to Role Assignments and assign the “Monitoring Metrics Publisher” role to the App Registration created in step 4.
- Before running the Terraform script, run:
az login export ARM_SUBSCRIPTION_ID=<your-subscription-id> export ARM_TENANT_ID=<your-tenant-id> - Save the following script to a
.tffile.terraform { required_version = ">= 1.5.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 3.100" } azuread = { source = "hashicorp/azuread" version = "~> 2.50" } azapi = { source = "azure/azapi" version = "~> 1.13" } } } provider "azurerm" { features {} } provider "azuread" {} provider "azapi" {} # --------------------------------------------------------------------------- # Variables - Global # --------------------------------------------------------------------------- variable "location" { type = string default = "eastus" description = "Azure region for all resources." } variable "create_resource_group" { type = bool default = true description = "Set to false to reference an existing resource group instead of creating one." } variable "create_workspace" { type = bool default = true description = "Set to false to reference an existing Log Analytics workspace (with Sentinel already onboarded) instead of creating one." } variable "workspace_name" { type = string default = "sysdig-sentinel-workspace" description = "Name of the Log Analytics workspace. Created when create_workspace = true; referenced when false." } variable "resource_group_name" { type = string default = "sysdig_forwarding" description = "Name of the resource group. Created when create_resource_group = true; referenced when false." } # --------------------------------------------------------------------------- # Variables - Workspace to create # --------------------------------------------------------------------------- variable "workspace_sku" { type = string default = "PerGB2018" } variable "workspace_retention_days" { type = number default = 30 } variable "daily_quota_gb" { type = number default = -1 description = "Daily ingestion quota in GB. -1 means unlimited." } # --------------------------------------------------------------------------- # Variables - Optional # --------------------------------------------------------------------------- variable "app_display_name" { type = string default = "Sysdig Log Forwarder" description = "Display name for the Entra app registration created in the customer's tenant." } variable "secret_expiry_days" { type = number default = null description = "Lifetime of the client secret in days. Leave unset (null) for a non-expiring secret." } variable "dce_name" { type = string default = "sysdig-forwarding-dce" } variable "dcr_name" { type = string default = "sysdig-forwarding-dcr" } variable "custom_table_name" { type = string default = "SysdigEvents_CL" description = "Name of the custom DCR-based table. Must end in _CL." validation { condition = endswith(var.custom_table_name, "_CL") error_message = "Custom table names must end with '_CL'." } } variable "tags" { type = map(string) default = {} } # --------------------------------------------------------------------------- # Data sources # --------------------------------------------------------------------------- data "azurerm_client_config" "current" {} data "azurerm_resource_group" "rg" { count = var.create_resource_group ? 0 : 1 name = var.resource_group_name } data "azurerm_log_analytics_workspace" "la" { count = var.create_workspace ? 0 : 1 name = var.workspace_name resource_group_name = local.rg_name } # --------------------------------------------------------------------------- # Locals # --------------------------------------------------------------------------- locals { rg_name = var.create_resource_group ? azurerm_resource_group.rg[0].name : data.azurerm_resource_group.rg[0].name rg_location = var.create_resource_group ? azurerm_resource_group.rg[0].location : data.azurerm_resource_group.rg[0].location workspace_id = var.create_workspace ? azurerm_log_analytics_workspace.la[0].id : data.azurerm_log_analytics_workspace.la[0].id # Stream name used both in the DCR and as an output for the Go client. stream_name = "Custom-${var.custom_table_name}" } # --------------------------------------------------------------------------- # Resource group # --------------------------------------------------------------------------- resource "azurerm_resource_group" "rg" { count = var.create_resource_group ? 1 : 0 name = var.resource_group_name location = var.location tags = var.tags } # --------------------------------------------------------------------------- # Log Analytics Workspace # --------------------------------------------------------------------------- resource "azurerm_log_analytics_workspace" "la" { count = var.create_workspace ? 1 : 0 name = var.workspace_name location = local.rg_location resource_group_name = local.rg_name sku = var.workspace_sku retention_in_days = var.workspace_retention_days daily_quota_gb = var.daily_quota_gb tags = var.tags } # --------------------------------------------------------------------------- # Microsoft Sentinel onboarding # --------------------------------------------------------------------------- resource "azurerm_sentinel_log_analytics_workspace_onboarding" "sentinel" { count = var.create_workspace ? 1 : 0 workspace_id = azurerm_log_analytics_workspace.la[0].id } # --------------------------------------------------------------------------- # Data Collection Endpoint # --------------------------------------------------------------------------- resource "azurerm_monitor_data_collection_endpoint" "dce" { name = var.dce_name location = local.rg_location resource_group_name = local.rg_name kind = "Linux" public_network_access_enabled = true tags = var.tags } # --------------------------------------------------------------------------- # Custom DCR-based table (azapi — azurerm cannot create new _CL tables) # --------------------------------------------------------------------------- resource "azapi_resource" "custom_table" { type = "Microsoft.OperationalInsights/workspaces/tables@2022-10-01" name = var.custom_table_name parent_id = local.workspace_id body = jsonencode({ properties = { plan = "Analytics" schema = { name = var.custom_table_name columns = [ { name = "TimeGenerated", type = "datetime" }, { name = "EventType", type = "string" }, { name = "EventURL", type = "string" }, { name = "RawEvent", type = "dynamic" } ] } } }) depends_on = [azurerm_sentinel_log_analytics_workspace_onboarding.sentinel] } # --------------------------------------------------------------------------- # Data Collection Rule # --------------------------------------------------------------------------- resource "azurerm_monitor_data_collection_rule" "dcr" { name = var.dcr_name location = local.rg_location resource_group_name = local.rg_name data_collection_endpoint_id = azurerm_monitor_data_collection_endpoint.dce.id tags = var.tags # Stream columns mirror the table schema exactly — passthrough transform, no KQL manipulation. # The Go client must send JSON with these field names. stream_declaration { stream_name = local.stream_name column { name = "TimeGenerated" type = "datetime" } column { name = "EventType" type = "string" } column { name = "EventURL" type = "string" } column { name = "RawEvent" type = "dynamic" } } destinations { log_analytics { workspace_resource_id = local.workspace_id name = "la-destination" } } data_flow { streams = [local.stream_name] destinations = ["la-destination"] output_stream = local.stream_name transform_kql = "source" } depends_on = [azapi_resource.custom_table] } # --------------------------------------------------------------------------- # App Registration, Service Principal, and client secret # --------------------------------------------------------------------------- resource "azuread_application" "sysdig_forwarder" { display_name = var.app_display_name notes = "Owned by the customer; grants Sysdig SaaS write access to the Sentinel log ingestion pipeline." } resource "azuread_service_principal" "sysdig_forwarder" { client_id = azuread_application.sysdig_forwarder.client_id notes = "Service Principal for the Sysdig log forwarder (Sentinel Logs Ingestion API writer)" } resource "azuread_application_password" "sysdig_forwarder" { application_id = azuread_application.sysdig_forwarder.id display_name = "sysdig-forwarder-secret" end_date_relative = var.secret_expiry_days != null ? "${var.secret_expiry_days * 24}h" : null } # Least-privilege: scoped to this DCR only — not the workspace or subscription. resource "azurerm_role_assignment" "dcr_publisher" { scope = azurerm_monitor_data_collection_rule.dcr.id role_definition_name = "Monitoring Metrics Publisher" principal_id = azuread_service_principal.sysdig_forwarder.object_id } # --------------------------------------------------------------------------- # Outputs — everything the Sysdig SaaS connector config needs # --------------------------------------------------------------------------- output "tenant_id" { value = data.azurerm_client_config.current.tenant_id description = "Azure AD tenant ID." } output "subscription_id" { value = data.azurerm_client_config.current.subscription_id description = "Azure subscription ID." } output "data_collection_endpoint_logs_ingestion_uri" { value = azurerm_monitor_data_collection_endpoint.dce.logs_ingestion_endpoint description = "Base URI for the Logs Ingestion API (DCE endpoint)." } output "data_collection_rule_immutable_id" { value = azurerm_monitor_data_collection_rule.dcr.immutable_id description = "Immutable ID of the DCR — required in the ingestion request path." } output "stream_name" { value = local.stream_name description = "DCR stream name — required in the ingestion request path." } output "service_principal_object_id" { value = azuread_service_principal.sysdig_forwarder.object_id description = "Object ID of the Sysdig forwarder service principal in this tenant." } output "service_principal_application_id" { value = azuread_application.sysdig_forwarder.client_id description = "Client (application) ID of the Sysdig forwarder Entra app." } output "service_principal_client_secret" { value = azuread_application_password.sysdig_forwarder.value description = "Client secret for the Sysdig forwarder app. Store this securely — it is shown only once." sensitive = true } output "log_analytics_workspace_id" { value = local.workspace_id description = "Full resource ID of the Log Analytics workspace." } - In the script, set the Variables - Global values, or pass them as arguments (
-var variable=value). To create the workspace, set the Variables - Workspace to create values as well. The Variables - Optional values let you tweak the setup further; their defaults fit most cases. - Set up and apply the Terraform script:
terraform init terraform plan terraform apply - Collect the outputs; you need them to configure the integration later.
- Collect the client secret (
service_principal_client_secret). Treat it as a sensitive value.terraform output -raw service_principal_client_secret
Configure Standard Integration
Log in to Sysdig Secure as Admin and go to Integrations > Add Integrations.
Search and choose Microsoft Sentinel.
Configure the required options:
Integration Name: Define an integration name.
Tenant ID: Enter your Azure tenant ID (the Directory ID, available in the Azure portal) that hosts the Sentinel Log Analytics Workspace.
Data Collection Endpoint URI: Enter the Logs Ingestion URI for the DCE you configured in step 1.
Data Collection Rule ID: Enter the Immutable ID for the DCR you configured in step 3.
Stream name: Enter the stream name you configured for the DCR in step 3.
Service Principal App ID: Enter the Application ID for the App Registration you created in step 4.
Service Principal App Secret: Enter the secret you created in step 5.
Data to Send: Select from the drop-down the types of Sysdig data that should be forwarded to Sentinel. The available list depends on the Sysdig features and products you have enabled.
Toggle the enable switch as necessary. Remember that you need to select Test Integration before you enable the integration.
Select Save.
Configure Agent Local Forwarding
Review the configuration steps and use the following parameters for this integration.
| Type | Attribute | Required? | Type | Allowed values | Default | Description |
|---|---|---|---|---|---|---|
| SENTINEL | tenantId | yes | string | Azure Tenant ID hosting the Sentinel instance | ||
| SENTINEL | clientId | yes | string | App Registration ID | ||
| SENTINEL | clientSecret | yes | string | App Registration Client Secret | ||
| SENTINEL | dceUri | yes | string | DCE Logs Ingestion URI | ||
| SENTINEL | dceImmutableId | yes | string | DCE Immutable ID | ||
| SENTINEL | streamName | yes | string | Stream name in the DCR |