Query Azure Security Security Recommendation by different ways

If you work with Azure Security Center you probably know about Azure Security Center Recommendation that periodically analyzes security state of Azure resources. In the past Azure Security Center Recommendation was executed by private Azure back-end service internally. Microsoft then made it more configurable by moving it to be integrated with Azure Policy. In a nutshell, Azure Policy does the job of scanning Azure resources and feed results to Recommendation page.

In this article, let’s explore different ways to get recommendation state from Azure Security Center. You will learn not only Azure Security Center API, but also Kusto Query Language as well as Continuous Export.

As a SecOps engineer you may receive a request from your customer or manager on security posture in your Azure environment. For example, get all virtual machines that Azure Security Center audits missing critical and security update, especially when there is a critical CVE like CVE-2020-0601 that require immediate patching action on your Azure cloud environment. The recommendation name is “System updates on virtual machine should be installed“. The report that you are going to send to your manager or customer should show the list of virtual machines under that recommendation.

Built-in Export to CSV feature

You can export Azure Security Center Recommendation to a CVS file using built-in export feature.

Azure Security Center API

First of first, to interact with Azure you should think about Azure REST API first. Not all services in which API is available for use but you can do the check. Specific to Azure Security Center API there is one here. For recommendation the one the article is written about Microsoft calls Tasks.

Here are a few of examples to do with different scripting language.

# PowerShell
$subscriptionId = "xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxx"

$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
}

$uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Security/tasks?api-version=2015-06-01-preview"

$response = Invoke-RestMethod -Uri $uri `
                              -Method Get `
                              -Headers $authHeader
$response.value | ConvertTo-Json

or with Bash:

ACCESS_TOKEN=$(az account get-access-token --query 'accessToken' -o tsv)
AUTH_HEADER="Authorization: Bearer $ACCESS_TOKEN"
CONTENT_TYPE="Content-Type: application/json"
SUBSCRIPTION_ID="xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxx"
RM_ENDPOINT='https://management.azure.com'
URI="$RM_ENDPOINT/subscriptions/$SUBSCRIPTION_ID/providers/Microsoft.Security/tasks?api-version=2015-06-01-preview"
 
curl -X GET -H "$AUTH_HEADER" -H "$CONTENT_TYPE" $URI

Built-in Command Module

While you can dig into Azure Security Center REST API, you can utilize Azure PowerShell module for Azure Security Center Recommendation.

# Get all recommendations
$recommendations = Get-AzSecurityTask
$recommendations | Convert-ToJson

This PowerShell cmdlet may not satisfy your need because it requires you to know RecommendationType that are allowed as inputs. Compared with other approaches you may need to query with your recommendation display name only. For example, getting all resources that are recommended to install antimalware:

$recommendations = Get-AzSecurityTask
$recommendations | Where-Object {$_.RecommendationType -eq "InstallAntimalware" } `
                 | ConvertTo-Json

or with Azure CLI:

az security task list

Continuous Export

If you are familiar with Kusto Query Language and would to use it for querying security state, as well as to use Recommendation data to build your own Monitor Workbook , check out Continuous Export feature. This feature allows you to send Recommendation data to whether Event Hub or a Log Analytics workspace. It also allows you to filter recommendation type to be sent.

Once Azure Security Center recommendation data is in your Log Analytics workspace you can simply do the query, for example:

SecurityRecommendation
| extend ResourceName = (tostring(split(AssessedResourceId, "/")[8]))
| extend ResourceGroupName = (tostring(split(AssessedResourceId, "/")[4]))
| summarize arg_max(TimeGenerated, *) by AssessedResourceId
| project TimeGenerated,
          ResourceName,
          ResourceGroupName,
          RecommendationName,
          RecommendationState,
          AssessedResourceId

There are some issues with Recommendation data type as of this article:

  • ResourceTenantId is always 00000000-0000-0000-0000-000000000000
  • RecommendationSeverity is N/A
  • Some recommendation types have description, some are missing or are blank.

I wouldn’t recommend you to use SecurityRecommnedation data table at this moment.

Resource Graph Explorer

Resource Graph query is definitely an another way to analyze security state of Azure resources. As long as Azure Policy is still running well, you can access to its latest compliance state by doing Resource Graph query against securityresources data table. Here is an example:

securityresources
| where type == "microsoft.security/assessments"
| extend resourceId = properties.resourceDetails.Id
| extend resourceName = tostring(split(resourceId, "/")[8])
| extend resourceGroup = (split(resourceId, "/")[4])
| extend status = properties.status.code
| extend recommendatioName = properties.displayName 
| project subscriptionId,
		  recommendatioName,
		  resourceName,
		  resourceGroup,
		  status,
		  resourceId

You will encounter 1000 limit threshold in result so I’d highly recommend to add a filter to query specific recommendation as well as to query Unhealthy resource only, for example check all unhealthy resources under  Secure transfer to storage accounts should be enabled recommendation type:

securityresources
| where type == "microsoft.security/assessments"
| extend resourceId = properties.resourceDetails.Id
| extend resourceName = tostring(split(resourceId, "/")[8])
| extend resourceGroup = (split(resourceId, "/")[4])
| extend status = properties.status.code
| extend recommendatioName = properties.displayName 
| where recommendatioName == "Secure transfer to storage accounts should be enabled"
| where status == "Unhealthy"
| project subscriptionId,
		  recommendatioName,
		  resourceName,
		  resourceGroup,
		  status,
		  resourceId

Using Resource Graph query you wouldn’t have to worry about querying Azure Policy compliance result for Azure Security Center. Moreover, the result shows you the last compliance/security state of scanned resources.

Azure Policy Compliance State

As said earlier, Azure Security Center Recommendation is powered by Azure Policy now. Therefore you can get compliance state from Azure Policy by querying Azure Security Center assignment. Below is the sample code to get all non-compliant resources under System Update Monitoring (aka system update should be installed)

$subscriptionId = "xxxxxx-xxxx-xxxxx-xxxxx"
$assignmentId = "/subscriptions/$subscriptionId/providers/microsoft.authorization/policyassignments/securitycenterbuiltin"
Get-AzPolicyState | Where-Object {$_.PolicyAssignmentId -eq $assignmentId -AND `
                                  $_.PolicyDefinitionReferenceId -eq "systemupdatesmonitoring" -AND `
                                  $_.ComplianceState -eq "NonCompliant" }

Conclusion

You don’t have only one way to get recommendation data in Azure Security Center. From this article, you can query from Azure Security Center API, Azure Policy API or use Kusto Query Language to query against Resource Graph and Log Analytics workspace. Each of these ways have pros and cons. Depending on use case the approach may vary. For example, while Resource Graph provides you fastest way that accesses directly compliant result from Azure Policy without any worry about timestamp it still has limit threshold as well as it doesn’t allow you to do cross query (e.g. to get subscription friendly name). Exporting recommendation to a Log Analytics workspace helps you do more with Kusto but the current data schema looks like an incomplete one and Microsoft perhaps is still in progress of fixing.

Below are some references to check out:

This entry was posted in Azure Security Center, Governance & Compliance and tagged , , . Bookmark the permalink.

Leave a Reply