Deploying Sentinel to multiple environments using Bicep in VS Code

Introduction

The aim of this article is describe the process of deploying Sentinel instances to multiple environments* in Azure using Bicep for Infrastructure as Code. We’ll walkthrough creating and onboarding the Sentinel instance as well as adding diagnostic settings to capture Sentinel Logs in a Log Analytics workspace.

*in this demo separate environments refers to different resource groups – but this could be applied at the subscription level if you so choose

Assumptions

  • An Azure Tenant
  • A User with Contributor permissions on the subscription we will be deploying Sentinel
  • Visual Studio Code with the Bicep extension installed
  • The az cli installed

The Project structure

  • security.bicep: The module file for Sentinel IaC configuration
  • main.bicep: The bicep entry point file where the module bicep files are run
  • {dev}/{test}/{prod}.bicepparam: a bicep parameter files – typically there is one file per environment being deployed to

security.bicep

This is a bicep module file where all the configuration for SIEM (Sentinel) is held. It also includes input parameters for dynamic settings that can be passed in from the main.bicep file.

//Parameters
@description('Specifies the location for all resources.')
@allowed([
  'uksouth'
])
param location string

@description('Specifies the SKU name for the workspace.')
@allowed([
  'PerGB2018'
  'Standard'
])
param skuName string = 'PerGB2018'

@description('Specifies the log retention in days.')
@minValue(30)
@maxValue(730)
param retentionInDays int = 90

@description('Log analytics workspace name')
param log_analytics_workspace_name string

@description('Sentinel diagnostic settings name')
param diagnostic_settings_name string

//Resources

//The log analytics workspace sentinel will sit on top of
resource law_workspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: log_analytics_workspace_name
  location: location
  properties: {
    sku: {
      name: skuName
    }
    retentionInDays: retentionInDays
  }
}

//The Sentinel instance
resource sentinel 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = {
  name: 'SecurityInsights(${log_analytics_workspace_name})'
  location: location
  properties: {
    workspaceResourceId: law_workspace.id
  }
  plan: {
    name: 'SecurityInsights(${log_analytics_workspace_name})'
       product: 'OMSGallery/SecurityInsights'
       promotionCode: ''
       publisher: 'Microsoft'
  }
}

//Onboarding the Sentinel instance to the log analytics workspace
resource onboarding_state 'Microsoft.SecurityInsights/onboardingStates@2023-02-01-preview' = {
  name: 'default'
  scope: law_workspace
}

//The Sentinel diagnostic settings to capture Sentinel activity in the Log analytics workspace
resource diagnosticsSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  scope: law_workspace
  name: diagnostic_settings_name
  properties: {
    workspaceId: law_workspace.id
    logs: [
      {
        categoryGroup: 'audit'
        enabled: true
      }
      {
        categoryGroup: 'allLogs'
        enabled: true
      }
    ]
    metrics: [
      {
        enabled:true
        category: 'AllMetrics'
      }
    ]
  }
}

//Output parameters to echo the state of the resources once built
output workspaceId string = law_workspace.id
output workspaceName string = law_workspace.name
output solutionId string = sentinel.id
output solutionName string = sentinel.name

*.bicepparams files

The environment specific variable values. Below is an example taken from the development environment dev.bicepparam file. The test.bicepparam and prod.bicepparam files will look the same albeit with environment specific values. Note the using reference to the main.bicep file – this tells the parameter file where to pass its values into when the main.bicep file is executed.

using '../main.bicep'

param location = 'uksouth'
param resource_group_name = 'rg-logging-dev-uks-01'
param log_analytics_workspace_name = 'sent-law-logging-dev-uks-01'
param diagnostic_settings_name = 'diagsetting-dev-uks-01'

main.bicep

This is the entry point file that the security.bicep (module) and *.bicepparam(s) files feed into. The main.bicep file is the file referenced when running the bicep script.

//As we are creating the resource group we run this at //Subscription scope level
targetScope = 'subscription'

//Parameters
param resource_group_name string

@description('law workspace name.')
param log_analytics_workspace_name string

@description('Specifies the location to deploy all resources')
@allowed([
  'uksouth'
])
param location string

@description('Specifies the SKU name for the log analytics workspace.')
@allowed([
  'PerGB2018'
  'Standard'
])
param skuName string = 'PerGB2018'

@description('Specifies the log retention in days')
@minValue(30)
@maxValue(730)
param retentionInDays int = 90

@description('Sentinel diagnostic settings name')
param diagnostic_settings_name string

//Resources
//Create resource group
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: resource_group_name
  location: location
}

//Run the security.bicep module to create the Sentinel //instance and associated support resources
module security 'security.bicep' = {
  scope: resourceGroup
  name: 'security'
  params: {
    retentionInDays: retentionInDays
    skuName: skuName
    location: location
    log_analytics_workspace_name: log_analytics_workspace_name
    diagnostic_settings_name: diagnostic_settings_name
  }
}

Building the resources – running the Bicep/IaC scripts

Now we can run the code to build the Sentinel instance. Before you can run the code within VS Code you will need to connect to your Azure tenant and select the correct Subscription. You can run the below command inside a terminal window to login to your Tenant and follow the instructions;

az login

Once you have logged into your tenant and selected the correct subscription you can run the below code to run the main.bicep file.

As a rule of thumb I always run the script first time around with the –what-if tag at the end of the command. This will initially build a report of what resources are going to be unmodified/updated/created when you run the script proper.

az deployment sub create -l uksouth --template-file .\src\main.bicep --parameters dev.bicepparam --what-if

Note the –parameters dev.bicepparam reference. This will initially build the Sentinel instance for the development environment. To build resources for the test and prod environments just swap the dev.bicepparam reference out for test.biceparam or prod.bicepparam respectively.

Once you are happy with the report output having previously applied the –what-if tag. run the build command to build the resources;

az deployment sub create -l uksouth --template-file .\src\main.bicep --parameters dev.bicepparam

Summary

We have been through the process of describing the file structure and configuration of Bicep files when building Azure Sentinel instances using IaC

We also described how to run the files on our local machine using VS Code and how to switch between parameter files when targeting specific deployment environments.

Going forward I will write a post on how to build the same IaC using Azure Devops for CI/CD

Thanks for reading and happy building!


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *