Many organizations that work with Azure Sentinel find that the built-in ‘ticketing’ capabilities are rather lightweight. More often than not, they are already using an existing ITSM tool and want to use this tool to manage their Azure Sentinel incidents.
Within The Collective we had the same challenge. As we already used Jira Service Management, we wanted to have a bi-directional synchronization between Azure Sentinel and JIRA Service Management (Cloud). That’s why we embarked on a journey to create a custom ‘engine’ that keeps incidents in sync between Sentinel and JIRA. This solution, that is built entirely on Azure native components, does the following:
- Create an incident in JIRA whenever an incident is created in Sentinel
- Add a link to the JIRA incident in the Azure Sentinel incident
- Sync the assigned user from JIRA to Azure Sentinel
- Sync the status from JIRA to Azure Sentinel
- Sync public comments from JIRA to Azure Sentinel
Under the hood, the solution uses the following services and components:
- Azure Logic Apps
- Azure Functions
- Automation for JIRA
- Azure Sentinel Automation Rules
- Azure Key Vault
Complete documentation and the source code can be found on the official Azure Sentinel GitHub page.
This blog will focus on some key elements and things to look out for when building a solution like this.
The Automation Rules capability is a brand new feature within Azure Sentinel. This allows an administrator to add certain actions when an incident is created. With this, we can execute a Playbook each time an incident is created. Before this feature, it was only possible to trigger a Playbook based on an alert creation. But as an alert could contain multiple incidents, this can cause your ITSM tool to have multiple, duplicate incidents…
The beautiful part of Automation Rules is that it also works with Azure Lighthouse; you can specify Playbooks which exist in a different tenant too! This allows you to, for example, specify Playbooks in your Partner tenant when configuring Azure Sentinel in the tenant of your customer(s).
Sync Azure Sentinel changes to JIRA
You might have noticed from the chart above that updates from Azure Sentinel (such as closing incidents or commenting on incidents) are not synced to JIRA. This is because there is currently no way to create triggers when incidents in Azure Sentinel are updated. For this solution to work best, it is important that all changes are done inside of JIRA. This way, updates flow from JIRA to Azure Sentinel. If not, you would be creating a discrepancy between the data in JIRA and Azure Sentinel.
There is an open feature request to also enable triggers on incident updates in Azure Sentinel… Let’s hope it gets completed sooner rather than later.
A lot of the built-in Logic App connectors default to an OAuth connection. This means that the authentication is done with a ‘regular’ user account. But when that user account gets disabled or deleted, your Logic Apps stop working as they would be unable to authenticate anymore. That’s why our solution uses Service Principals for its authentication to Azure. Service Principals can be given privileges in a more flexible manner and are monitored with Azure Sentinel.
Using the right tools
The solutions uses four (4) different Logic Apps, and an Azure Function written in PowerShell. One might ask why we didn’t use Logic Apps for everything. This is done because we always try to find the right Azure service for the job.
Logic Apps are ideal for creating simple tools that don’t have a lot of complexity and can be built in a few small steps. Logic Apps offer the advantage that they are extremely easy to build as you add actions as building block, much like LEGO. This enables you to create simple Logic Apps that are really easy to troubleshoot. Because they offer a wide range of connectors, a lot of the API calls are simplified as the built-in connectors take care of authentication and API calls.
But Logic Apps are not always the answer. The comment synchronization is written in Powershell because we need to loop through the comments (which is an array) and select the comment with the latest Update Time. Although this is possible with custom expressions in Logic Apps too, it can quickly become quite complex. This is why we decided to add it in an Azure Function instead. The moment you need to use a few For Each-Loops and If- statements, you are often better of with Azure Functions in our opinion.
Built-in actions vs custom HTTP actions
Logic Apps offer a ton of built-in connectors, also for Azure Sentinel, JIRA and Azure AD.
Within this tool, the built-in connectors are not always used. Some connectors are not as good as others. The newest action for Sentinel is the ‘Update Incident’ action, it allows us to easily update existing incidents (changing the status/assigned user…). This is an example of a good connector!
However not all connectors are built that well. In the example below, the connector doesn’t allow you to define custom fields or dynamically set content, forcing us to move to a custom HTTP action calling the JIRA API instead.
The same applies to the Azure AD actions: there is a built-in action to retrieve an Azure AD user but this actions only supports OAuth delegated authentication and no service principal auth. This is why we are leveraging the Graph API with a custom HTTP action instead.
Built-in capabilities #FTW
The solution we discussed here is one of the many examples made possible by native Azure components and built-in features such as Logic Apps and Automation Rules. Automation Rules are absolutely something to consider, as they provide a lot more flexibility into automating actions in Azure Sentinel over what was previously available.
There’s many ways that lead to Rome. Whereas we’ve included quite a bit of custom scripts and coding, we felt that we had to because of our requirements. However, every environment is different and perhaps you’ll be able to make do without any of the custom work, just leveraging out-of-the-box features and connectors in Logic Apps.