Programmatically enable Microsoft Sentinel solutions

Introduction

One last post for 2022!

Microsoft Sentinel has the Content Hub which, at the time this post was written, is still in preview. Inside the Content Hub are two types of entries: Solutions and Standalone contents.

Standalone contents are pretty new and are just single entities that can be enabled and be listed using the Microsoft Sentinel “contentpackages” REST API. Since these are pretty simple, I am not going to cover those here.

Solutions, on the other hand, can contain multiple items that get installed or enabled all at once. These do not use any Microsoft Sentinel REST API (at least not right now, maybe in the future?) so it is a bit more complicated to activate those using REST API calls.

I will say, that if you can use the UI to activate these, then that would be the preferred method. The UI has everything that you would need to do the install and will be updated automatically if the solution changes what it needs to deploy. As you will see below, even using the REST API, it will not be 100% automated as there is some manual steps that would be required before you can use the code to deploy.

Listing Solutions

As I mentioned before, the solutions do not use a Microsoft Sentinel REST API. In order to get a listing of the solutions, use the URL listed below. NOTE: You must use URL encoding as shown otherwise it will not work (and may or may not take you a while to figure out why the call isn’t working)

https://catalogapi.azure.com/offers?api-version=2018-08-01-beta&%24filter=categoryIds%2Fany%28cat%3A+cat+eq+%27AzureSentinelSolution%27%29+or+keywords%2Fany%28key%3A+contains%28key%2C%27f1de974b-f438-4719-b423-8bf704ba2aef%27%29%29

You use the standard code to login to Azure and setup your access like shown below:

Connect-AzAccount
$context = Get-AzContext
$profile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($profile)
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId)
$authHeader = @{
 'Content-Type'  = 'application/json' 
 'Authorization' = 'Bearer ' + $token.AccessToken }

The big difference is in the “Invoke-RestMethod” call that we would normally make to get our entries. With a Microsoft Sentinel REST API call we would add “.value” at the end of the call to filter out extraneous information. With this URL, we would add “.items” instead so the call would be:

 $results = (Invoke-RestMethod -Method "Get" -Uri $url -Headers $authHeader ).items

The information being returned is not in the usual format either. For example, there is no “properties” value anywhere. Instead, we care about “plans” and in that, “artifacts”. In particular we care about the “DefaultTemplate” entry’s “uri” field.

Getting the Solution’s requirements

Now that we have the listing of the solutions, let’s take a look at installing one. I am going to be using the “Log4j Vulnerability Detection” solution in this case. I found that the easiest way to get this particular solution is to use:

$solution = $results | Where-Object {$_.displayName -eq "Log4j Vulnerability Detection"}

We will be using the same format to get just the “DefaultTemplate” entry’s “uri”, namely:

 $uri = ($solution.plans.artifacts | Where-Object {$_.name -eq "DefaultTemplate"}).uri

As I mentioned in the introduction, there is a manual step required. This is it. You will need to paste the URI you just got into a new browser window. This will show the ARM template for the solution.

If you do not know the format for an ARM template, I suggest starting with this web page. It contains a good introduction to ARM templates.

Now we need to look at the ARM template to see what parameters are needed. You can also decide to override any of the ones that have a default value if you desire. Looking at this ARM template, you will see the following parameters are needed:

  • location
  • workspace-location
  • workspace
  • workbook1-name
  • workbook2-name
  • watchlist1-id

The entries in bold have defaults, so we will just use those. In this case, we need to determine the “workspace-location”, which is the region where the workspace is located, and the “workspace” which is the name of the workspace.

Making the call

We will be using the “New-AzResourceGroupDeployment” command. You could also use the respective Subscription, Tenant, or Management Group commands. For more information, look at this web page.

There are two different ways we can actually do the deployment since we have parameters to pass in.

  1. Pass the name of the needed parameters into the call directly
  2. Create a hash table and pass that in

Since the first one is pretty simple, we will use the second example.

Creating the hash table is pretty simple. For our example, we will assume the workspace is in the East US region and is call “gabazuresentinel”

$templateParameter = @{"workspace-location"="EastUS"; workspace="gabazuresentinel"}

We will then pass that into the “TemplateParameterObject” parameter when we make the call. So, the complete PowerShell call to install the “Log4j” solution will be:

New-AzResourceGroupDeployment -ResourceGroupName azuresentinel -TemplateUri "https://catalogartifact.azureedge.net/publicartifacts/azuresentinel.azure-sentinel-solution-apachelog4jvulnerability-1881b389-0405-450a-9440-512a6b4a36ed-azure-sentinel-solution-apachelog4jvulnerability/Artifacts/mainTemplate.json" -TemplateParameterObject $templateParameter

Pretty easy.

What about inside an ARM template

I know there are people who prefer to use an ARM template rather than PowerShell to create their environments. The good news is that you can easily call an ARM template (called a subtemplate) from within an ARM template. So, if I want to make the ARM call it would look like:

{
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-05-01",
      "name": "enableLog4j",
      "dependsOn": [
        "default"
      ],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "https://catalogartifact.azureedge.net/publicartifacts/azuresentinel.azure-sentinel-solution-apachelog4jvulnerability-1881b389-0405-450a-9440-512a6b4a36ed-azure-sentinel-solution-apachelog4jvulnerability/Artifacts/mainTemplate.json",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "workspace": {
            "value": "gabazuresentinel"
          },
          "workspace-location": {
            "value": "EastUS"
          }
        }
      },
      "condition": "Enter Conditions Here"
   }

Also pretty easy.

Summary

I’ve shown you how to get a listing of all the solutions that are available for you to use and then how to get the information needed to successfully deploy that solution using either PowerShell or an ARM template.

Keep in mind, that the entry I used was very basic. There are some very complex solutions out there so buyer beware!

Leave a Reply

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.