Upcoming May 2025 Microsoft 365 Champion Community Call
May 15, 2025Demystifying Azure Private Link: Benefits, Pitfalls & Best Practices
May 15, 2025As cyber threats become increasingly sophisticated, security teams must adopt scalable and repeatable practices to maintain a robust defense posture. Azure Sentinel, Microsoft’s cloud-native Security Information and Event Management (SIEM) and Security Orchestration Automated Response (SOAR) solution, offers powerful capabilities for threat detection and automated response. However, manually configuring Sentinel resources like data connectors, analytic rules, and workbooks can be error-prone and time-consuming.
This blog walks through a modern CI/CD implementation using Terraform and Azure DevOps to automate the deployment and management of Azure Sentinel resources. We’ll provision the infrastructure, deploy analytic rules, configure workbooks, and prepare a pipeline to enable continuous integration and delivery.
Prerequisites
- Azure Subscription with permissions to create resources.
- Azure DevOps or GitHub Actions account.
- Service Principal or Workload Identity Federation for authentication.
- Terraform >= v1.0.
- Basic understanding of Azure Sentinel components.
Architectural Diagram
- Infrastructure Provisioning with Terraform
1.1 Create Log Analytics Workspace and Enable Sentinel
provider “azurerm” {
features {}
}
resource “azurerm_resource_group” “sentinel_rg” {
name = “rg-sentinel-demo”
location = “East US”
}
resource “azurerm_log_analytics_workspace” “law” {
name = “law-sentinel-demo”
location = azurerm_resource_group.sentinel_rg.location
resource_group_name = azurerm_resource_group.sentinel_rg.name
sku = “PerGB2018”
retention_in_days = 30
}
resource “azurerm_sentinel_log_analytics_workspace_onboarding” “sentinel” {
log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id
}
- Deploying Analytic Rules
Create reusable modules or directly deploy rules using Terraform resources:
resource “azurerm_sentinel_alert_rule_scheduled” “sign_in_alert” {
name = “sign-in-failure-alert”
log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id
display_name = “Multiple Sign-in Failures”
query = <<QUERY
SigninLogs
| where ResultType == 50074
| summarize count() by bin(TimeGenerated, 5m), UserPrincipalName
QUERY
severity = "Medium"
tactics = ["InitialAccess"]
trigger_operator = "GreaterThan"
trigger_threshold = 5
frequency = "PT5M"
query_period = "PT5M"
enabled = true
}
- Enabling Data Connectors
Data connectors like AzureActivity or SecurityCenter can be enabled using Terraform ARM templates.
resource “azurerm_template_deployment” “enable_connector” {
name = “Enable-AzureActivity-Connector”
resource_group_name = azurerm_resource_group.sentinel_rg.name
deployment_mode = “Incremental”
template_body = file(“connectors/azure_activity_connector.json”)
parameters = {
workspaceId = {
value = azurerm_log_analytics_workspace.law.id
}
}
}
- Deploying Workbooks
Workbooks are typically deployed using exported ARM templates. You can manage them in source control and deploy via Terraform.
resource “azurerm_template_deployment” “workbook” {
name = “Deploy-Sentinel-Workbook”
resource_group_name = azurerm_resource_group.sentinel_rg.name
deployment_mode = “Incremental”
template_body = file(“workbooks/sample_workbook.json”)
parameters = {
workbookName = { value = “SignInWorkbook” }
location = { value = azurerm_log_analytics_workspace.law.location }
}
}
- CI/CD Pipeline with Azure DevOps
5.1 Folder Structure
project-root/
├── connectors/
├── workbooks/
├── rules/
├── terraform/
│ ├── main.tf
│ ├── variables.tf
│ └── backend.tf
├── pipelines/
│ └── azure-pipeline.yml
5.2 Azure DevOps Pipeline Definition
trigger:
branches:
include:
– main
pool:
vmImage: ‘ubuntu-latest’
variables:
TF_VERSION: ‘1.6.0’
steps:
– task: UseTerraform@0
inputs:
command: ‘install’
terraformVersion: $(TF_VERSION)
– checkout: self
– task: TerraformTaskV4@4
displayName: ‘Terraform Init’
inputs:
provider: ‘azurerm’
command: ‘init’
backendServiceArm: ‘azure-connection’
backendAzureRmResourceGroupName: ‘rg-tfstate’
backendAzureRmStorageAccountName: ‘tfstatestorage’
backendAzureRmContainerName: ‘tfstate’
backendAzureRmKey: ‘sentinel.terraform.tfstate’
workingDirectory: ‘$(System.DefaultWorkingDirectory)/terraform’
– task: TerraformTaskV4@4
displayName: ‘Terraform Plan’
inputs:
provider: ‘azurerm’
command: ‘plan’
environmentServiceNameAzureRM: ‘azure-connection’
workingDirectory: ‘$(System.DefaultWorkingDirectory)/terraform’
– task: TerraformTaskV4@4
displayName: ‘Terraform Apply’
inputs:
provider: ‘azurerm’
command: ‘apply’
environmentServiceNameAzureRM: ‘azure-connection’
workingDirectory: ‘$(System.DefaultWorkingDirectory)/terraform’
args: ‘-auto-approve’
- Best Practices
- Use Modules: Create reusable modules for common Sentinel configurations.
- State Management: Store the Terraform state securely in Azure Storage with locking.
- Secret Management: Use Azure Key Vault or Workload Identity Federation to avoid storing secrets in pipeline code.
- Version Control: Keep ARM templates, KQL queries, and rule configurations in source control.
- Testing: Use terraform validate and automated tests to check for issues before deploying.
Conclusion
CI/CD automation for Azure Sentinel significantly enhances your security posture by enabling consistent, auditable, and scalable deployments. By leveraging Terraform and Azure DevOps, security teams can manage infrastructure, deploy rules, onboard connectors, and configure workbooks with confidence and speed.
This implementation paves the way for future enhancements like deploying playbooks (Logic Apps), integrating with Defender for Cloud, and enabling Sentinel-as-Code using Azure Verified Modules.