Forum Discussion
ARM template for deploying a workbook template to Microsoft Sentinel
- Dec 21, 2024
Hi Jason,
You are quite right. It's moving quite a long way from the original question but altering the Id string is all that is required to deploy an object to a different subscription.
In Azure, objects can clip together like Lego blocks based on the "provider" element. The Id string refences where something is deployed to and it tells Azure what type of object is being deployed (although most of the time that is also shown as the type property). You dont actually need the name property either - that's always the last element if the Id.
I'm familiar with the argument for deploying everything as code. These content templates are vesioned and are being updated constantly - it will be one headache to keep the versioning in your code templates up-to-date and if they go down the path of not allowing SOC engineers to create detection rules or update content through the portal it will be a tragedy. If your client also wants data connectors also deployed through code that becomes an almighty world of pain and also a security risk as your build pipeline has to be super-privileged with god rights in all systems.
From an Engineer's perspective, seeing Azure as REST objects is really helpful in understanding how it really works and there are still rare times when REST can get around issues with ARM. I use REST all the time as I'm troubleshooting in my sandpit but I still use Bicep (or ARM) when delivering solutions for customers as it's a standard solution that is officially supported by Microsoft. Once you have a JSON object you can find the type of object with Microsoft's https://learn.microsoft.com/en-us/azure/templates/microsoft.securityinsights/contenttemplates?pivots=deployment-language-bicep and it's almost a straight copy and paste of values against properties.
Absolutely it doesn't work!
I've been looking a bit more deeply into what these workbook "templates" are when displayed in Sentinel. They are "Content Templates"
https://learn.microsoft.com/en-us/rest/api/securityinsights/content-templates/list?view=rest-securityinsights-2024-09-01&tabs=HTTP
Creating your own set of content templates isn't well documented. It really deserves quite a long blog post - but I have been able to get a basic example working with REST.
I'm actually happy to get something working at all - so I'm sure refinement is needed. But this is the path you should be looking at...
{
"id": "/subscriptions/xxxxxxxx-xxxxxxxx-xxxxxxx-xxxxx/resourceGroups/xxxxxxxxxxxxxxxxxx/providers/Microsoft.OperationalInsights/workspaces/xxxxxxxxxxxxxx/providers/Microsoft.SecurityInsights/contenttemplates/LaurieTest",
"name": "LaurieTest",
"type": "Microsoft.SecurityInsights/contenttemplates",
"properties": {
"packageKind": "Standalone",
"packageId": "sentinel-LaurieTest",
"packageVersion": "1.0.0",
"contentSchemaVersion": "3.0.0",
"contentProductId": "LaurieTest",
"contentId": "sentinel-LaurieTest",
"displayName": "Laurie Test",
"contentKind": "Workbook",
"version": "1.0.0",
"source": {
"kind": "LocalWorkspace",
"name": "Standalone"
},
"author": {
"name": "Laurie Rhodes"
},
"support": {
"tier": "Community",
"name": "Laurie Rhodes",
"email": "email address removed for privacy reasons",
"link": "https://laurierhodes.info"
},
"MainTemplate": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0",
"parameters": {
"workspace": {
"type": "string",
"metadata": {
"description": "The name of the workspace where the workbook will be deployed"
}
}
},
"resources": [
{
"type": "Microsoft.Insights/workbooks",
"apiVersion": "2021-08-01",
"name": "[guid('sentinel-LaurieTest')]",
"location": "[resourceGroup().location]",
"kind": "shared",
"properties": {
"displayName": "Laurie Test Workbook",
"serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Welcome to the Test Workbook\\n---\\nThis is a test workbook to verify template deployment.\"},\"name\":\"text - 1\"},{\"type\":1,\"content\":{\"json\":\"### Sample Query Section\\nBelow is a basic query to verify data access:\"},\"name\":\"text - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityAlert\\n| summarize count() by AlertName\\n| top 10 by count_\",\"size\":0,\"timeContext\":{\"durationMs\":2592000000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"query - 1\"}],\"styleSettings\":{},\"defaultResourceIds\":[],\"fallbackResourceIds\":[],\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}",
"version": "1.0",
"sourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace'))]",
"category": "sentinel"
}
},
{
"type": "Microsoft.OperationalInsights/workspaces/providers/metadata",
"apiVersion": "2022-01-01-preview",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/Workbook-sentinel-LaurieTest')]",
"dependsOn": [
"[resourceId('Microsoft.Insights/workbooks', guid('sentinel-LaurieTest'))]"
],
"properties": {
"description": "Test of a community content template",
"parentId": "[resourceId('Microsoft.Insights/workbooks', guid('sentinel-LaurieTest'))]",
"contentId": "sentinel-LaurieTest",
"kind": "Workbook",
"version": "1.0.0",
"source": {
"kind": "Community",
"name": "Laurie Rhodes",
"sourceId": "sentinel-LaurieTest"
},
"author": {
"name": "Laurie Rhodes",
"email": "email address removed for privacy reasons"
},
"support": {
"tier": "Community",
"name": "Laurie Rhodes",
"email": "email address removed for privacy reasons",
"link": "https://laurierhodes.info"
}
}
}
]
}
}
}