Microsoft Azure Keywords
The following keywords are supported in Microsoft Azure audits:
Keyword |
Description |
---|---|
json_transform |
json_transform uses JQ to transform the aggregate JSON file from Azure into a format that is easier to understand and evaluate. For an example, see JQ Example. |
subscriptions |
When combined with the login credentials in the scan wizard, this keyword displays a comma-separated list of subscription IDs to be scanned. By default, all accessible subscriptions will be scanned. |
request |
This keyword specifies the plugin should return a data set.
|
regex | The regex is used to filter the JQ outputs to a smaller set of lines of text based on the regular expression. It is an optional transformation. |
expect and not_expect |
The evaluation is based on expect or not_expect. Use only one of these fields in a check. For expect, if the regular expression matches a line of text, the check results as PASSED. If there are no matches, the check results as FAILED. For not_expect, if the regular expression matches a line of text, the check results as FAILED. If there are no matches, the check results as PASSED. |
match_all | Setting match_all to YES requires the item to match all lines of text, and not just a single line of text. If match_all is set to the default NO, only one line must match for the check to pass. |
The Azure plugin utilizes the Azure REST API in order to obtain configuration information for your cloud environment. At the Tenable .audit and check level, action types are used in the request field. These action types correlate to documented API endpoints with some modifications. If there are prerequisites for a given API call, for example, the subscription ID or resource group name, that information is queried for and prepopulated into an aggregate JSON document before attaching the specified action type’s information. This aggregate JSON document is then filtered using JQ in order to format the configuration data for evaluation and review.
Note: When writing your own checks for Azure, you can list the aggregate JSON document by using a request type with no json_transform, regex or expect fields. For more information, see Request Types.
Aggregate JSON Example
The following is an example of the aggregate JSON document with subscription IDs as a prerequisite:
[ { "id" : "/subscriptions/12345", "subscriptionId" : "12345", "displayName" : "Microsoft Azure Enterprise", "state" : "Enabled", "subscriptionPolicies" : { "locationPlacementId" : "Public_2014-09-01", "quotaId" : "EnterpriseAgreement_2014-09-01", "spendingLimit" : "Off" }, "value" : [] }, { "id" : "/subscriptions/123456",-9 "subscriptionId" : "123456", "displayName" : "Microsoft Azure Enterprise", "state" : "Enabled", "subscriptionPolicies" : { "locationPlacementId" : "Public_2014-09-01", "quotaId" : "EnterpriseAgreement_2014-09-01", "spendingLimit" : "Off" }, "value" : [] }, { "id" : "/subscriptions/1234567", "subscriptionId" : "1234567", "displayName" : "Microsoft Azure Enterprise", "state" : "Enabled", "subscriptionPolicies" : { "locationPlacementId" : "Public_2014-09-01", "quotaId" : "EnterpriseAgreement_2014-09-01", "spendingLimit" : "Off" }, "value" : [ { "id" : "/subscriptions/1234567providers/microsoft.insights/logprofiles/default", "type" : null, "name" : "default", "location" : null, "kind" : null, "tags" : null, "properties" : { "storageAccountId" : "/subscriptions/1234567/resourceGroups/testservice1/providers/Microsoft.Storage/storageAccounts/testservice1diag830", "serviceBusRuleId" : null, "locations" : [ "eastus", "eastus2", "global" ], "categories" : [ "Write", "Delete", "Action" ], "retentionPolicy" : { "enabled" : true, "days" : 90 } }, "identity" : null } ] } ]
JQ Example
The following is an example of how an aggregate JSON document gets transformed into JQ:
JQ example: .[]| if ((.value | length) != 0) then "Sub ID: (.subscriptionId) has a Log Profile" else "Sub ID: (.subscriptionId) does not have a Log Profiles" end
Plugin Output example: Remote value:
Sub ID: 12345 does not have a Log Profile Sub ID: 2123456 does not have a Log Profile Sub ID: 1234567 has a Log Profile
Policy value:
request: 'listLogProfiles'
Example
The following is an example check that uses the previously listed JSON document and JQ:
<custom_item>
description : "Ensure that a Log Profile exists"
request : "listLogProfiles"
json_transform:'.[]| if ((.value | length) != 0) then "Sub ID: (.subscriptionId) has a Log Profile" else "Sub ID: (.subscriptionId) does not have a Log Profile" end'
regex: "Sub ID:" not_expect:'does not have a Log Profile' </custom_item>