diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditDCR.json b/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditDCR.json deleted file mode 100644 index c73bf483d2c..00000000000 --- a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditDCR.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "dataCollectionRuleName": { - "type": "string", - "defaultValue": "dcr-checkmarx-audit-log-ingestion", - "metadata": { - "description": "Name of the Data Collection Rule" - } - }, - "location": { - "type": "string", - "metadata": { - "description": "Location for the Data Collection Rule. Must match Log Analytics Workspace location." - } - }, - "workspaceResourceId": { - "type": "string", - "metadata": { - "description": "Full Resource ID of the Log Analytics workspace" - } - }, - "dataCollectionEndpointResourceId": { - "type": "string", - "metadata": { - "description": "Full Resource ID of the Data Collection Endpoint" - } - } - }, - "variables": { - "tableName": "CheckmarxAuditEvents_CL", - "streamName": "Custom-CheckmarxAuditEvents_CL" - }, - "resources": [ - { - "type": "Microsoft.Insights/dataCollectionRules", - "apiVersion": "2023-03-11", - "name": "[parameters('dataCollectionRuleName')]", - "location": "[parameters('location')]", - "properties": { - "dataCollectionEndpointId": "[parameters('dataCollectionEndpointResourceId')]", - "streamDeclarations": { - "[variables('streamName')]": { - "columns": [ - { - "name": "TimeGenerated", - "type": "datetime" - }, - { - "name": "EventDate", - "type": "datetime" - }, - { - "name": "EventType", - "type": "string" - }, - { - "name": "AuditResource", - "type": "string" - }, - { - "name": "ActionType", - "type": "string" - }, - { - "name": "ActionUserId", - "type": "string" - }, - { - "name": "IpAddress", - "type": "string" - }, - { - "name": "UserId", - "type": "string" - }, - { - "name": "Status", - "type": "string" - }, - { - "name": "Username", - "type": "string" - }, - { - "name": "DataJson", - "type": "string" - } - ] - } - }, - "dataSources": {}, - "destinations": { - "logAnalytics": [ - { - "workspaceResourceId": "[parameters('workspaceResourceId')]", - "name": "clv2ws1" - } - ] - }, - "dataFlows": [ - { - "streams": [ - "[variables('streamName')]" - ], - "destinations": [ - "clv2ws1" - ], - "transformKql": "source", - "outputStream": "[variables('streamName')]" - } - ] - } - } - ], - "outputs": { - "dcrImmutableId": { - "type": "string", - "value": "[reference(resourceId('Microsoft.Insights/dataCollectionRules', parameters('dataCollectionRuleName'))).immutableId]" - }, - "dcrResourceId": { - "type": "string", - "value": "[resourceId('Microsoft.Insights/dataCollectionRules', parameters('dataCollectionRuleName'))]" - } - } -} diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditTable.json b/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditTable.json deleted file mode 100644 index 6b9c73ed933..00000000000 --- a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployAuditTable.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "workspaceName": { - "type": "string", - "metadata": { - "description": "Name of the Log Analytics workspace" - } - } - }, - "variables": { - "tableName": "CheckmarxAuditEvents_CL" - }, - "resources": [ - { - "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", - "name": "[concat(parameters('workspaceName'), '/', variables('tableName'))]", - "properties": { - "totalRetentionInDays": 90, - "plan": "Analytics", - "schema": { - "name": "[variables('tableName')]", - "columns": [ - { - "name": "TimeGenerated", - "type": "datetime", - "description": "Time the record was ingested" - }, - { - "name": "EventDate", - "type": "datetime", - "description": "Date and time of the audit event" - }, - { - "name": "EventType", - "type": "string", - "description": "Type of audit event" - }, - { - "name": "AuditResource", - "type": "string", - "description": "Resource being audited" - }, - { - "name": "ActionType", - "type": "string", - "description": "Type of action performed" - }, - { - "name": "ActionUserId", - "type": "string", - "description": "User ID who performed the action" - }, - { - "name": "IpAddress", - "type": "string", - "description": "IP address of the user" - }, - { - "name": "UserId", - "type": "string", - "description": "User ID from data payload" - }, - { - "name": "Status", - "type": "string", - "description": "Status of the action" - }, - { - "name": "Username", - "type": "string", - "description": "Username who performed the action" - }, - { - "name": "DataJson", - "type": "string", - "description": "Full JSON data payload" - } - ] - }, - "retentionInDays": 90 - } - } - ], - "outputs": { - "tableName": { - "type": "string", - "value": "[variables('tableName')]" - } - } -} diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployDCE.json b/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployDCE.json deleted file mode 100644 index 53b83a87c54..00000000000 --- a/Playbooks/AS-Checkmarx-Audit-Ingestion/AzureDeployDCE.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "dataCollectionEndpointName": { - "type": "string", - "defaultValue": "dce-checkmarx-log-ingestion", - "metadata": { - "description": "Name of the Data Collection Endpoint" - } - }, - "location": { - "type": "string", - "metadata": { - "description": "Location for the Data Collection Endpoint. Must match Log Analytics Workspace location." - } - } - }, - "resources": [ - { - "type": "Microsoft.Insights/dataCollectionEndpoints", - "apiVersion": "2023-03-11", - "name": "[parameters('dataCollectionEndpointName')]", - "location": "[parameters('location')]", - "properties": { - "networkAcls": { - "publicNetworkAccess": "Enabled" - } - } - } - ], - "outputs": { - "logsIngestionEndpoint": { - "type": "string", - "value": "[reference(resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('dataCollectionEndpointName'))).logsIngestion.endpoint]" - }, - "dceResourceId": { - "type": "string", - "value": "[resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('dataCollectionEndpointName'))]" - } - } -} diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_1.png deleted file mode 100644 index 60ffd7b2ee6..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_1.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_2.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_2.png deleted file mode 100644 index 2e72b9c83ae..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_2.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_3.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_3.png deleted file mode 100644 index eebe8435223..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_3.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_4.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_4.png deleted file mode 100644 index 41535725a04..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_DCR_Access_4.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_1.png index 61a23f2cbf8..65f15aac88e 100644 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_1.png and b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_1.png differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_3.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_3.png index 8aebb647504..0833c13a932 100644 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_3.png and b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_3.png differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_1.png deleted file mode 100644 index 79253235ce0..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_1.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_2.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_2.png deleted file mode 100644 index ba829b76b20..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_2.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_Table_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_Table_1.png deleted file mode 100644 index 6f58adc50d5..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_Audit_Table_1.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_1.png deleted file mode 100644 index 5b2f02ef5b0..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_1.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_2.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_2.png deleted file mode 100644 index a4be5156032..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Deploy_DCE_2.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_1.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_1.png deleted file mode 100644 index c127aed2cef..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_1.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_2.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_2.png deleted file mode 100644 index f8227f583ca..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_2.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_3.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_3.png deleted file mode 100644 index facf278c360..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_3.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_4.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_4.png deleted file mode 100644 index f56a4033ea8..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_4.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_5.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_5.png deleted file mode 100644 index e87157dbdca..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_5.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_6.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_6.png deleted file mode 100644 index 3d70c7d703b..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_6.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_7.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_7.png deleted file mode 100644 index 065be24f38d..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_7.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_8.png b/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_8.png deleted file mode 100644 index dc3f28b3c3e..00000000000 Binary files a/Playbooks/AS-Checkmarx-Audit-Ingestion/Images/Checkmarx_Audit_Integration_Key_Vault_Access_8.png and /dev/null differ diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/README.md b/Playbooks/AS-Checkmarx-Audit-Ingestion/README.md index 60ba9f0f4d0..bedaa992109 100644 --- a/Playbooks/AS-Checkmarx-Audit-Ingestion/README.md +++ b/Playbooks/AS-Checkmarx-Audit-Ingestion/README.md @@ -4,18 +4,18 @@ Author: Accelerynt For any technical questions, please contact [info@accelerynt.com](mailto:info@accelerynt.com) -This playbook will create a unidirectional integration with Microsoft Sentinel. It will pull Checkmarx audit log events into a Microsoft Sentinel custom log table where they can be tracked, queried, and correlated with other security data. This uses Data Collection Rules (DCR), Data Collection Endpoints (DCE), and custom log tables. +This playbook will create a unidirectional integration with Microsoft Sentinel. It will pull Checkmarx audit events into a Microsoft Sentinel custom log table on a daily schedule where they can be tracked, queried, and correlated with other security data. This uses Data Collection Rules (DCR), Data Collection Endpoints (DCE), and custom log tables. ![Checkmarx_Audit_Integration_Demo_1](Images/Checkmarx_Audit_Integration_Demo_1.png) > [!NOTE] -> Estimated Time to Complete: 45 minutes +> Estimated Time to Complete: 15 minutes > [!TIP] > Required deployment variables are noted throughout. Reviewing the deployment page and filling out fields as you proceed is recommended. > [!NOTE] -> This playbook handles **audit events only**. For SAST findings ingestion, see the [AS-Checkmarx-SAST-Ingestion](https://github.com/Accelerynt-Security/AS-Checkmarx-SAST-Ingestion) playbook. Note that only a single DCE and a single Key Vault secret need to be created for both playbooks. +> This playbook handles **audit events only**. For SAST findings ingestion, see the [AS-Checkmarx-SAST-Ingestion](https://github.com/Accelerynt-Security/AS-Checkmarx-SAST-Ingestion) playbook. # @@ -23,12 +23,12 @@ This playbook will create a unidirectional integration with Microsoft Sentinel. The following items are required under the template settings during deployment: -* **Checkmarx Client Secret or Refresh Token** - a client secret (recommended) or refresh token with permissions to query audit logs from your Checkmarx One instance. [Documentation link](#checkmarx-api-permissions) +* **Checkmarx Client Secret or Refresh Token** - a client secret (recommended) or refresh token with permissions to query audit events from your Checkmarx One instance. [Documentation link](#checkmarx-api-permissions) * **Checkmarx IAM Base URL** - the base URL for Checkmarx IAM authentication based on your region (e.g., `https://us.iam.checkmarx.net`). [Documentation link](#checkmarx-api-permissions) * **Checkmarx AST Base URL** - the base URL for Checkmarx AST API calls based on your region (e.g., `https://us.ast.checkmarx.net`). [Documentation link](#checkmarx-api-permissions) * **Checkmarx Tenant** - your Checkmarx tenant/realm name used in the authentication URL. [Documentation link](#checkmarx-api-permissions) * **Azure Key Vault Secret** - this will be used to store your Checkmarx client secret or refresh token. [Documentation link](#create-an-azure-key-vault-secret) -* **Log Analytics Workspace** - the name, location, subscription ID, resource group, and resource ID of the Log Analytics workspace that the Checkmarx data will be sent to. [Documentation link](#log-analytics-workspace) +* **Log Analytics Workspace** - the name, location, and resource ID of the Log Analytics workspace that the Checkmarx data will be sent to. [Documentation link](#log-analytics-workspace) # @@ -94,6 +94,9 @@ Choose a name for the secret, such as "**checkmarx-integration-secret**", and en ![Checkmarx_Audit_Integration_Key_Vault_2](Images/Checkmarx_Audit_Integration_Key_Vault_2.png) +> [!IMPORTANT] +> This deployment uses the **Azure role-based access control (RBAC)** permission model. Key Vault Access Policies will need to be set up manually post-deployment if this legacy permission model is still in use in your tenant. To switch a Key Vault from legacy Access Policies to the recommended RBAC, navigate to the "**Access configuration**" menu option under the "**Settings**" section and select "**Azure role-based access control**". Existing secrets, keys, and certificates are not affected by this change. + #### Log Analytics Workspace Navigate to the Log Analytics Workspace page: https://portal.azure.com/#view/HubsExtension/BrowseResource/resourceType/Microsoft.OperationalInsights%2Fworkspaces @@ -102,11 +105,11 @@ Select the workspace that the Checkmarx data will be sent to, and take note of t ![Checkmarx_Audit_Integration_Log_Analytics_Workspace_1](Images/Checkmarx_Audit_Integration_Log_Analytics_Workspace_1.png) -From the left menu blade, click **Overview** and take note of the **Name** and **Location** field values. These will be needed for the DCE deployment. +From the left menu blade, click **Overview** and take note of the **Name** and **Location** field values. These will be needed during deployment. ![Checkmarx_Audit_Integration_Log_Analytics_Workspace_2](Images/Checkmarx_Audit_Integration_Log_Analytics_Workspace_2.png) -From the left menu blade, click **Overview** and take note of the **Subscription**, **Resource group**, and **Resource ID** shown in the JSON View. These will be needed for the DCR and Logic App deployments. +From the left menu blade, click **Overview** and take note of the **Resource ID** shown in the JSON View. This will also be needed during deployment. ![Checkmarx_Audit_Integration_Log_Analytics_Workspace_3](Images/Checkmarx_Audit_Integration_Log_Analytics_Workspace_3.png) @@ -114,93 +117,7 @@ From the left menu blade, click **Overview** and take note of the **Subscription ### Deployment -#### Deploy the Audit Logs Custom Table - -The custom table **CheckmarxAuditEvents_CL** must be created before deploying the DCR. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployAuditTable.json) -[![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployAuditTable.json) - -Click the "**Deploy to Azure**" button and it will bring you to the custom deployment template. - -In the **Project details** section: - -* Select the **Subscription** and **Resource group** from the dropdown boxes you would like the playbook deployed to. - -In the **Instance details** section: - -* **Workspace Name**: Enter the **Name** of your Log Analytics workspace referenced in [Log Analytics Workspace](#log-analytics-workspace). - -Towards the bottom, click on "**Review + create**". - -![Checkmarx_Audit_Integration_Deploy_Audit_Table_1](Images/Checkmarx_Audit_Integration_Deploy_Audit_Table_1.png) - -Once the resources have validated, click on "**Create**". - -#### Deploy the Data Collection Endpoint (DCE) - -The DCE provides the ingestion endpoint URL for the Logic App. - -> [!NOTE] -> If you have already deployed the **AS-Checkmarx-SAST-Ingestion** playbook, a DCE already exists in your workspace. You may skip this step and use the existing DCE's Logs Ingestion Endpoint URL and Resource ID for the DCR deployment below. Navigate to your existing DCE resource to find these values. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployDCE.json) -[![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployDCE.json) - -Click the "**Deploy to Azure**" button and it will bring you to the custom deployment template. - -In the **Project details** section: - -* Select the **Subscription** and **Resource group** from the dropdown boxes you would like the playbook deployed to. - -In the **Instance details** section: - -* **Data Collection Endpoint Name**: This can be left as "**dce-checkmarx-log-ingestion**" or you may change it. -* **Location**: Enter the **Location** of your Log Analytics workspace referenced in [Log Analytics Workspace](#log-analytics-workspace). Note that this may differ from the Region field, which is automatically populated based on the selected Resource group. - -Towards the bottom, click on "**Review + create**". - -![Checkmarx_Audit_Integration_Deploy_DCE_1](Images/Checkmarx_Audit_Integration_Deploy_DCE_1.png) - -Once the resources have validated, click on "**Create**". - -After deployment, navigate to the "**Outputs**" section and take note of the values listed, as these will be needed for subsequent deployment steps. - -![Checkmarx_Audit_Integration_Deploy_DCE_2](Images/Checkmarx_Audit_Integration_Deploy_DCE_2.png) - -#### Deploy the Audit Logs Data Collection Rule (DCR) - -The DCR defines the schema and destination for the ingested audit log data. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployAuditDCR.json) -[![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2FAzureDeployAuditDCR.json) - -Click the "**Deploy to Azure**" button and it will bring you to the custom deployment template. - -In the **Project details** section: - -* Select the **Subscription** and **Resource group** from the dropdown boxes you would like the playbook deployed to. - -In the **Instance details** section: - -* **Data Collection Rule Name**: This can be left as "**dcr-checkmarx-audit-log-ingestion**" or you may change it. -* **Location**: Enter the location listed on your Log Analytics workspace. -* **Workspace Resource Id**: Enter the full resource ID of your Log Analytics workspace referenced in [Log Analytics Workspace](#log-analytics-workspace). -* **Data Collection Endpoint Resource Id**: Enter the full resource ID of the DCE created in the previous step. - -Towards the bottom, click on "**Review + create**". - -![Checkmarx_Audit_Integration_Deploy_Audit_DCR_1](Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_1.png) - -Once the resources have validated, click on "**Create**". - -After deployment, navigate to the "**Outputs**" section and take note of the **dcrImmutableId** value, as this will be needed for the Logic App deployment. - -![Checkmarx_Audit_Integration_Deploy_Audit_DCR_2](Images/Checkmarx_Audit_Integration_Deploy_Audit_DCR_2.png) - -#### Deploy the Logic App Playbook - -The Logic App performs the daily ingestion of Checkmarx audit log events. +This single deployment creates the custom log table, Data Collection Endpoint (DCE), Data Collection Rule (DCR), Key Vault API connection, Logic App, and all required role assignments. [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2Fazuredeploy.json) [![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FPlaybooks%2FAS-Checkmarx-Audit-Ingestion%2Fazuredeploy.json) @@ -214,15 +131,20 @@ In the **Project details** section: In the **Instance details** section: * **Playbook Name**: This can be left as "**AS-Checkmarx-Audit-Ingestion**" or you may change it. +* **Workspace Name**: Enter the **Name** of your Log Analytics workspace referenced in [Log Analytics Workspace](#log-analytics-workspace). +* **Workspace Resource Id**: Enter the full **Resource ID** of your Log Analytics workspace. +* **Workspace Location**: Enter the **Location** of your Log Analytics workspace. Note that this may differ from the selected Resource group's region; the DCE and DCR will be deployed to the workspace's region. * **Key Vault Name**: Enter the name of the Key Vault referenced in [Create an Azure Key Vault Secret](#create-an-azure-key-vault-secret). -* **Key Vault Secret Name**: Enter the name of the Key Vault secret created in [Create an Azure Key Vault Secret](#create-an-azure-key-vault-secret). -* **Grant Type**: Enter the OAuth grant type for Checkmarx authentication. Use `client_credentials` (default) for client ID and secret, or `refresh_token` for refresh token authentication. See [Checkmarx API Permissions](#checkmarx-api-permissions) for details. +* **Key Vault Resource Group**: Enter the resource group containing the Key Vault. +* **Key Vault Secret Name**: This can be left as "**checkmarx-integration-secret**" or changed to match the secret name you used. +* **Data Collection Endpoint Name**: This can be left as the default. Override it only if you are deploying multiple ingestion playbooks into the same resource group and need to avoid a name collision. +* **Data Collection Rule Name**: This can be left as the default. Override it only if you are deploying multiple ingestion playbooks into the same resource group and need to avoid a name collision. * **Checkmarx IAM Base Url**: Enter the IAM base URL for your Checkmarx region referenced in [Checkmarx API Permissions](#checkmarx-api-permissions). * **Checkmarx AST Base Url**: Enter the AST base URL for your Checkmarx region referenced in [Checkmarx API Permissions](#checkmarx-api-permissions). * **Checkmarx Tenant**: Enter your Checkmarx tenant/realm name (this appears in your Checkmarx URL and authentication settings). * **Checkmarx Client Id**: Enter your Checkmarx OAuth Client ID (e.g., "**ast-app**"). -* **DCE Logs Ingestion Endpoint**: Enter the Logs Ingestion Endpoint URL from the DCE created previously. -* **DCR Immutable Id**: Enter the Immutable ID from the Audit DCR created previously. +* **Grant Type**: Select the OAuth grant type for Checkmarx authentication. Use `client_credentials` for client ID and secret, or `refresh_token` for refresh token authentication. See [Checkmarx API Permissions](#checkmarx-api-permissions) for details. +* **Lookback Days**: Number of days prior to each run to pull audit events from. Default is **2**. For the initial backfill, set this higher (e.g., **180**, or up to **365**, the Checkmarx retention maximum) to ingest historical events, then reduce to **2** for steady-state daily operation. See the [Checkmarx Audit Trail API documentation](https://docs.checkmarx.com/en/34965-156810-audit-trail-api.html) for endpoint specifics. This can be changed later by editing the **FromDate** variable in the Logic App's **Initialize_Variables** action. Towards the bottom, click on "**Review + create**". @@ -232,100 +154,48 @@ Once the resources have validated, click on "**Create**". ![Checkmarx_Audit_Integration_Deploy_2](Images/Checkmarx_Audit_Integration_Deploy_2.png) -The resources should take around a minute to deploy. Once the deployment is complete, you can expand the "**Deployment details**" section to view them. -Click the one corresponding to the Logic App. +The resources should take around two minutes to deploy. Once the deployment is complete, you can expand the "**Deployment details**" section to view them. ![Checkmarx_Audit_Integration_Deploy_3](Images/Checkmarx_Audit_Integration_Deploy_3.png) # -### Granting Access to Azure Key Vault +### Role Assignments -Before the Logic App can run successfully, the playbook must be granted access to the Key Vault storing your Checkmarx secret. +The following role assignments are created automatically by this deployment: -From the Key Vault page menu, click the "**Access configuration**" menu option under the "**Settings**" section. +| Resource | Role | Purpose | +| --- | --- | --- | +| Azure Key Vault | **Key Vault Secrets User** | Allows the Logic App to retrieve the Checkmarx secret | +| Audit Data Collection Rule | **Monitoring Metrics Publisher** | Allows the Logic App to send audit data to the DCR ingestion endpoint | -![Checkmarx_Audit_Integration_Key_Vault_Access_1](Images/Checkmarx_Audit_Integration_Key_Vault_Access_1.png) +> [!IMPORTANT] +> The role assignments may take some time to propagate. If your Logic App is not running successfully immediately after deployment, please allow up to 10 minutes before retrying. > [!NOTE] -> Azure Key Vault supports two permission models for granting data plane access: **Azure role-based access control (Azure RBAC)** and **Vault access policy**. Azure RBAC is the **recommended** authorization system, as indicated in the Azure portal. Vault access policy is considered **legacy** by Microsoft. Both methods are documented below; choose the option that matches your Key Vault's configuration. - -# - -#### Option 1: Azure Role-Based Access Control (Recommended) - -From the Key Vault "**Access control (IAM)**" page, click "**Add role assignment**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_2](Images/Checkmarx_Audit_Integration_Key_Vault_Access_2.png) - -Select the "**Key Vault Secrets User**" role, then click "**Next**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_3](Images/Checkmarx_Audit_Integration_Key_Vault_Access_3.png) - -Select "**Managed identity**" and click "**Select members**". Search for "**AS-Checkmarx-Audit-Ingestion**" (or the playbook name you used) and click the option that appears. Click "**Select**", then "**Next**" towards the bottom of the page. - -![Checkmarx_Audit_Integration_Key_Vault_Access_4](Images/Checkmarx_Audit_Integration_Key_Vault_Access_4.png) - -Navigate to the "**Review + assign**" section and click "**Review + assign**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_5](Images/Checkmarx_Audit_Integration_Key_Vault_Access_5.png) - -# - -#### Option 2: Vault Access Policy (Legacy) - -If your Key Vault is configured to use "**Vault access policy**", access must be granted through the "**Access policies**" page. - -Navigate to the "**Access policies**" menu option, found under the "**Settings**" section on the Key Vault page menu. - -Click "**Create**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_6](Images/Checkmarx_Audit_Integration_Key_Vault_Access_6.png) - -In the "**Permissions**" tab, select the "**Get**" checkbox under the "**Secret permissions**" section. Click "**Next**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_7](Images/Checkmarx_Audit_Integration_Key_Vault_Access_7.png) - -In the "**Principal**" tab, paste "**AS-Checkmarx-Audit-Ingestion**" (or the playbook name you used) into the search box and select the option that appears. Click "**Next**". - -![Checkmarx_Audit_Integration_Key_Vault_Access_8](Images/Checkmarx_Audit_Integration_Key_Vault_Access_8.png) - -Navigate to the "**Review + create**" tab and click "**Create**". +> The user performing the deployment must hold the **Owner** or **User Access Administrator** role on the resource group, Key Vault, and workspace being targeted. Most customers deploying Sentinel playbooks already have this level of access. # -### Granting Access to the Data Collection Rule - -The playbook must be granted access to the Audit Data Collection Rule to publish metrics. - -From the Audit DCR "**Access control (IAM)**" page, click "**Add role assignment**". - -![Checkmarx_Audit_Integration_DCR_Access_1](Images/Checkmarx_Audit_Integration_DCR_Access_1.png) - -Select the "**Monitoring Metrics Publisher**" role, then click "**Next**". - -![Checkmarx_Audit_Integration_DCR_Access_2](Images/Checkmarx_Audit_Integration_DCR_Access_2.png) - -Select "**Managed identity**" and click "**Select members**". Search for "**AS-Checkmarx-Audit-Ingestion**" (or the playbook name you used) and click the option that appears. Click "**Select**", then "**Next**" towards the bottom of the page. +### Post-Deployment Tuning -![Checkmarx_Audit_Integration_DCR_Access_3](Images/Checkmarx_Audit_Integration_DCR_Access_3.png) +A small number of operational values are baked into the Logic App definition rather than exposed as deployment parameters, because they are constrained by the Checkmarx API contract rather than by customer choice. They are not expected to need changes, but the edit locations are documented here in case they ever do (e.g., if Checkmarx updates an API limit). -Navigate to the "**Review + assign**" section and click "**Review + assign**". +To edit these, navigate to the deployed Logic App, open the **Code view** from the left menu, and modify the value in place. Save when done. -![Checkmarx_Audit_Integration_DCR_Access_4](Images/Checkmarx_Audit_Integration_DCR_Access_4.png) - -> [!IMPORTANT] -> The role assignment may take some time to propagate. If your Logic App is not running successfully immediately after the role assignment, please allow up to 10 minutes before retrying. +| Value | Default | Location in Logic App code | When to change | +| --- | --- | --- | --- | +| Audit page size | `1000` | `Initialize_Variables` action → `AuditPageSize` variable `value` | Only if Checkmarx changes the documented maximum for `/api/audit-events`. The current API maximum is 1000. | # ### Initial Run -This playbook runs once daily, collecting Checkmarx audit log events from the previous 24 hours and ingesting them into Microsoft Sentinel. +This playbook runs once daily, paginating the Checkmarx `/api/audit-events/` endpoint and ingesting events into Microsoft Sentinel. Each run retrieves events from the configured lookback window (default **2** days). Because consecutive runs overlap, the same event will appear multiple times in the table; the **EventID** column lets you collapse to one row per event at query time when desired. -This playbook is deployed in a **Disabled** state. After completing all role assignments, navigate to the Logic App overview page and click "**Enable**" to activate the playbook. Then click "**Run**" > "**Run**" to execute the initial run. +This playbook is deployed in a **Disabled** state. After waiting for role assignments to propagate, navigate to the Logic App overview page and click "**Enable**" to activate the playbook. Then click "**Run**" > "**Run**" to execute the initial run. -Click on the run to view the execution details. Verify that all steps completed successfully, particularly the "**HTTP - Send Audit Events to DCR**" step. +Click on the run to view the execution details. Verify that all steps completed successfully, particularly the "**HTTP - Send Audit Events to DCR**" step inside the `Until_Paginate_Audit_Logs` loop. # @@ -340,43 +210,51 @@ From there, select the workspace your deployed logic app references and click "* ![Checkmarx_Audit_Custom_Logs_1](Images/Checkmarx_Audit_Custom_Logs_1.png) +> [!IMPORTANT] +> The Checkmarx audit-events endpoint returns the full set of currently-available events on each request. The playbook ingests this full set on every run, so the same event may appear multiple times in the table across runs. **Use the `EventID` column to deduplicate rows at query time.** The sample queries below show the standard pattern: `summarize arg_max(TimeGenerated, *) by EventID`. Consider saving the dedup pattern as a workspace function (e.g., `CheckmarxAuditEvents`) so downstream queries can reference deduplicated data without repeating the boilerplate. + #### Sample KQL Queries -**View all audit logs:** +**View all audit events (deduplicated):** ```kql CheckmarxAuditEvents_CL -| project TimeGenerated, EventDate, EventType, ActionType, Username, IpAddress, Status -| order by TimeGenerated desc +| summarize arg_max(TimeGenerated, *) by EventID +| project EventDate, EventType, ActionType, Username, IpAddress, Status, TenantID +| order by EventDate desc ``` **User login activity:** ```kql CheckmarxAuditEvents_CL +| summarize arg_max(TimeGenerated, *) by EventID | where ActionType == "login" -| project TimeGenerated, Username, IpAddress, Status -| order by TimeGenerated desc +| project EventDate, Username, IpAddress, Status +| order by EventDate desc ``` **Failed login attempts:** ```kql CheckmarxAuditEvents_CL +| summarize arg_max(TimeGenerated, *) by EventID | where ActionType == "login" and Status != "OK" -| project TimeGenerated, Username, IpAddress, Status -| order by TimeGenerated desc +| project EventDate, Username, IpAddress, Status +| order by EventDate desc ``` -**Activity by user:** +**Activity by user (last 7 days):** ```kql CheckmarxAuditEvents_CL -| where TimeGenerated > ago(7d) +| summarize arg_max(TimeGenerated, *) by EventID +| where EventDate > ago(7d) | summarize ActionCount = count() by Username, ActionType | order by ActionCount desc ``` -**Activity by IP address:** +**Activity by IP address (last 7 days):** ```kql CheckmarxAuditEvents_CL -| where TimeGenerated > ago(7d) +| summarize arg_max(TimeGenerated, *) by EventID +| where EventDate > ago(7d) | summarize Count = count(), Users = make_set(Username) by IpAddress | order by Count desc ``` @@ -384,15 +262,17 @@ CheckmarxAuditEvents_CL **Audit events timeline:** ```kql CheckmarxAuditEvents_CL -| where TimeGenerated > ago(7d) -| summarize Count = count() by bin(TimeGenerated, 1h), ActionType +| summarize arg_max(TimeGenerated, *) by EventID +| where EventDate > ago(7d) +| summarize Count = count() by bin(EventDate, 1h), ActionType | render timechart ``` **User activity summary:** ```kql CheckmarxAuditEvents_CL -| where TimeGenerated > ago(7d) +| summarize arg_max(TimeGenerated, *) by EventID +| where EventDate > ago(7d) | summarize EventCount = count(), UniqueActions = dcount(ActionType), @@ -405,6 +285,7 @@ CheckmarxAuditEvents_CL **Login activity by IP address:** ```kql CheckmarxAuditEvents_CL +| summarize arg_max(TimeGenerated, *) by EventID | where EventType has "login" | summarize LoginCount = count(), @@ -414,6 +295,16 @@ CheckmarxAuditEvents_CL | order by LoginCount desc ``` +**Sensitive event types (creates, deletes, role changes):** +```kql +CheckmarxAuditEvents_CL +| summarize arg_max(TimeGenerated, *) by EventID +| where EventDate > ago(30d) +| where ActionType in ("create", "delete", "assign", "update") +| project EventDate, EventType, ActionType, ActionUserId, AuditResource, DataJson +| order by EventDate desc +``` + # ### Data Schema @@ -423,37 +314,49 @@ CheckmarxAuditEvents_CL | Column | Type | Description | | --- | --- | --- | | TimeGenerated | datetime | Time the record was ingested | +| EventID | string | Unique identifier for the audit event. Used as the deduplication key. | | EventDate | datetime | Date and time of the audit event | -| EventType | string | Type of audit event (e.g., events.cxiam.user.account.login) | -| AuditResource | string | Resource being audited (e.g., user.account) | -| ActionType | string | Type of action performed (e.g., login) | +| EventType | string | Type of audit event (e.g., `users.login`, `scans.create`) | +| AuditResource | string | Resource being audited (e.g., `users`, `scans`, `projects`) | +| ActionType | string | Type of action performed (e.g., `login`, `create`, `update`, `delete`) | | ActionUserId | string | User ID who performed the action | -| IpAddress | string | IP address of the user | -| UserId | string | User ID from data payload | -| Status | string | Status of the action (e.g., OK) | -| Username | string | Username who performed the action | -| DataJson | string | Full JSON data payload | +| IpAddress | string | IP address of the user (empty for events without an originating IP) | +| TenantID | string | Tenant ID for the Checkmarx instance | +| UserId | string | User ID from the data payload (login events) | +| Status | string | Status of the action (login events; e.g., `OK`) | +| Username | string | Username who performed the action (login events) | +| DataJson | string | Full JSON data payload. Fields vary by event type. | -# +> [!NOTE] +> The `UserId`, `Status`, and `Username` columns are extracted from the event's `data` object and are primarily populated for login events. For other event types (e.g., `scans.create`, `environment.delete`, `applications.update`), the event-specific fields are preserved in the `DataJson` column and can be extracted in KQL using `parse_json(DataJson)`. -### Role Assignments Summary +#### Extracting fields from DataJson -The following role assignments are required for the Logic App to function: +The `data` object varies by event type. Use `parse_json` to extract event-specific fields: -| Resource | Role | Purpose | -| --- | --- | --- | -| Azure Key Vault | **Key Vault Secrets User** | Allows the Logic App to retrieve the Checkmarx secret | -| Audit Data Collection Rule | **Monitoring Metrics Publisher** | Allows the Logic App to send audit data to the DCR ingestion endpoint | +```kql +CheckmarxAuditEvents_CL +| summarize arg_max(TimeGenerated, *) by EventID +| where EventType == "scans.create" +| extend ScanID = tostring(parse_json(DataJson).scanID), + Initiator = tostring(parse_json(DataJson).initiator) +| project EventDate, ScanID, Initiator +``` # ### Troubleshooting +**Deployment fails at the Key Vault role assignment:** +* Verify **Key Vault Resource Group** is correct. +* Verify the Key Vault is configured for **Azure RBAC**. If it's on the legacy Access Policy model, the automated role assignment won't apply; either switch to RBAC from the Key Vault's "Access configuration" blade and redeploy, or grant the Logic App's managed identity **Get** secret access manually via an Access Policy. +* The deploying principal needs `Microsoft.Authorization/roleAssignments/write` on the Key Vault (e.g., Owner or User Access Administrator). + **Logic App fails at "Get_secret" step:** * Verify the Key Vault name and secret name are correct. -* Ensure the Logic App managed identity has the "Key Vault Secrets User" role on the Key Vault (RBAC) or appropriate access policy (legacy). +* Role assignment may still be propagating. Wait up to 10 minutes after deployment before retrying. -**Logic App fails at "HTTP - Get Token" step:** +**Logic App fails at "HTTP - Refresh Token" step:** * Verify the Checkmarx IAM Base URL matches your Checkmarx region. * Verify the Checkmarx Tenant name is correct. * If using `client_credentials`, verify the client secret stored in Key Vault is valid. @@ -461,26 +364,31 @@ The following role assignments are required for the Logic App to function: * Verify the Grant Type parameter matches the type of credential stored in Key Vault. * Check that the Checkmarx IAM endpoint is accessible. -**Logic App fails at "HTTP - Get Audit Logs Page" step:** +**Logic App fails at "HTTP - Get Audit Events Page" step:** * Verify the Checkmarx AST Base URL matches your Checkmarx region. * Verify the access token was successfully obtained. * Check that the Checkmarx API endpoint is accessible. * Verify the API permissions for your Checkmarx client. **Logic App fails at "HTTP - Send Audit Events to DCR" step with 403:** -* Ensure the Logic App managed identity has the "Monitoring Metrics Publisher" role on the Audit DCR. -* Wait up to 10 minutes for role assignment propagation. +* Wait up to 10 minutes for the Monitoring Metrics Publisher role assignment to propagate. **Logic App fails at DCR step with 404:** -* Verify the DCE Logs Ingestion Endpoint URL is correct. -* Verify the DCR Immutable ID is correct. +* The DCE endpoint URL and DCR immutable ID are resolved at deploy time from the resources created by this template, so 404s should not occur unless the DCE or DCR was deleted out-of-band. Redeploy the template to restore them. **No data appearing in Log Analytics:** -* Wait several minutes after the first successful run. -* Verify the custom table was created successfully. -* Verify there are audit events in your Checkmarx tenant. +* Wait several minutes after the first successful run, since ingestion is asynchronous. +* Verify the **CheckmarxAuditEvents_CL** table exists under **Custom Logs** in the workspace. * Check the Logic App run history for any errors. -**Condition step is skipped:** -* This is normal behavior if no audit events are available. -* Verify you have audit activity in Checkmarx. +**Pagination loop reaches its iteration limit:** +* The loop is bounded by a 15-minute timeout and a maximum iteration count as safety nets. If runs hit these limits, the audit event volume in your tenant may exceed what one page-by-page sweep can complete in 15 minutes. Inspect the run to see how many pages were retrieved and contact support to evaluate options for very large tenants. + +**Only one page of events ingested when more should exist:** +* The playbook follows the API's HATEOAS-style pagination in two parts: `Compose_NextRelativeHref` extracts the relative path from `Links._links.next.href` in each response, and `Set_NextPageUrl` prepends the Checkmarx AST base URL to build the absolute URL for the next request. To diagnose a premature loop exit, drill into a run of `Compose_NextRelativeHref` and check its output. If the output is empty when more pages should exist, the API response structure has changed. Inspect the actual response body of `HTTP - Get Audit Events Page` and update the extraction expression to match the path where `next.href` actually lives. If the output is a relative path but `Set_NextPageUrl` still produces an empty result, verify the `CheckmarxASTBaseUrl` variable is populated correctly. + +**Duplicate rows in the table:** +* This is expected. Each run pulls events from the configured lookback window, so events within the overlap between consecutive runs will appear multiple times in the table. Always deduplicate at query time using `summarize arg_max(TimeGenerated, *) by EventID` (see the sample queries above). Consider saving a workspace function that wraps this pattern so downstream queries don't need to repeat it. + +**Condition step is skipped for a page:** +* This is normal behavior if the page returned zero events (e.g., the very last page when the total event count is an exact multiple of the page size). The condition guards against ingesting empty result sets. \ No newline at end of file diff --git a/Playbooks/AS-Checkmarx-Audit-Ingestion/azuredeploy.json b/Playbooks/AS-Checkmarx-Audit-Ingestion/azuredeploy.json index 3c85ec503f4..1c5bf3777cc 100644 --- a/Playbooks/AS-Checkmarx-Audit-Ingestion/azuredeploy.json +++ b/Playbooks/AS-Checkmarx-Audit-Ingestion/azuredeploy.json @@ -3,18 +3,16 @@ "contentVersion": "1.0.0.0", "metadata": { "title": "AS-Checkmarx-Audit-Ingestion", - "description": "This playbook ingests Checkmarx audit log events into a custom Microsoft Sentinel table on a daily schedule.", + "description": "This playbook ingests Checkmarx audit log events into a custom Microsoft Sentinel table on a daily schedule. This single template deploys the custom Log Analytics table, Data Collection Endpoint, Data Collection Rule, Key Vault API connection, Logic App, and all required role assignments.", "prerequisites": [ "1. A Key Vault secret containing the Checkmarx client secret or refresh token", - "2. The CheckmarxAuditEvents_CL custom table deployed to Log Analytics", - "3. A Data Collection Endpoint (DCE) deployed", - "4. A Data Collection Rule (DCR) deployed and linked to the DCE" + "2. An existing Log Analytics workspace" ], "postDeployment": [ - "1. Add the Logic App managed identity to Key Vault with 'Key Vault Secrets User' role", - "2. Add the Logic App managed identity to the DCR with 'Monitoring Metrics Publisher' role" + "1. Allow up to 10 minutes for role assignments to propagate", + "2. Enable the Logic App (deployed in Disabled state) and run it" ], - "lastUpdateTime": "2026-03-13T00:00:00Z", + "lastUpdateTime": "2026-06-12T00:00:00.000Z", "support": { "tier": "partner" }, @@ -30,36 +28,67 @@ "description": "Name of the Logic App" } }, + "WorkspaceName": { + "type": "string", + "metadata": { + "description": "Name of the Log Analytics workspace where the custom table will be created" + } + }, + "WorkspaceResourceId": { + "type": "string", + "metadata": { + "description": "Full resource ID of the Log Analytics workspace" + } + }, + "WorkspaceLocation": { + "type": "string", + "metadata": { + "description": "Azure region of the Log Analytics workspace (used for the DCE and DCR; may differ from the resource group region)" + } + }, "KeyVaultName": { "type": "string", "metadata": { - "description": "Name of the Key Vault containing the Checkmarx secret" + "description": "Name of the Key Vault containing the Checkmarx client secret or refresh token" + } + }, + "KeyVaultResourceGroup": { + "type": "string", + "metadata": { + "description": "Resource group containing the Key Vault" } }, "KeyVaultSecretName": { "type": "string", + "defaultValue": "checkmarx-integration-secret", "metadata": { "description": "Name of the Key Vault secret containing the Checkmarx client secret or refresh token" } }, - "GrantType": { + "DataCollectionEndpointName": { "type": "string", - "allowedValues": [ - "refresh_token", - "client_credentials" - ], + "defaultValue": "dce-checkmarx-audit-ingestion", "metadata": { - "description": "OAuth grant type for Checkmarx authentication. Use 'client_credentials' for client ID and secret, or 'refresh_token' for refresh token authentication." + "description": "Name of the Data Collection Endpoint. Override the default if deploying multiple ingestion playbooks into the same resource group to avoid name collisions." + } + }, + "DataCollectionRuleName": { + "type": "string", + "defaultValue": "dcr-checkmarx-audit-ingestion", + "metadata": { + "description": "Name of the Data Collection Rule. Override the default if deploying multiple ingestion playbooks into the same resource group to avoid name collisions." } }, "CheckmarxIAMBaseUrl": { "type": "string", + "defaultValue": "https://us.iam.checkmarx.net", "metadata": { "description": "Checkmarx IAM base URL for authentication (e.g., https://us.iam.checkmarx.net, https://eu.iam.checkmarx.net)" } }, "CheckmarxASTBaseUrl": { "type": "string", + "defaultValue": "https://us.ast.checkmarx.net", "metadata": { "description": "Checkmarx AST base URL for API calls (e.g., https://us.ast.checkmarx.net, https://eu.ast.checkmarx.net)" } @@ -76,34 +105,138 @@ "description": "Checkmarx OAuth Client ID (e.g., ast-app)" } }, - "DCELogsIngestionEndpoint": { + "GrantType": { "type": "string", + "allowedValues": [ + "refresh_token", + "client_credentials" + ], "metadata": { - "description": "Logs Ingestion Endpoint URL from the Data Collection Endpoint (e.g., https://dce-name.region.ingest.monitor.azure.com)" + "description": "OAuth grant type. Use 'refresh_token' with a refresh token stored in Key Vault, or 'client_credentials' with a client secret stored in Key Vault." } }, - "DCRImmutableId": { - "type": "string", + "LookbackDays": { + "type": "int", + "defaultValue": 2, + "minValue": 1, "metadata": { - "description": "Immutable ID of the Audit Logs Data Collection Rule (e.g., dcr-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)" + "description": "Number of days prior to each run to pull audit events from. Default is 2. For the initial backfill, set this higher (up to 365, the Checkmarx retention maximum) to ingest historical events, then reduce for steady-state daily operation. Can be changed later by editing the LookbackDays variable in the Logic App's Initialize_Variables action." } } }, + "variables": { + "tableName": "CheckmarxAuditEvents_CL", + "streamName": "Custom-CheckmarxAuditEvents_CL", + "connectionName": "[concat('keyvault-', parameters('PlaybookName'))]", + "keyVaultRoleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "monitoringMetricsPublisherRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "kvRoleAssignmentDeploymentName": "[concat('kv-role-', uniqueString(parameters('PlaybookName'), parameters('KeyVaultName'), resourceGroup().id))]", + "dcrRoleAssignmentName": "[guid(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName')), parameters('PlaybookName'), 'MonitoringMetricsPublisher')]" + }, "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "apiVersion": "2022-10-01", + "name": "[concat(parameters('WorkspaceName'), '/', variables('tableName'))]", + "properties": { + "totalRetentionInDays": 90, + "plan": "Analytics", + "schema": { + "name": "[variables('tableName')]", + "columns": [ + { "name": "TimeGenerated", "type": "datetime", "description": "Populated by the DCR transform at ingestion. Declared here because Sentinel custom tables require it (MSG 1005). NOT declared in the DCR stream declaration and NOT populated in the Logic App Select \u2014 the transform is the single source of truth." }, + { "name": "EventID", "type": "string" }, + { "name": "EventDate", "type": "datetime", "description": "Date and time of the audit event" }, + { "name": "EventType", "type": "string", "description": "Type of audit event (e.g., events.cxiam.user.account.login)" }, + { "name": "AuditResource", "type": "string", "description": "Resource being audited (e.g., user.account)" }, + { "name": "ActionType", "type": "string", "description": "Type of action performed (e.g., login)" }, + { "name": "ActionUserId", "type": "string", "description": "User ID who performed the action" }, + { "name": "IpAddress", "type": "string", "description": "IP address of the user" }, + { "name": "TenantID", "type": "string" }, + { "name": "UserId", "type": "string", "description": "User ID from data payload" }, + { "name": "Status", "type": "string", "description": "Status of the action (e.g., OK)" }, + { "name": "Username", "type": "string", "description": "Username who performed the action" }, + { "name": "DataJson", "type": "string", "description": "Full JSON data payload" } + ] + } + } + }, + { + "type": "Microsoft.Insights/dataCollectionEndpoints", + "apiVersion": "2022-06-01", + "name": "[parameters('DataCollectionEndpointName')]", + "location": "[parameters('WorkspaceLocation')]", + "properties": { + "networkAcls": { + "publicNetworkAccess": "Enabled" + } + } + }, + { + "type": "Microsoft.Insights/dataCollectionRules", + "apiVersion": "2022-06-01", + "name": "[parameters('DataCollectionRuleName')]", + "location": "[parameters('WorkspaceLocation')]", + "dependsOn": [ + "[resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))]", + "[resourceId('Microsoft.OperationalInsights/workspaces/tables', parameters('WorkspaceName'), variables('tableName'))]" + ], + "properties": { + "dataCollectionEndpointId": "[resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))]", + "streamDeclarations": { + "[variables('streamName')]": { + "columns": [ + { "name": "EventID", "type": "string" }, + { "name": "EventDate", "type": "datetime" }, + { "name": "EventType", "type": "string" }, + { "name": "AuditResource", "type": "string" }, + { "name": "ActionType", "type": "string" }, + { "name": "ActionUserId", "type": "string" }, + { "name": "IpAddress", "type": "string" }, + { "name": "TenantID", "type": "string" }, + { "name": "UserId", "type": "string" }, + { "name": "Status", "type": "string" }, + { "name": "Username", "type": "string" }, + { "name": "DataJson", "type": "string" } + ] + } + }, + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[parameters('WorkspaceResourceId')]", + "name": "LogAnalyticsDestination" + } + ] + }, + "dataFlows": [ + { + "streams": [ + "[variables('streamName')]" + ], + "destinations": [ + "LogAnalyticsDestination" + ], + "transformKql": "source | extend TimeGenerated = now()", + "outputStream": "[variables('streamName')]" + } + ] + } + }, { "type": "Microsoft.Web/connections", "apiVersion": "2016-06-01", - "name": "[concat('keyvault-', parameters('PlaybookName'))]", + "name": "[variables('connectionName')]", "location": "[resourceGroup().location]", "kind": "V1", "properties": { - "displayName": "[concat('keyvault-', parameters('PlaybookName'))]", + "displayName": "[variables('connectionName')]", "parameterValueType": "Alternative", "alternativeParameterValues": { "vaultName": "[parameters('KeyVaultName')]" }, "api": { - "id": "[subscriptionResourceId('Microsoft.Web/locations/managedApis', resourceGroup().location, 'keyvault')]" + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/keyvault')]" } } }, @@ -112,23 +245,19 @@ "apiVersion": "2019-05-01", "name": "[parameters('PlaybookName')]", "location": "[resourceGroup().location]", - "dependsOn": [ - "[resourceId('Microsoft.Web/connections', concat('keyvault-', parameters('PlaybookName')))]" - ], "identity": { "type": "SystemAssigned" }, + "dependsOn": [ + "[resourceId('Microsoft.Web/connections', variables('connectionName'))]", + "[resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))]", + "[resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))]" + ], "properties": { "state": "Disabled", "definition": { "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", "contentVersion": "1.0.0.0", - "parameters": { - "$connections": { - "type": "Object", - "defaultValue": {} - } - }, "triggers": { "Recurrence": { "type": "Recurrence", @@ -139,6 +268,34 @@ } }, "actions": { + "Initialize_Variables": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "AuditPageSize", + "type": "integer", + "value": 1000 + }, + { + "name": "FromDate", + "type": "string", + "value": "[concat('@{addDays(utcNow(), -', parameters('LookbackDays'), ', ''yyyy-MM-ddTHH:mm:ssZ'')}')]" + }, + { + "name": "NextPageUrl", + "type": "string", + "value": "" + }, + { + "name": "CheckmarxASTBaseUrl", + "type": "string", + "value": "[parameters('CheckmarxASTBaseUrl')]" + } + ] + }, + "runAfter": {} + }, "Get_secret": { "type": "ApiConnection", "inputs": { @@ -150,35 +307,8 @@ "method": "get", "path": "[concat('/secrets/@{encodeURIComponent(''', parameters('KeyVaultSecretName'), ''')}/value')]" }, - "runAfter": {}, - "runtimeConfiguration": { - "secureData": { - "properties": [ - "inputs", - "outputs" - ] - } - } - }, - "HTTP_-_Get_Token": { - "type": "Http", - "inputs": { - "uri": "[concat(parameters('CheckmarxIAMBaseUrl'), '/auth/realms/', parameters('CheckmarxTenant'), '/protocol/openid-connect/token')]", - "method": "POST", - "headers": { - "Content-Type": "application/x-www-form-urlencoded" - }, - "body": "[if(equals(parameters('GrantType'), 'client_credentials'), concat('grant_type=client_credentials&client_id=', parameters('CheckmarxClientId'), '&client_secret=@{body(''Get_secret'')?[''value'']}'), concat('grant_type=refresh_token&client_id=', parameters('CheckmarxClientId'), '&refresh_token=@{body(''Get_secret'')?[''value'']}'))]", - "retryPolicy": { - "type": "exponential", - "count": 3, - "interval": "PT10S", - "minimumInterval": "PT10S", - "maximumInterval": "PT1M" - } - }, "runAfter": { - "Get_secret": [ + "Initialize_Variables": [ "Succeeded" ] }, @@ -191,204 +321,198 @@ } } }, - "Initialize_variable_-_AuditOffset": { - "type": "InitializeVariable", - "inputs": { - "variables": [ - { - "name": "AuditOffset", - "type": "integer", - "value": 0 - } - ] - }, - "runAfter": { - "HTTP_-_Get_Token": [ - "Succeeded" - ] - } - }, - "Initialize_variable_-_AuditHasMore": { - "type": "InitializeVariable", + "Set_Variable_-_NextPageUrl_Initial": { + "type": "SetVariable", "inputs": { - "variables": [ - { - "name": "AuditHasMore", - "type": "boolean", - "value": true - } - ] + "name": "NextPageUrl", + "value": "[concat('@{concat(''', parameters('CheckmarxASTBaseUrl'), '/api/audit-events/?startDate='', variables(''FromDate''), ''&offset=0&limit='', variables(''AuditPageSize''))}')]" }, "runAfter": { - "Initialize_variable_-_AuditOffset": [ + "Get_secret": [ "Succeeded" ] } }, "Until_-_Paginate_Audit_Logs": { - "type": "Until", - "expression": "@equals(variables('AuditHasMore'), false)", - "limit": { - "count": 50, - "timeout": "PT1H" - }, - "actions": { - "HTTP_-_Get_Audit_Logs_Page": { - "type": "Http", - "inputs": { - "uri": "[concat(parameters('CheckmarxASTBaseUrl'), '/api/audit?limit=100&offset=@{variables(''AuditOffset'')}&from-date=@{formatDateTime(addDays(utcNow(), -1), ''yyyy-MM-ddTHH:mm:ssZ'')}&to-date=@{formatDateTime(utcNow(), ''yyyy-MM-ddTHH:mm:ssZ'')}')]", - "method": "GET", - "headers": { - "Accept": "application/json", - "Authorization": "Bearer @{body('HTTP_-_Get_Token')?['access_token']}" - }, - "retryPolicy": { - "type": "exponential", - "count": 3, - "interval": "PT10S", - "minimumInterval": "PT10S", - "maximumInterval": "PT1M" - } - }, - "runAfter": {}, - "runtimeConfiguration": { - "secureData": { - "properties": [ - "inputs", - "outputs" - ] - } - } - }, - "Condition_-_Audit_Page_Has_Events": { - "type": "If", - "expression": { - "and": [ - { - "greater": [ - "@length(coalesce(body('HTTP_-_Get_Audit_Logs_Page')?['events'], json('[]')))", - 0 - ] - } - ] + "type": "Until", + "expression": "@equals(variables('NextPageUrl'), '')", + "limit": { + "count": 100, + "timeout": "PT15M" }, "actions": { - "Select_-_Map_Audit_Events": { - "type": "Select", + "HTTP_-_Get_Token": { + "type": "Http", "inputs": { - "from": "@body('HTTP_-_Get_Audit_Logs_Page')?['events']", - "select": { - "TimeGenerated": "@utcNow()", - "EventDate": "@item()?['eventDate']", - "EventType": "@item()?['eventType']", - "AuditResource": "@item()?['auditResource']", - "ActionType": "@item()?['actionType']", - "ActionUserId": "@item()?['actionUserId']", - "IpAddress": "@item()?['ipAddress']", - "UserId": "@item()?['data']?['id']", - "Status": "@item()?['data']?['status']", - "Username": "@item()?['data']?['username']", - "DataJson": "@string(item()?['data'])" + "method": "POST", + "uri": "[concat(parameters('CheckmarxIAMBaseUrl'), '/auth/realms/', parameters('CheckmarxTenant'), '/protocol/openid-connect/token')]", + "headers": { + "Content-Type": "application/x-www-form-urlencoded" + }, + "body": "[if(equals(parameters('GrantType'), 'client_credentials'), concat('grant_type=client_credentials&client_id=', parameters('CheckmarxClientId'), '&client_secret=@{body(''Get_secret'')?[''value'']}'), concat('grant_type=refresh_token&client_id=', parameters('CheckmarxClientId'), '&refresh_token=@{body(''Get_secret'')?[''value'']}'))]", + "retryPolicy": { + "type": "exponential", + "count": 3, + "interval": "PT10S", + "minimumInterval": "PT10S", + "maximumInterval": "PT1M" + } + }, + "runAfter": {}, + "runtimeConfiguration": { + "secureData": { + "properties": [ + "inputs", + "outputs" + ] } } }, - "HTTP_-_Send_Audit_Events_to_DCR": { + "HTTP_-_Get_Audit_Events_Page": { "type": "Http", "inputs": { - "uri": "[concat(parameters('DCELogsIngestionEndpoint'), '/dataCollectionRules/', parameters('DCRImmutableId'), '/streams/Custom-CheckmarxAuditEvents_CL?api-version=2023-01-01')]", - "method": "POST", + "method": "GET", + "uri": "@{variables('NextPageUrl')}", "headers": { - "Content-Type": "application/json" - }, - "body": "@body('Select_-_Map_Audit_Events')", - "authentication": { - "type": "ManagedServiceIdentity", - "audience": "https://monitor.azure.com" + "Accept": "*/*; version=1.0", + "Authorization": "Bearer @{body('HTTP_-_Get_Token')?['access_token']}" }, "retryPolicy": { "type": "exponential", - "count": 4, + "count": 3, "interval": "PT10S", "minimumInterval": "PT10S", "maximumInterval": "PT1M" } }, "runAfter": { - "Select_-_Map_Audit_Events": [ + "HTTP_-_Get_Token": [ "Succeeded" ] + }, + "runtimeConfiguration": { + "secureData": { + "properties": [ + "inputs" + ] + } } - } - }, - "else": { - "actions": {} - }, - "runAfter": { - "HTTP_-_Get_Audit_Logs_Page": [ - "Succeeded" - ] - } - }, - "Set_variable_-_Increment_AuditOffset": { - "type": "IncrementVariable", - "inputs": { - "name": "AuditOffset", - "value": 100 - }, - "runAfter": { - "Condition_-_Audit_Page_Has_Events": [ - "Succeeded" - ] - } - }, - "Condition_-_Check_Audit_Page_Size": { - "type": "If", - "expression": { - "and": [ - { - "less": [ - "@length(coalesce(body('HTTP_-_Get_Audit_Logs_Page')?['events'], json('[]')))", - 100 + }, + "Condition_-_Audit_Page_Has_Events": { + "type": "If", + "expression": { + "and": [ + { + "greater": [ + "@length(coalesce(body('HTTP_-_Get_Audit_Events_Page')?['events'], json('[]')))", + 0 + ] + } + ] + }, + "actions": { + "Select_-_Audit_Events": { + "type": "Select", + "inputs": { + "from": "@body('HTTP_-_Get_Audit_Events_Page')?['events']", + "select": { + "EventID": "@item()?['eventID']", + "EventDate": "@item()?['eventDate']", + "EventType": "@item()?['eventType']", + "AuditResource": "@item()?['auditResource']", + "ActionType": "@item()?['actionType']", + "ActionUserId": "@item()?['actionUserId']", + "IpAddress": "@coalesce(item()?['ipAddress'], '')", + "TenantID": "@item()?['tenantID']", + "UserId": "@item()?['data']?['id']", + "Status": "@item()?['data']?['status']", + "Username": "@item()?['data']?['username']", + "DataJson": "@string(item()?['data'])" + } + }, + "runAfter": {} + }, + "HTTP_-_Send_Audit_Events_to_DCR": { + "type": "Http", + "inputs": { + "method": "POST", + "uri": "[concat(reference(resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))).logsIngestion.endpoint, '/dataCollectionRules/', reference(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))).immutableId, '/streams/', variables('streamName'), '?api-version=2023-01-01')]", + "headers": { + "Content-Type": "application/json" + }, + "body": "@body('Select_-_Audit_Events')", + "authentication": { + "type": "ManagedServiceIdentity", + "audience": "https://monitor.azure.com" + }, + "retryPolicy": { + "type": "exponential", + "count": 4, + "interval": "PT10S", + "minimumInterval": "PT10S", + "maximumInterval": "PT1M" + } + }, + "runAfter": { + "Select_-_Audit_Events": [ + "Succeeded" + ] + } + } + }, + "else": { + "actions": {} + }, + "runAfter": { + "HTTP_-_Get_Audit_Events_Page": [ + "Succeeded" ] } - ] - }, - "actions": { - "Set_variable_-_AuditHasMore_False": { + }, + "Compose_-_NextRelativeHref": { + "type": "Compose", + "inputs": "@coalesce(body('HTTP_-_Get_Audit_Events_Page')?['Links']?['_links']?['next']?['href'], '')", + "runAfter": { + "Condition_-_Audit_Page_Has_Events": [ + "Succeeded" + ] + } + }, + "Set_Variable_-_NextPageUrl": { "type": "SetVariable", "inputs": { - "name": "AuditHasMore", - "value": false + "name": "NextPageUrl", + "value": "@if(empty(outputs('Compose_-_NextRelativeHref')), '', concat(variables('CheckmarxASTBaseUrl'), outputs('Compose_-_NextRelativeHref')))" }, - "runAfter": {} + "runAfter": { + "Compose_-_NextRelativeHref": [ + "Succeeded" + ] + } } }, - "else": { - "actions": {} - }, "runAfter": { - "Set_variable_-_Increment_AuditOffset": [ + "Set_Variable_-_NextPageUrl_Initial": [ "Succeeded" ] } } - }, - "runAfter": { - "Initialize_variable_-_AuditHasMore": [ - "Succeeded" - ] - } - } }, - "outputs": {} + "outputs": {}, + "parameters": { + "$connections": { + "type": "Object", + "defaultValue": {} + } + } }, "parameters": { "$connections": { "value": { "keyvault": { - "id": "[subscriptionResourceId('Microsoft.Web/locations/managedApis', resourceGroup().location, 'keyvault')]", - "connectionId": "[resourceId('Microsoft.Web/connections', concat('keyvault-', parameters('PlaybookName')))]", - "connectionName": "[concat('keyvault-', parameters('PlaybookName'))]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/keyvault')]", + "connectionId": "[resourceId('Microsoft.Web/connections', variables('connectionName'))]", + "connectionName": "[variables('connectionName')]", "connectionProperties": { "authentication": { "type": "ManagedServiceIdentity" @@ -399,20 +523,114 @@ } } } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))]", + "name": "[variables('dcrRoleAssignmentName')]", + "dependsOn": [ + "[resourceId('Microsoft.Logic/workflows', parameters('PlaybookName'))]", + "[resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))]" + ], + "properties": { + "roleDefinitionId": "[variables('monitoringMetricsPublisherRoleId')]", + "principalId": "[reference(resourceId('Microsoft.Logic/workflows', parameters('PlaybookName')), '2019-05-01', 'Full').identity.principalId]", + "principalType": "ServicePrincipal" + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[variables('kvRoleAssignmentDeploymentName')]", + "resourceGroup": "[parameters('KeyVaultResourceGroup')]", + "dependsOn": [ + "[resourceId('Microsoft.Logic/workflows', parameters('PlaybookName'))]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "KeyVaultName": { + "value": "[parameters('KeyVaultName')]" + }, + "PrincipalId": { + "value": "[reference(resourceId('Microsoft.Logic/workflows', parameters('PlaybookName')), '2019-05-01', 'Full').identity.principalId]" + }, + "RoleDefinitionId": { + "value": "[variables('keyVaultRoleDefinitionId')]" + }, + "RoleAssignmentName": { + "value": "[guid(parameters('KeyVaultName'), parameters('PlaybookName'), 'KeyVaultSecretsUser')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "KeyVaultName": { + "type": "string" + }, + "PrincipalId": { + "type": "string" + }, + "RoleDefinitionId": { + "type": "string" + }, + "RoleAssignmentName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/providers/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[concat(parameters('KeyVaultName'), '/Microsoft.Authorization/', parameters('RoleAssignmentName'))]", + "properties": { + "roleDefinitionId": "[parameters('RoleDefinitionId')]", + "principalId": "[parameters('PrincipalId')]", + "principalType": "ServicePrincipal" + } + } + ] + } + } } ], "outputs": { - "logicAppName": { + "playbookName": { "type": "string", "value": "[parameters('PlaybookName')]" }, - "logicAppResourceId": { + "tableName": { + "type": "string", + "value": "[variables('tableName')]" + }, + "streamName": { + "type": "string", + "value": "[variables('streamName')]" + }, + "dataCollectionEndpointId": { + "type": "string", + "value": "[resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))]" + }, + "dataCollectionRuleId": { + "type": "string", + "value": "[resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))]" + }, + "dcrImmutableId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName'))).immutableId]" + }, + "logsIngestionEndpoint": { "type": "string", - "value": "[resourceId('Microsoft.Logic/workflows', parameters('PlaybookName'))]" + "value": "[reference(resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName'))).logsIngestion.endpoint]" }, - "logicAppPrincipalId": { + "managedIdentityPrincipalId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Logic/workflows', parameters('PlaybookName')), '2019-05-01', 'full').identity.principalId]" + "value": "[reference(resourceId('Microsoft.Logic/workflows', parameters('PlaybookName')), '2019-05-01', 'Full').identity.principalId]" } } -} +} \ No newline at end of file