diff --git a/Solutions/Salesforce Service Cloud/Data Connectors/SalesforceServiceCloud_API_FunctionApp.json b/Solutions/Salesforce Service Cloud/Data Connectors/SalesforceServiceCloud_API_FunctionApp.json index 26fb37a9b99..de8cbaa4c27 100644 --- a/Solutions/Salesforce Service Cloud/Data Connectors/SalesforceServiceCloud_API_FunctionApp.json +++ b/Solutions/Salesforce Service Cloud/Data Connectors/SalesforceServiceCloud_API_FunctionApp.json @@ -79,7 +79,7 @@ "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." }, { - "description":"**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Salesforce%20Service%20Cloud/Parsers/SalesforceServiceCloud.txt). The function usually takes 10-15 minutes to activate after solution installation/update." + "description":"**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://aka.ms/sentinel-SalesforceServiceCloud-parser). The function usually takes 10-15 minutes to activate after solution installation/update." }, { "title": "", @@ -114,21 +114,40 @@ ] }, { - "title": "Option 1 - Azure Resource Manager (ARM) Template", - "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy." - }, - { - "title": "Option 2 - Manual Deployment of Azure Functions", - "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code)." - }, - { - "title": "", - "description": "**1. Deploy a Function App**\n\n> NOTE:You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. SalesforceXXXXX).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." - }, - { - "title": "", - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n3. Once all application settings have been entered, click **Save**." - - } - ] -} + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "**NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration.\n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n5. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] +} \ No newline at end of file diff --git a/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json b/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json index 156f95e1ca0..34b1a4eb4d1 100644 --- a/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json +++ b/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json @@ -12,13 +12,13 @@ "Data Connectors/SalesforceServiceCloud_API_FunctionApp.json" ], "Parsers": [ - "Parsers/SalesforceServiceCloud.txt" + "Parsers/SalesforceServiceCloud.yaml" ], "Workbooks": [ "Workbooks/SalesforceServiceCloud.json" ], "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Salesforce Service Cloud", - "Version": "2.0.4", + "Version": "3.0.0", "Metadata": "SolutionMetadata.json", "TemplateSpec": true, "Is1PConnector": false diff --git a/Solutions/Salesforce Service Cloud/Data/system_generated_metadata.json b/Solutions/Salesforce Service Cloud/Data/system_generated_metadata.json new file mode 100644 index 00000000000..0834e9ec209 --- /dev/null +++ b/Solutions/Salesforce Service Cloud/Data/system_generated_metadata.json @@ -0,0 +1,33 @@ +{ + "Name": "Salesforce Service Cloud", + "Author": "Microsoft - support@microsoft.com", + "Logo": "", + "Description": "The [Salesforce Service Cloud](https://www.salesforce.com/in/products/service-cloud/overview/) solution for Microsoft Sentinel enables you to ingest Service Cloud events into Microsoft Sentinel.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api)\r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview).", + "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Salesforce Service Cloud", + "Version": "3.0.0", + "Metadata": "SolutionMetadata.json", + "TemplateSpec": true, + "Is1PConnector": false, + "publisherId": "azuresentinel", + "offerId": "azure-sentinel-solution-salesforceservicecloud", + "providers": [ + "Salesforce" + ], + "categories": { + "domains": [ + "Cloud Provider" + ], + "verticals": [] + }, + "firstPublishDate": "2022-05-16", + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com/" + }, + "Data Connectors": "[\n \"Data Connectors/SalesforceServiceCloud_API_FunctionApp.json\"\n]", + "Parsers": "[\n \"SalesforceServiceCloud.yaml\"\n]", + "Workbooks": "[\n \"Workbooks/SalesforceServiceCloud.json\"\n]", + "Analytic Rules": "[\n \"Salesforce-BruteForce.yaml\",\n \"Salesforce-PasswordSpray.yaml\",\n \"Salesforce-SigninsMultipleCountries.yaml\"\n]" +} diff --git a/Solutions/Salesforce Service Cloud/Package/3.0.0.zip b/Solutions/Salesforce Service Cloud/Package/3.0.0.zip new file mode 100644 index 00000000000..381920a886d Binary files /dev/null and b/Solutions/Salesforce Service Cloud/Package/3.0.0.zip differ diff --git a/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json b/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json index 66d3f3ad677..f91cea274c2 100644 --- a/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json +++ b/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json @@ -6,7 +6,7 @@ "config": { "isWizard": false, "basics": { - "description": "\n\n**Note:** _There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing._\n\nThe [Salesforce Service Cloud](https://www.salesforce.com/in/products/service-cloud/overview/) solution for Microsoft Sentinel enables you to ingest Service Cloud events into Microsoft Sentinel.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api)\r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview).\n\n**Data Connectors:** 1, **Parsers:** 1, **Workbooks:** 1, **Analytic Rules:** 3\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \r \n • Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Salesforce%20Service%20Cloud/ReleaseNotes.md)\r \n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Salesforce Service Cloud](https://www.salesforce.com/in/products/service-cloud/overview/) solution for Microsoft Sentinel enables you to ingest Service Cloud events into Microsoft Sentinel.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api)\r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview).\n\n**Data Connectors:** 1, **Parsers:** 1, **Workbooks:** 1, **Analytic Rules:** 3\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", "subscription": { "resourceProviders": [ "Microsoft.OperationsManagement/solutions", @@ -60,14 +60,14 @@ "name": "dataconnectors1-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This Solution installs the data connector for Salesforce Service Cloud. You can get Salesforce Service Cloud custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." + "text": "The Salesforce Service Cloud data connector provides the capability to ingest information about your Salesforce operational events into Microsoft Sentinel through the REST API. The connector provides the ability to review events in your org on an accelerated basis and get event log files in hourly increments for recent activity. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." } }, { "name": "dataconnectors-parser-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The Solution installs a parser that transforms the ingested data into Microsoft Sentinel normalized format. The normalized format enables better correlation of different types of data from different data sources to drive end-to-end outcomes seamlessly in security monitoring, hunting, incident investigation and response scenarios in Microsoft Sentinel." + "text": "The solution installs a parser that transforms ingested data. The transformed logs can be accessed using the SalesforceServiceCloud Kusto Function alias." } }, { diff --git a/Solutions/Salesforce Service Cloud/Package/mainTemplate.json b/Solutions/Salesforce Service Cloud/Package/mainTemplate.json index 7f281d5c0f2..b114a3242f1 100644 --- a/Solutions/Salesforce Service Cloud/Package/mainTemplate.json +++ b/Solutions/Salesforce Service Cloud/Package/mainTemplate.json @@ -42,140 +42,236 @@ "_solutionId": "[variables('solutionId')]", "email": "support@microsoft.com", "_email": "[variables('email')]", - "analyticRuleVersion1": "1.0.1", - "analyticRulecontentId1": "5a6ce089-e756-40fb-b022-c8e8864a973a", - "_analyticRulecontentId1": "[variables('analyticRulecontentId1')]", - "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId1'))]", - "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId1')))]", - "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", - "analyticRuleVersion2": "1.0.1", - "analyticRulecontentId2": "64d16e62-1a17-4a35-9ea7-2b9fe6f07118", - "_analyticRulecontentId2": "[variables('analyticRulecontentId2')]", - "analyticRuleId2": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId2'))]", - "analyticRuleTemplateSpecName2": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId2')))]", - "analyticRuleVersion3": "1.0.1", - "analyticRulecontentId3": "3094e036-e5ae-4d6e-8626-b0f86ebc71f2", - "_analyticRulecontentId3": "[variables('analyticRulecontentId3')]", - "analyticRuleId3": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId3'))]", - "analyticRuleTemplateSpecName3": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId3')))]", + "_solutionName": "Salesforce Service Cloud", + "_solutionVersion": "3.0.0", "uiConfigId1": "SalesforceServiceCloud", "_uiConfigId1": "[variables('uiConfigId1')]", "dataConnectorContentId1": "SalesforceServiceCloud", "_dataConnectorContentId1": "[variables('dataConnectorContentId1')]", "dataConnectorId1": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", "_dataConnectorId1": "[variables('dataConnectorId1')]", - "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1')))]", + "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", "dataConnectorVersion1": "1.0.0", - "parserVersion1": "1.0.0", - "parserContentId1": "SalesforceServiceCloud-Parser", - "_parserContentId1": "[variables('parserContentId1')]", + "_dataConnectorcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId1'),'-', variables('dataConnectorVersion1'))))]", "parserName1": "SalesforceServiceCloud", "_parserName1": "[concat(parameters('workspace'),'/',variables('parserName1'))]", "parserId1": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", "_parserId1": "[variables('parserId1')]", - "parserTemplateSpecName1": "[concat(parameters('workspace'),'-pr-',uniquestring(variables('_parserContentId1')))]", + "parserTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-pr-',uniquestring(variables('_parserContentId1'))))]", + "parserVersion1": "1.0.0", + "parserContentId1": "SalesforceServiceCloud-Parser", + "_parserContentId1": "[variables('parserContentId1')]", + "_parsercontentProductId1": "[concat(take(variables('_solutionId'),50),'-','pr','-', uniqueString(concat(variables('_solutionId'),'-','Parser','-',variables('_parserContentId1'),'-', variables('parserVersion1'))))]", "workbookVersion1": "1.0.0", "workbookContentId1": "SalesforceServiceCloudWorkbook", "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", - "workbookTemplateSpecName1": "[concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1')))]", - "_workbookContentId1": "[variables('workbookContentId1')]" + "workbookTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1'))))]", + "_workbookContentId1": "[variables('workbookContentId1')]", + "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", + "_workbookcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','wb','-', uniqueString(concat(variables('_solutionId'),'-','Workbook','-',variables('_workbookContentId1'),'-', variables('workbookVersion1'))))]", + "analyticRuleVersion1": "1.0.1", + "analyticRulecontentId1": "5a6ce089-e756-40fb-b022-c8e8864a973a", + "_analyticRulecontentId1": "[variables('analyticRulecontentId1')]", + "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId1'))]", + "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId1'))))]", + "_analyticRulecontentProductId1": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId1'),'-', variables('analyticRuleVersion1'))))]", + "analyticRuleVersion2": "1.0.1", + "analyticRulecontentId2": "64d16e62-1a17-4a35-9ea7-2b9fe6f07118", + "_analyticRulecontentId2": "[variables('analyticRulecontentId2')]", + "analyticRuleId2": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId2'))]", + "analyticRuleTemplateSpecName2": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId2'))))]", + "_analyticRulecontentProductId2": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId2'),'-', variables('analyticRuleVersion2'))))]", + "analyticRuleVersion3": "1.0.1", + "analyticRulecontentId3": "3094e036-e5ae-4d6e-8626-b0f86ebc71f2", + "_analyticRulecontentId3": "[variables('analyticRulecontentId3')]", + "analyticRuleId3": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId3'))]", + "analyticRuleTemplateSpecName3": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId3'))))]", + "_analyticRulecontentProductId3": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId3'),'-', variables('analyticRuleVersion3'))))]", + "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" }, "resources": [ { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('analyticRuleTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Salesforce Service Cloud Analytics Rule 1 with template", - "displayName": "Salesforce Service Cloud Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName1'),'/',variables('analyticRuleVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('dataConnectorTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Salesforce-BruteForce_AnalyticalRules Analytics Rule with template version 2.0.4", + "description": "Salesforce Service Cloud data connector with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion1')]", + "contentVersion": "[variables('dataConnectorVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId1')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", "location": "[parameters('workspace-location')]", + "kind": "GenericUI", "properties": { - "description": "Identifies evidence of brute force activity against a user based on multiple authentication failures \nand at least one successful authentication within a given time window. This query limits IPAddresses to 100 and may not potentially cover all IPAddresses\nThe default failure threshold is 10, success threshold is 1, and the default time window is 20 minutes.", - "displayName": "Brute force attack against user credentials", - "enabled": false, - "query": "let failureCountThreshold = 10;\nlet successCountThreshold = 1;\nlet Failures =\nSalesforceServiceCloud\n| where EventType == \"Login\" and LoginStatus != \"LOGIN_NO_ERROR\"\n| summarize\n FailureStartTime = min(TimeGenerated),\n FailureEndTime = max(TimeGenerated),\n IpAddresses = make_set (ClientIp, 100),\n FailureCount = count() by User, UserId, UserType;\n SalesforceServiceCloud\n | where EventType == \"Login\" and LoginStatus == \"LOGIN_NO_ERROR\"\n | summarize\n SuccessStartTime = min(TimeGenerated),\n SuccessEndTime = max(TimeGenerated),\n IpAddresses = make_set (ClientIp, 100),\n SuccessCount = count() by User, UserId, UserType\n | join kind=leftouter Failures on UserId\n | where FailureCount >= failureCountThreshold and SuccessCount >= successCountThreshold\n | where FailureEndTime < SuccessStartTime\n | project User, EventStartTime = FailureStartTime, EventEndTime = SuccessEndTime, IpAddresses\n", - "queryFrequency": "PT20M", - "queryPeriod": "PT20M", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "dataTypes": [ - "SalesforceServiceCloud" - ], - "connectorId": "SalesforceServiceCloud" - } - ], - "tactics": [ - "CredentialAccess" - ], - "techniques": [ - "T1110" - ], - "entityMappings": [ - { - "fieldMappings": [ + "connectorUiConfig": { + "id": "[variables('_uiConfigId1')]", + "title": "Salesforce Service Cloud (using Azure Functions)", + "publisher": "Salesforce", + "descriptionMarkdown": "The Salesforce Service Cloud data connector provides the capability to ingest information about your Salesforce operational events into Microsoft Sentinel through the REST API. The connector provides ability to review events in your org on an accelerated basis, get [event log files](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/event_log_file_hourly_overview.htm) in hourly increments for recent activity.", + "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution.", + "graphQueries": [ + { + "metricName": "Total data received", + "legend": "SalesforceServiceCloud_CL", + "baseQuery": "SalesforceServiceCloud_CL" + } + ], + "sampleQueries": [ + { + "description": "Last Salesforce Service Cloud EventLogFile Events", + "query": "SalesforceServiceCloud\n | sort by TimeGenerated desc" + } + ], + "dataTypes": [ + { + "name": "SalesforceServiceCloud_CL", + "lastDataReceivedQuery": "SalesforceServiceCloud_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" + } + ], + "connectivityCriterias": [ + { + "type": "IsConnectedQuery", + "value": [ + "SalesforceServiceCloud_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(30d)" + ] + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ + { + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, { - "columnName": "User", - "identifier": "FullName" + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true + } } ], - "entityType": "Account" - } - ], - "customDetails": { - "EventStartTime": "FailureStartTime", - "EventEndTime": "SuccessEndTime", - "IPAddresses": "IpAddresses" + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "REST API Credentials/permissions", + "description": "**Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** is required for REST API. [See the documentation to learn more about API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm)." + } + ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Salesforce Lightning Platform REST API to pull its logs into Microsoft Sentinel. This might result in additional data ingestion costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) for details." + }, + { + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": "**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://aka.ms/sentinel-SalesforceServiceCloud-parser). The function usually takes 10-15 minutes to activate after solution installation/update." + }, + { + "description": "**STEP 1 - Configuration steps for the Salesforce Lightning Platform REST API**\n\n1. See the [link](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm) and follow the instructions for obtaining Salesforce API Authorization credentials. \n2. On the **Set Up Authorization** step choose **Session ID Authorization** method.\n3. You must provide your client id, client secret, username, and password with user security token." + }, + { + "description": ">**NOTE:** Ingesting data from on an hourly interval may require additional licensing based on the edition of the Salesforce Service Cloud being used. Please refer to [Salesforce documentation](https://www.salesforce.com/editions-pricing/service-cloud/) and/or support for more details." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the Salesforce Service Cloud data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Salesforce API Authorization credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" + }, + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" + } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "**NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration.\n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n5. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] } } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "properties": { - "description": "Salesforce Service Cloud Analytics Rule 1", - "parentId": "[variables('analyticRuleId1')]", - "contentId": "[variables('_analyticRulecontentId1')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion1')]", + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", "source": { "kind": "Solution", "name": "Salesforce Service Cloud", @@ -194,199 +290,240 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_dataConnectorContentId1')]", + "contentKind": "DataConnector", + "displayName": "Salesforce Service Cloud (using Azure Functions)", + "contentProductId": "[variables('_dataConnectorcontentProductId1')]", + "id": "[variables('_dataConnectorcontentProductId1')]", + "version": "[variables('dataConnectorVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('analyticRuleTemplateSpecName2')]", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "dependsOn": [ + "[variables('_dataConnectorId1')]" + ], "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "properties": { - "description": "Salesforce Service Cloud Analytics Rule 2 with template", - "displayName": "Salesforce Service Cloud Analytics Rule template" + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", + "source": { + "kind": "Solution", + "name": "Salesforce Service Cloud", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com/" + } } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName2'),'/',variables('analyticRuleVersion2'))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName2'))]" - ], + "kind": "GenericUI", "properties": { - "description": "Salesforce-PasswordSpray_AnalyticalRules Analytics Rule with template version 2.0.4", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion2')]", - "parameters": {}, - "variables": {}, - "resources": [ + "connectorUiConfig": { + "title": "Salesforce Service Cloud (using Azure Functions)", + "publisher": "Salesforce", + "descriptionMarkdown": "The Salesforce Service Cloud data connector provides the capability to ingest information about your Salesforce operational events into Microsoft Sentinel through the REST API. The connector provides ability to review events in your org on an accelerated basis, get [event log files](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/event_log_file_hourly_overview.htm) in hourly increments for recent activity.", + "graphQueries": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId2')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", - "location": "[parameters('workspace-location')]", - "properties": { - "description": "This query searches for failed attempts to log in from more than 15 various users within a 5 minute timeframe from the same source. This is a potential indication of a password spray attack.", - "displayName": "Potential Password Spray Attack", - "enabled": false, - "query": "let FailureThreshold = 15; \nSalesforceServiceCloud\n| where EventType =~ 'Login' and LoginStatus != 'LOGIN_NO_ERROR'\n| where LoginStatus in~ ('LOGIN_ERROR_INVALID_PASSWORD', 'LOGIN_ERROR_SSO_PWD_INVALID')\n| summarize UserCount=dcount(UserId), Users = make_set(UserId,100) by ClientIp, bin(TimeGenerated, 5m)\n| where UserCount > FailureThreshold\n", - "queryFrequency": "PT5M", - "queryPeriod": "PT5M", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "dataTypes": [ - "SalesforceServiceCloud" - ], - "connectorId": "SalesforceServiceCloud" - } - ], - "tactics": [ - "CredentialAccess" - ], - "techniques": [ - "T1110" - ], - "entityMappings": [ - { - "fieldMappings": [ - { - "columnName": "ClientIp", - "identifier": "Address" - } - ], - "entityType": "IP" - } - ], - "customDetails": { - "Users": "Users" + "metricName": "Total data received", + "legend": "SalesforceServiceCloud_CL", + "baseQuery": "SalesforceServiceCloud_CL" + } + ], + "dataTypes": [ + { + "name": "SalesforceServiceCloud_CL", + "lastDataReceivedQuery": "SalesforceServiceCloud_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" + } + ], + "connectivityCriterias": [ + { + "type": "IsConnectedQuery", + "value": [ + "SalesforceServiceCloud_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(30d)" + ] + } + ], + "sampleQueries": [ + { + "description": "Last Salesforce Service Cloud EventLogFile Events", + "query": "SalesforceServiceCloud\n | sort by TimeGenerated desc" + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ + { + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, + { + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true } } + ], + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "REST API Credentials/permissions", + "description": "**Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** is required for REST API. [See the documentation to learn more about API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm)." + } + ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Salesforce Lightning Platform REST API to pull its logs into Microsoft Sentinel. This might result in additional data ingestion costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) for details." }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", - "properties": { - "description": "Salesforce Service Cloud Analytics Rule 2", - "parentId": "[variables('analyticRuleId2')]", - "contentId": "[variables('_analyticRulecontentId2')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion2')]", - "source": { - "kind": "Solution", - "name": "Salesforce Service Cloud", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": "**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://aka.ms/sentinel-SalesforceServiceCloud-parser). The function usually takes 10-15 minutes to activate after solution installation/update." + }, + { + "description": "**STEP 1 - Configuration steps for the Salesforce Lightning Platform REST API**\n\n1. See the [link](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm) and follow the instructions for obtaining Salesforce API Authorization credentials. \n2. On the **Set Up Authorization** step choose **Session ID Authorization** method.\n3. You must provide your client id, client secret, username, and password with user security token." + }, + { + "description": ">**NOTE:** Ingesting data from on an hourly interval may require additional licensing based on the edition of the Salesforce Service Cloud being used. Please refer to [Salesforce documentation](https://www.salesforce.com/editions-pricing/service-cloud/) and/or support for more details." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the Salesforce Service Cloud data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Salesforce API Authorization credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com/" + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" } - } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "**NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration.\n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n5. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] } - ] + ], + "id": "[variables('_uiConfigId1')]", + "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution." } } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('analyticRuleTemplateSpecName3')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Salesforce Service Cloud Analytics Rule 3 with template", - "displayName": "Salesforce Service Cloud Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName3'),'/',variables('analyticRuleVersion3'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('parserTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName3'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Salesforce-SigninsMultipleCountries_AnalyticalRules Analytics Rule with template version 2.0.4", + "description": "SalesforceServiceCloud Data Parser with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion3')]", + "contentVersion": "[variables('parserVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId3')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "name": "[variables('_parserName1')]", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", "location": "[parameters('workspace-location')]", "properties": { - "description": "This query searches for successful user logins from different countries within 30min.", - "displayName": "User Sign in from different countries", - "enabled": false, - "query": "let threshold = 2;\nlet Countrydb = externaldata(Network:string, geoname_id:string, continent_code:string, continent_name:string, country_iso_code:string, country_name:string)\n[@\"https://raw.githubusercontent.com/datasets/geoip2-ipv4/master/data/geoip2-ipv4.csv\"];\nlet UsersLocation = SalesforceServiceCloud\n| where EventType =~ 'Login' and LoginStatus=~'LOGIN_NO_ERROR'\n| project TimeGenerated, ClientIp, UserId, User, UserType ;\nUsersLocation\n| extend Dummy=1\n| summarize count() by Hour=bin(TimeGenerated,30m), ClientIp,User, Dummy\n| partition by Hour(\n lookup (Countrydb|extend Dummy=1) on Dummy\n | where ipv4_is_match(ClientIp, Network)\n )\n| summarize NumOfCountries = dcount(country_name) by User, Hour\n| where NumOfCountries >= threshold\n", - "queryFrequency": "PT30M", - "queryPeriod": "PT30M", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "dataTypes": [ - "SalesforceServiceCloud" - ], - "connectorId": "SalesforceServiceCloud" - } - ], - "tactics": [ - "InitialAccess" - ], - "techniques": [ - "T1078" - ], - "entityMappings": [ + "eTag": "*", + "displayName": "SalesforceServiceCloud", + "category": "Microsoft Sentinel Parser", + "functionAlias": "SalesforceServiceCloud", + "query": "SalesforceServiceCloud_CL \n| extend \n\t\tRequestSize=column_ifexists('request_size_s',''),\n\t\tExecTime=column_ifexists('exec_time_s',''),\n\t\tAction=column_ifexists('action_s',''),\n\t\tPlatformType=column_ifexists('platform_type_s',''),\n\t\tOsName=column_ifexists('os_name_s',''),\n\t\tOsVersion=column_ifexists('os_version_s',''),\n\t\tTimestamp=column_ifexists('timestamp_s',''),\n\t\tStatusCode=column_ifexists('status_code_s',''),\n\t\tEventType=column_ifexists('event_type_s',''),\n\t\tReferrerUri=column_ifexists('referrer_uri_s',''),\n\t\tUserAgent=column_ifexists('user_agent_s',''),\n\t\tBrowserType=column_ifexists('browser_type_s',''),\n\t\tTime=column_ifexists('time_s',''),\n\t\tResponseSize=column_ifexists('response_size_s',''),\n\t\tDeviceId=column_ifexists('device_id_s',''),\n\t\tDeviceModel=column_ifexists('device_model_s',''),\n\t\tSourceIp=column_ifexists('source_ip_s',''),\n\t\tClientIp=column_ifexists('client_ip_s',''),\n\t\tSuccess=column_ifexists('success_s',''),\n\t\tUri=column_ifexists('uri_s',''),\n\t\tUrl=column_ifexists('url_s',''),\n\t\tClientName=column_ifexists('client_name_s',''),\n\t\tUserType=column_ifexists('user_type_s',''),\n\t\tUserInitiatedLogout=column_ifexists('user_initiated_logout_s',''),\n\t\tUserIdDerived=column_ifexists('user_id_derived_s',''),\n\t\tUserId=column_ifexists('user_id_s',''),\n\t\tUserEmail=column_ifexists('user_email_s',''),\n\t\tUser=column_ifexists('user_name_s',''),\n\t\tUriIdDerived=column_ifexists('uri_id_derived_s',''),\n\t\tUiEventType=column_ifexists('ui_event_type_s',''),\n\t\tUiEventTimestamp=column_ifexists('ui_event_timestamp_s',''),\n\t\tUiEventSource=column_ifexists('ui_event_source_s',''),\n\t\tUiEventSequenceNum=column_ifexists('ui_event_sequence_num_s',''),\n\t\tUiEventId=column_ifexists('ui_event_id_s',''),\n\t\tTlsProtocol=column_ifexists('tls_protocol_s',''),\n\t\tTimestampDerived=column_ifexists('timestamp_derived_t',''),\n\t\tTargetUiElement=column_ifexists('target_ui_element_s',''),\n\t\tSort=column_ifexists('sort_s',''),\n\t\tSessionType=column_ifexists('session_type_s',''),\n\t\tSessionLevel=column_ifexists('session_level_s',''),\n\t\tSessionKey=column_ifexists('session_key_s',''),\n\t\tSearchQuery=column_ifexists('search_query_s',''),\n\t\tSdkVersion=column_ifexists('sdk_version_s',''),\n\t\tSdkAppVersion=column_ifexists('sdk_app_version_s',''),\n\t\tSdkAppType=column_ifexists('sdk_app_type_s',''),\n\t\tRunTime=column_ifexists('run_time_s',''),\n\t\tRowsProcessed=column_ifexists('rows_processed_s',''),\n\t\tRowCount=column_ifexists('row_count_s',''),\n\t\tResolutionType=column_ifexists('resolution_type_s',''),\n\t\tRequestStatus=column_ifexists('request_status_s',''),\n\t\tRequestId=column_ifexists('request_id_s',''),\n\t\tReportIdDerived=column_ifexists('report_id_derived_s',''),\n\t\tReportId=column_ifexists('report_id_s',''),\n\t\tRenderingType=column_ifexists('rendering_type_s',''),\n\t\tRelatedList=column_ifexists('related_list_s',''),\n\t\tRecordType=column_ifexists('record_type_s',''),\n\t\tRecordId=column_ifexists('record_id_s',''),\n\t\tQuiddity=column_ifexists('quiddity_s',''),\n\t\tQueryId=column_ifexists('query_id_s',''),\n\t\tPrevpageUrl=column_ifexists('prevpage_url_s',''),\n\t\tPrevpageEntityType=column_ifexists('prevpage_entity_type_s',''),\n\t\tPrevpageEntityId=column_ifexists('prevpage_entity_id_s',''),\n\t\tPrevpageContext=column_ifexists('prevpage_context_s',''),\n\t\tPrevpageAppName=column_ifexists('prevpage_app_name_s',''),\n\t\tPrefixesSearched=column_ifexists('prefixes_searched_s',''),\n\t\tParentUiElement=column_ifexists('parent_ui_element_s',''),\n\t\tPageUrl=column_ifexists('page_url_s',''),\n\t\tPageStartTime=column_ifexists('page_start_time_s',''),\n\t\tPageEntityType=column_ifexists('page_entity_type_s',''),\n\t\tPageEntityId=column_ifexists('page_entity_id_s',''),\n\t\tPageContext=column_ifexists('page_context_s',''),\n\t\tPageAppName=column_ifexists('page_app_name_s',''),\n\t\tOrigin=column_ifexists('origin_s',''),\n\t\tOrganizationId=column_ifexists('organization_id_s',''),\n\t\tNumResults=column_ifexists('num_results_s',''),\n\t\tNumberSoqlQueries=column_ifexists('number_soql_queries_s',''),\n\t\tNumberFields=column_ifexists('number_fields_s',''),\n\t\tNumberExceptionFilters=column_ifexists('number_exception_filters_s',''),\n\t\tNumberColumns=column_ifexists('number_columns_s',''),\n\t\tNumberBuckets=column_ifexists('number_buckets_s',''),\n\t\tMethodName=column_ifexists('method_name_s',''),\n\t\tMethod=column_ifexists('method_s',''),\n\t\tMediaType=column_ifexists('media_type_s',''),\n\t\tLoginStatus=column_ifexists('login_status_s',''),\n\t\tLoginKey=column_ifexists('login_key_s',''),\n\t\tHttpMethod=column_ifexists('http_method_s',''),\n\t\tGrandparentUiElement=column_ifexists('grandparent_ui_element_s',''),\n\t\tEntryPoint=column_ifexists('entry_point_s',''),\n\t\tEntityName=column_ifexists('entity_name_s',''),\n\t\tEntity=column_ifexists('entity_s',''),\n\t\tEffectivePageTime=column_ifexists('effective_page_time_s',''),\n\t\tDuration=column_ifexists('duration_s',''),\n\t\tDisplayType=column_ifexists('display_type_s',''),\n\t\tDeviceSessionId=column_ifexists('device_session_id_s',''),\n\t\tDevicePlatform=column_ifexists('device_platform_s',''),\n\t\tDbTotalTime=column_ifexists('db_total_time_s',''),\n\t\tDbCpuTime=column_ifexists('db_cpu_time_s',''),\n\t\tDbBlocks=column_ifexists('db_blocks_s',''),\n\t\tCpuTime=column_ifexists('cpu_time_s',''),\n\t\tConnectionType=column_ifexists('connection_type_s',''),\n\t\tComponentName=column_ifexists('component_name_s',''),\n\t\tClientVersion=column_ifexists('client_version_s',''),\n\t\tClientId=column_ifexists('client_id_s',''),\n\t\tCipherSuite=column_ifexists('cipher_suite_s',''),\n\t\tCalloutTime=column_ifexists('callout_time_s',''),\n\t\tBrowserVersion=column_ifexists('browser_version_s',''),\n\t\tBrowserName=column_ifexists('browser_name_s',''),\n\t\tAverageRowSize=column_ifexists('average_row_size_s',''),\n\t\tAppType=column_ifexists('app_type_s',''),\n\t\tAppName=column_ifexists('app_name_s',''),\n\t\tApiVersion=column_ifexists('api_version_s',''),\n\t\tApiType=column_ifexists('api_type_s',''),\n ArticleVersionId=column_ifexists('article_version_id_s',''),\n\t\tArticleVersion=column_ifexists('article_version_s',''),\n\t\tArticleStatus=column_ifexists('article_status_s',''),\n\t\tArticleId=column_ifexists('article_id_s',''),\n AnalyticsMode=column_ifexists('analytics_mode_s',''),\n BatchId=column_ifexists('batch_id_s',''),\n ClickedRecordId=column_ifexists('clicked_record_id_s',''),\n\t\tClassName=column_ifexists('class_name_s',''),\n ComponentIdDerived=column_ifexists('component_id_derived_s',''),\n\t\tComponentId=column_ifexists('component_id_s',''),\n ControllerType=column_ifexists('controller_type_s',''),\n\t\tContext=column_ifexists('context_s',''),\n\t\tConsoleIdDerived=column_ifexists('console_id_derived_s',''),\n\t\tConsoleId=column_ifexists('console_id_s',''), \n ClientInfo=column_ifexists('client_info_s',''),\n DstBytes=column_ifexists('request_size_s',''),\n\t\tDstUser=column_ifexists('delegated_user_name_s',''),\n DstUserSid=column_ifexists('delegated_user_id_s',''),\n\t\tDstUserSidDerived=column_ifexists('delegated_user_id_derived_s',''),\n Data=column_ifexists('data_s',''),\n\t\tDashboardType=column_ifexists('dashboard_type_s',''),\n\t\tDashboardIdDerived=column_ifexists('dashboard_id_derived_s',''),\n\t\tDashboardId=column_ifexists('dashboard_id_s',''),\n\t\tDashboardComponentId=column_ifexists('dashboard_component_id_s',''),\n\t\tDvcAction=column_ifexists('action_s',''),\n\t\tDvcOS=column_ifexists('platform_type_s',''),\n\t\tDvcOSName=column_ifexists('os_name_s',''),\n\t\tDvcOSVersion=column_ifexists('os_version_s',''),\n DeliveryLocation=column_ifexists('delivery_location_s',''),\n\t\tDeliveryId=column_ifexists('delivery_id_s',''),\n DocumentIdDerived=column_ifexists('document_id_derived_s',''),\n\t\tDocumentId=column_ifexists('document_id_s',''),\n EntityType=column_ifexists('entity_type_s',''),\n EntityId=column_ifexists('entity_id_s',''),\n FileType=column_ifexists('file_type_s',''),\n\t\tFilePreviewType=column_ifexists('file_preview_type_s',''),\n\t\tExceptionType=column_ifexists('exception_type_s',''),\n\t\tExceptionMessage=column_ifexists('exception_message_s',''),\n\t\tEpt=column_ifexists('ept_s',''),\n EventCount=column_ifexists('number_of_records_s',''),\n\t\tEventEndTime=column_ifexists('timestamp_s',''),\n\t\tEventResult=column_ifexists('status_code_s',''),\n\t\tFileSize=column_ifexists('size_bytes_s',''),\n HttpReferrerOriginal=column_ifexists('referrer_uri_s',''),\n\t\tHttpUserAgentOriginal=column_ifexists('user_agent_s',''),\n\t\tHttpUserAgent=column_ifexists('browser_type_s',''),\n LogGroupId=column_ifexists('log_group_id_s',''),\n\t\tLimitUsagePercent=column_ifexists('limit_usage_percent_s',''),\n\t\tLicenseContext=column_ifexists('license_context_s',''),\n\t\tLastVersion=column_ifexists('last_version_s',''),\n\t\tLanguage=column_ifexists('language_s',''),\n\t\tJobId=column_ifexists('job_id_s',''),\n\t\tIsSuccess=column_ifexists('is_success_s',''),\n\t\tIsSecure=column_ifexists('is_secure_s',''),\n\t\tIsScheduled=column_ifexists('is_scheduled_s',''),\n\t\tIsNew=column_ifexists('is_new_s',''),\n\t\tIsMobile=column_ifexists('is_mobile_s',''),\n\t\tIsLongRunningRequest=column_ifexists('is_long_running_request_s',''),\n\t\tIsGuest=column_ifexists('is_guest_s',''),\n\t\tIsFirstRequest=column_ifexists('is_first_request_s',''),\n\t\tIsError=column_ifexists('is_error_s',''),\n\t\tIsApi=column_ifexists('is_api_s',''),\n\t\tIsAjaxRequest=column_ifexists('is_ajax_request_s',''),\n ManagedPackageNamespace=column_ifexists('managed_package_namespace_s',''),\n HttpHeaders=column_ifexists('http_headers_s',''),\n\t\tNetworkDuration=column_ifexists('time_s',''),\n Name=column_ifexists('name_s',''),\n NumberFailures=column_ifexists('number_failures_s',''),\n NumClicks=column_ifexists('num_clicks_s',''),\n OperationType=column_ifexists('operation_type_s',''),\n\t\tNumSessions=column_ifexists('num_sessions_s',''),\n PageName=column_ifexists('page_name_s',''),\n Query=column_ifexists('query_s',''),\n RequestType=column_ifexists('request_type_s',''),\n ReportDescription=column_ifexists('report_description_s',''),\n\t\tReopenCount=column_ifexists('reopen_count_s',''),\n RelatedEntityId=column_ifexists('related_entity_id_s',''),\n RecordIdDerived=column_ifexists('record_id_derived_s',''),\n ReadTime=column_ifexists('read_time_s',''),\n\t\tRank=column_ifexists('rank_s',''),\n\t\tSrcBytes=column_ifexists('response_size_s',''),\n\t\tSrcDvcId=column_ifexists('device_id_s',''),\n\t\tSrcDvcModelName=column_ifexists('device_model_s',''),\n\t\tSrcIpAddr=column_ifexists('source_ip_s',''),\n\t\tSrcNatIpAddr=column_ifexists('client_ip_s',''),\n SessionId=column_ifexists('session_id_s',''),\n SiteId=column_ifexists('site_id_s',''),\n\t\tSharingPermission=column_ifexists('sharing_permission_s',''),\n\t\tSharingOperation=column_ifexists('sharing_operation_s',''),\n\t\tSharedWithEntityId=column_ifexists('shared_with_entity_id_s',''),\n\t\tUrlOriginal=column_ifexists('url_s',''),\n\t\tWaveTimestamp=column_ifexists('wave_timestamp_s',''),\n\t\tWaveSessionId=column_ifexists('wave_session_id_g',''),\n\t\tViewStateSize=column_ifexists('view_state_size_s',''),\n\t\tVersionIdDerived=column_ifexists('version_id_derived_s',''),\n\t\tVersionId=column_ifexists('version_id_s',''),\n TriggerType=column_ifexists('trigger_type_s',''),\n\t\tTriggerName=column_ifexists('trigger_name_s',''),\n\t\tTriggerId=column_ifexists('trigger_id_s',''),\n\t\tTransactionType=column_ifexists('transaction_type_s',''),\n\t\tTotalTime=column_ifexists('total_time_s',''),\n TabId=column_ifexists('tab_id_s',''),\n\t\tStackTrace=column_ifexists('stack_trace_s','')\n| project-away *_s\n", + "functionParameters": "", + "version": 2, + "tags": [ { - "fieldMappings": [ - { - "columnName": "User", - "identifier": "AadUserId" - } - ], - "entityType": "Account" + "name": "description", + "value": "" } ] } @@ -394,16 +531,18 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", + "dependsOn": [ + "[variables('_parserName1')]" + ], "properties": { - "description": "Salesforce Service Cloud Analytics Rule 3", - "parentId": "[variables('analyticRuleId3')]", - "contentId": "[variables('_analyticRulecontentId3')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion3')]", + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", "source": { - "kind": "Solution", "name": "Salesforce Service Cloud", + "kind": "Solution", "sourceId": "[variables('_solutionId')]" }, "author": { @@ -419,187 +558,114 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_parserContentId1')]", + "contentKind": "Parser", + "displayName": "SalesforceServiceCloud", + "contentProductId": "[variables('_parsercontentProductId1')]", + "id": "[variables('_parsercontentProductId1')]", + "version": "[variables('parserVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('dataConnectorTemplateSpecName1')]", + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2022-10-01", + "name": "[variables('_parserName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, "properties": { - "description": "Salesforce Service Cloud data connector with template", - "displayName": "Salesforce Service Cloud template" + "eTag": "*", + "displayName": "SalesforceServiceCloud", + "category": "Microsoft Sentinel Parser", + "functionAlias": "SalesforceServiceCloud", + "query": "SalesforceServiceCloud_CL \n| extend \n\t\tRequestSize=column_ifexists('request_size_s',''),\n\t\tExecTime=column_ifexists('exec_time_s',''),\n\t\tAction=column_ifexists('action_s',''),\n\t\tPlatformType=column_ifexists('platform_type_s',''),\n\t\tOsName=column_ifexists('os_name_s',''),\n\t\tOsVersion=column_ifexists('os_version_s',''),\n\t\tTimestamp=column_ifexists('timestamp_s',''),\n\t\tStatusCode=column_ifexists('status_code_s',''),\n\t\tEventType=column_ifexists('event_type_s',''),\n\t\tReferrerUri=column_ifexists('referrer_uri_s',''),\n\t\tUserAgent=column_ifexists('user_agent_s',''),\n\t\tBrowserType=column_ifexists('browser_type_s',''),\n\t\tTime=column_ifexists('time_s',''),\n\t\tResponseSize=column_ifexists('response_size_s',''),\n\t\tDeviceId=column_ifexists('device_id_s',''),\n\t\tDeviceModel=column_ifexists('device_model_s',''),\n\t\tSourceIp=column_ifexists('source_ip_s',''),\n\t\tClientIp=column_ifexists('client_ip_s',''),\n\t\tSuccess=column_ifexists('success_s',''),\n\t\tUri=column_ifexists('uri_s',''),\n\t\tUrl=column_ifexists('url_s',''),\n\t\tClientName=column_ifexists('client_name_s',''),\n\t\tUserType=column_ifexists('user_type_s',''),\n\t\tUserInitiatedLogout=column_ifexists('user_initiated_logout_s',''),\n\t\tUserIdDerived=column_ifexists('user_id_derived_s',''),\n\t\tUserId=column_ifexists('user_id_s',''),\n\t\tUserEmail=column_ifexists('user_email_s',''),\n\t\tUser=column_ifexists('user_name_s',''),\n\t\tUriIdDerived=column_ifexists('uri_id_derived_s',''),\n\t\tUiEventType=column_ifexists('ui_event_type_s',''),\n\t\tUiEventTimestamp=column_ifexists('ui_event_timestamp_s',''),\n\t\tUiEventSource=column_ifexists('ui_event_source_s',''),\n\t\tUiEventSequenceNum=column_ifexists('ui_event_sequence_num_s',''),\n\t\tUiEventId=column_ifexists('ui_event_id_s',''),\n\t\tTlsProtocol=column_ifexists('tls_protocol_s',''),\n\t\tTimestampDerived=column_ifexists('timestamp_derived_t',''),\n\t\tTargetUiElement=column_ifexists('target_ui_element_s',''),\n\t\tSort=column_ifexists('sort_s',''),\n\t\tSessionType=column_ifexists('session_type_s',''),\n\t\tSessionLevel=column_ifexists('session_level_s',''),\n\t\tSessionKey=column_ifexists('session_key_s',''),\n\t\tSearchQuery=column_ifexists('search_query_s',''),\n\t\tSdkVersion=column_ifexists('sdk_version_s',''),\n\t\tSdkAppVersion=column_ifexists('sdk_app_version_s',''),\n\t\tSdkAppType=column_ifexists('sdk_app_type_s',''),\n\t\tRunTime=column_ifexists('run_time_s',''),\n\t\tRowsProcessed=column_ifexists('rows_processed_s',''),\n\t\tRowCount=column_ifexists('row_count_s',''),\n\t\tResolutionType=column_ifexists('resolution_type_s',''),\n\t\tRequestStatus=column_ifexists('request_status_s',''),\n\t\tRequestId=column_ifexists('request_id_s',''),\n\t\tReportIdDerived=column_ifexists('report_id_derived_s',''),\n\t\tReportId=column_ifexists('report_id_s',''),\n\t\tRenderingType=column_ifexists('rendering_type_s',''),\n\t\tRelatedList=column_ifexists('related_list_s',''),\n\t\tRecordType=column_ifexists('record_type_s',''),\n\t\tRecordId=column_ifexists('record_id_s',''),\n\t\tQuiddity=column_ifexists('quiddity_s',''),\n\t\tQueryId=column_ifexists('query_id_s',''),\n\t\tPrevpageUrl=column_ifexists('prevpage_url_s',''),\n\t\tPrevpageEntityType=column_ifexists('prevpage_entity_type_s',''),\n\t\tPrevpageEntityId=column_ifexists('prevpage_entity_id_s',''),\n\t\tPrevpageContext=column_ifexists('prevpage_context_s',''),\n\t\tPrevpageAppName=column_ifexists('prevpage_app_name_s',''),\n\t\tPrefixesSearched=column_ifexists('prefixes_searched_s',''),\n\t\tParentUiElement=column_ifexists('parent_ui_element_s',''),\n\t\tPageUrl=column_ifexists('page_url_s',''),\n\t\tPageStartTime=column_ifexists('page_start_time_s',''),\n\t\tPageEntityType=column_ifexists('page_entity_type_s',''),\n\t\tPageEntityId=column_ifexists('page_entity_id_s',''),\n\t\tPageContext=column_ifexists('page_context_s',''),\n\t\tPageAppName=column_ifexists('page_app_name_s',''),\n\t\tOrigin=column_ifexists('origin_s',''),\n\t\tOrganizationId=column_ifexists('organization_id_s',''),\n\t\tNumResults=column_ifexists('num_results_s',''),\n\t\tNumberSoqlQueries=column_ifexists('number_soql_queries_s',''),\n\t\tNumberFields=column_ifexists('number_fields_s',''),\n\t\tNumberExceptionFilters=column_ifexists('number_exception_filters_s',''),\n\t\tNumberColumns=column_ifexists('number_columns_s',''),\n\t\tNumberBuckets=column_ifexists('number_buckets_s',''),\n\t\tMethodName=column_ifexists('method_name_s',''),\n\t\tMethod=column_ifexists('method_s',''),\n\t\tMediaType=column_ifexists('media_type_s',''),\n\t\tLoginStatus=column_ifexists('login_status_s',''),\n\t\tLoginKey=column_ifexists('login_key_s',''),\n\t\tHttpMethod=column_ifexists('http_method_s',''),\n\t\tGrandparentUiElement=column_ifexists('grandparent_ui_element_s',''),\n\t\tEntryPoint=column_ifexists('entry_point_s',''),\n\t\tEntityName=column_ifexists('entity_name_s',''),\n\t\tEntity=column_ifexists('entity_s',''),\n\t\tEffectivePageTime=column_ifexists('effective_page_time_s',''),\n\t\tDuration=column_ifexists('duration_s',''),\n\t\tDisplayType=column_ifexists('display_type_s',''),\n\t\tDeviceSessionId=column_ifexists('device_session_id_s',''),\n\t\tDevicePlatform=column_ifexists('device_platform_s',''),\n\t\tDbTotalTime=column_ifexists('db_total_time_s',''),\n\t\tDbCpuTime=column_ifexists('db_cpu_time_s',''),\n\t\tDbBlocks=column_ifexists('db_blocks_s',''),\n\t\tCpuTime=column_ifexists('cpu_time_s',''),\n\t\tConnectionType=column_ifexists('connection_type_s',''),\n\t\tComponentName=column_ifexists('component_name_s',''),\n\t\tClientVersion=column_ifexists('client_version_s',''),\n\t\tClientId=column_ifexists('client_id_s',''),\n\t\tCipherSuite=column_ifexists('cipher_suite_s',''),\n\t\tCalloutTime=column_ifexists('callout_time_s',''),\n\t\tBrowserVersion=column_ifexists('browser_version_s',''),\n\t\tBrowserName=column_ifexists('browser_name_s',''),\n\t\tAverageRowSize=column_ifexists('average_row_size_s',''),\n\t\tAppType=column_ifexists('app_type_s',''),\n\t\tAppName=column_ifexists('app_name_s',''),\n\t\tApiVersion=column_ifexists('api_version_s',''),\n\t\tApiType=column_ifexists('api_type_s',''),\n ArticleVersionId=column_ifexists('article_version_id_s',''),\n\t\tArticleVersion=column_ifexists('article_version_s',''),\n\t\tArticleStatus=column_ifexists('article_status_s',''),\n\t\tArticleId=column_ifexists('article_id_s',''),\n AnalyticsMode=column_ifexists('analytics_mode_s',''),\n BatchId=column_ifexists('batch_id_s',''),\n ClickedRecordId=column_ifexists('clicked_record_id_s',''),\n\t\tClassName=column_ifexists('class_name_s',''),\n ComponentIdDerived=column_ifexists('component_id_derived_s',''),\n\t\tComponentId=column_ifexists('component_id_s',''),\n ControllerType=column_ifexists('controller_type_s',''),\n\t\tContext=column_ifexists('context_s',''),\n\t\tConsoleIdDerived=column_ifexists('console_id_derived_s',''),\n\t\tConsoleId=column_ifexists('console_id_s',''), \n ClientInfo=column_ifexists('client_info_s',''),\n DstBytes=column_ifexists('request_size_s',''),\n\t\tDstUser=column_ifexists('delegated_user_name_s',''),\n DstUserSid=column_ifexists('delegated_user_id_s',''),\n\t\tDstUserSidDerived=column_ifexists('delegated_user_id_derived_s',''),\n Data=column_ifexists('data_s',''),\n\t\tDashboardType=column_ifexists('dashboard_type_s',''),\n\t\tDashboardIdDerived=column_ifexists('dashboard_id_derived_s',''),\n\t\tDashboardId=column_ifexists('dashboard_id_s',''),\n\t\tDashboardComponentId=column_ifexists('dashboard_component_id_s',''),\n\t\tDvcAction=column_ifexists('action_s',''),\n\t\tDvcOS=column_ifexists('platform_type_s',''),\n\t\tDvcOSName=column_ifexists('os_name_s',''),\n\t\tDvcOSVersion=column_ifexists('os_version_s',''),\n DeliveryLocation=column_ifexists('delivery_location_s',''),\n\t\tDeliveryId=column_ifexists('delivery_id_s',''),\n DocumentIdDerived=column_ifexists('document_id_derived_s',''),\n\t\tDocumentId=column_ifexists('document_id_s',''),\n EntityType=column_ifexists('entity_type_s',''),\n EntityId=column_ifexists('entity_id_s',''),\n FileType=column_ifexists('file_type_s',''),\n\t\tFilePreviewType=column_ifexists('file_preview_type_s',''),\n\t\tExceptionType=column_ifexists('exception_type_s',''),\n\t\tExceptionMessage=column_ifexists('exception_message_s',''),\n\t\tEpt=column_ifexists('ept_s',''),\n EventCount=column_ifexists('number_of_records_s',''),\n\t\tEventEndTime=column_ifexists('timestamp_s',''),\n\t\tEventResult=column_ifexists('status_code_s',''),\n\t\tFileSize=column_ifexists('size_bytes_s',''),\n HttpReferrerOriginal=column_ifexists('referrer_uri_s',''),\n\t\tHttpUserAgentOriginal=column_ifexists('user_agent_s',''),\n\t\tHttpUserAgent=column_ifexists('browser_type_s',''),\n LogGroupId=column_ifexists('log_group_id_s',''),\n\t\tLimitUsagePercent=column_ifexists('limit_usage_percent_s',''),\n\t\tLicenseContext=column_ifexists('license_context_s',''),\n\t\tLastVersion=column_ifexists('last_version_s',''),\n\t\tLanguage=column_ifexists('language_s',''),\n\t\tJobId=column_ifexists('job_id_s',''),\n\t\tIsSuccess=column_ifexists('is_success_s',''),\n\t\tIsSecure=column_ifexists('is_secure_s',''),\n\t\tIsScheduled=column_ifexists('is_scheduled_s',''),\n\t\tIsNew=column_ifexists('is_new_s',''),\n\t\tIsMobile=column_ifexists('is_mobile_s',''),\n\t\tIsLongRunningRequest=column_ifexists('is_long_running_request_s',''),\n\t\tIsGuest=column_ifexists('is_guest_s',''),\n\t\tIsFirstRequest=column_ifexists('is_first_request_s',''),\n\t\tIsError=column_ifexists('is_error_s',''),\n\t\tIsApi=column_ifexists('is_api_s',''),\n\t\tIsAjaxRequest=column_ifexists('is_ajax_request_s',''),\n ManagedPackageNamespace=column_ifexists('managed_package_namespace_s',''),\n HttpHeaders=column_ifexists('http_headers_s',''),\n\t\tNetworkDuration=column_ifexists('time_s',''),\n Name=column_ifexists('name_s',''),\n NumberFailures=column_ifexists('number_failures_s',''),\n NumClicks=column_ifexists('num_clicks_s',''),\n OperationType=column_ifexists('operation_type_s',''),\n\t\tNumSessions=column_ifexists('num_sessions_s',''),\n PageName=column_ifexists('page_name_s',''),\n Query=column_ifexists('query_s',''),\n RequestType=column_ifexists('request_type_s',''),\n ReportDescription=column_ifexists('report_description_s',''),\n\t\tReopenCount=column_ifexists('reopen_count_s',''),\n RelatedEntityId=column_ifexists('related_entity_id_s',''),\n RecordIdDerived=column_ifexists('record_id_derived_s',''),\n ReadTime=column_ifexists('read_time_s',''),\n\t\tRank=column_ifexists('rank_s',''),\n\t\tSrcBytes=column_ifexists('response_size_s',''),\n\t\tSrcDvcId=column_ifexists('device_id_s',''),\n\t\tSrcDvcModelName=column_ifexists('device_model_s',''),\n\t\tSrcIpAddr=column_ifexists('source_ip_s',''),\n\t\tSrcNatIpAddr=column_ifexists('client_ip_s',''),\n SessionId=column_ifexists('session_id_s',''),\n SiteId=column_ifexists('site_id_s',''),\n\t\tSharingPermission=column_ifexists('sharing_permission_s',''),\n\t\tSharingOperation=column_ifexists('sharing_operation_s',''),\n\t\tSharedWithEntityId=column_ifexists('shared_with_entity_id_s',''),\n\t\tUrlOriginal=column_ifexists('url_s',''),\n\t\tWaveTimestamp=column_ifexists('wave_timestamp_s',''),\n\t\tWaveSessionId=column_ifexists('wave_session_id_g',''),\n\t\tViewStateSize=column_ifexists('view_state_size_s',''),\n\t\tVersionIdDerived=column_ifexists('version_id_derived_s',''),\n\t\tVersionId=column_ifexists('version_id_s',''),\n TriggerType=column_ifexists('trigger_type_s',''),\n\t\tTriggerName=column_ifexists('trigger_name_s',''),\n\t\tTriggerId=column_ifexists('trigger_id_s',''),\n\t\tTransactionType=column_ifexists('transaction_type_s',''),\n\t\tTotalTime=column_ifexists('total_time_s',''),\n TabId=column_ifexists('tab_id_s',''),\n\t\tStackTrace=column_ifexists('stack_trace_s','')\n| project-away *_s\n", + "functionParameters": "", + "version": 2, + "tags": [ + { + "name": "description", + "value": "" + } + ] } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('dataConnectorTemplateSpecName1'),'/',variables('dataConnectorVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('dataConnectorTemplateSpecName1'))]" + "[variables('_parserId1')]" ], "properties": { - "description": "Salesforce Service Cloud data connector with template version 2.0.4", + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", + "source": { + "kind": "Solution", + "name": "Salesforce Service Cloud", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com/" + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('workbookTemplateSpecName1')]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "SalesforceServiceCloudWorkbook Workbook with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion1')]", + "contentVersion": "[variables('workbookVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "type": "Microsoft.Insights/workbooks", + "name": "[variables('workbookContentId1')]", "location": "[parameters('workspace-location')]", - "kind": "GenericUI", + "kind": "shared", + "apiVersion": "2021-08-01", + "metadata": { + "description": "Sets the time name for analysis." + }, "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId1')]", - "title": "Salesforce Service Cloud (using Azure Function)", - "publisher": "Salesforce", - "descriptionMarkdown": "The Salesforce Service Cloud data connector provides the capability to ingest information about your Salesforce operational events into Microsoft Sentinel through the REST API. The connector provides ability to review events in your org on an accelerated basis, get [event log files](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/event_log_file_hourly_overview.htm) in hourly increments for recent activity.", - "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution.", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "SalesforceServiceCloud_CL", - "baseQuery": "SalesforceServiceCloud_CL" - } - ], - "sampleQueries": [ - { - "description": "Last Salesforce Service Cloud EventLogFile Events", - "query": "SalesforceServiceCloud\n | sort by TimeGenerated desc" - } - ], - "dataTypes": [ - { - "name": "SalesforceServiceCloud_CL", - "lastDataReceivedQuery": "SalesforceServiceCloud_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "SalesforceServiceCloud_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(30d)" - ] - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, - { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true - } - } - ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "REST API Credentials/permissions", - "description": "**Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** is required for REST API. [See the documentation to learn more about API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm)." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Salesforce Lightning Platform REST API to pull its logs into Microsoft Sentinel. This might result in additional data ingestion costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": "**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Salesforce%20Service%20Cloud/Parsers/SalesforceServiceCloud.txt). The function usually takes 10-15 minutes to activate after solution installation/update." - }, - { - "description": "**STEP 1 - Configuration steps for the Salesforce Lightning Platform REST API**\n\n1. See the [link](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm) and follow the instructions for obtaining Salesforce API Authorization credentials. \n2. On the **Set Up Authorization** step choose **Session ID Authorization** method.\n3. You must provide your client id, client secret, username, and password with user security token." - }, - { - "description": ">**NOTE:** Ingesting data from on an hourly interval may require additional licensing based on the edition of the Salesforce Service Cloud being used. Please refer to [Salesforce documentation](https://www.salesforce.com/editions-pricing/service-cloud/) and/or support for more details." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the Salesforce Service Cloud data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Salesforce API Authorization credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" - } - ] - }, - { - "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy.", - "title": "Option 1 - Azure Resource Manager (ARM) Template" - }, - { - "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "title": "Option 2 - Manual Deployment of Azure Functions" - }, - { - "description": "**1. Deploy a Function App**\n\n> NOTE:You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. SalesforceXXXXX).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." - }, - { - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n3. Once all application settings have been entered, click **Save**." - } - ] - } + "displayName": "[parameters('workbook1-name')]", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Salesforce Service Cloud Workbook\\n---\\n\\nThis workbook brings together queries and visualizations to assist you in identifying potential threats in your Salesforce Service cloud audit data. Visualizations may not appear if no data is present.\\n\\nTo begin select the desired TimeRange to filter the data to the timeframe you want to focus on. Note if you have a large amount of salesforce service cloud data, queries may timeout with a large time range, if this is the case simply select a smaller time range.: \",\"style\":\"info\"},\"name\":\"text - 2\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"412a09a0-64ae-4614-aec6-cbfc9273b82b\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":1800000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}],\"allowCustom\":true},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 32\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"ae90d1dc-20da-4948-80da-127b210bf152\",\"cellValue\":\"view_tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"User Logins\",\"subTarget\":\"1\",\"style\":\"link\"},{\"id\":\"af58b4d9-a888-43ed-91a9-6e9f539a61d4\",\"cellValue\":\"view_tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"API Usage\",\"subTarget\":\"2\",\"style\":\"link\"}]},\"name\":\"links - 34\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"title\":\"User login locations\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let Countrydb = externaldata(Network:string, geoname_id:string, continent_code:string, continent_name:string, country_iso_code:string, country_name:string)\\n[@\\\"https://raw.githubusercontent.com/datasets/geoip2-ipv4/master/data/geoip2-ipv4.csv\\\"];\\nlet UsersLocation = SalesforceServiceCloud\\n| where EventType == \\\"Login\\\"\\n| project TimeGenerated, SourceIp;\\nUsersLocation\\n| extend Dummy=1\\n| summarize count() by Hour=bin(TimeGenerated,24h), SourceIp,Dummy\\n| partition by Hour(\\n lookup (Countrydb|extend Dummy=1) on Dummy\\n | where ipv4_is_match(SourceIp, Network)\\n )\\n| summarize sum(count_) by country_name\",\"size\":3,\"title\":\"Heat Map- Geographical - {TimeRange:label}\",\"timeContextFromParameter\":\"TimeRange\",\"exportedParameters\":[{\"fieldName\":\"TimeGenerated\",\"parameterName\":\"RetTime\"},{\"parameterType\":1}],\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"map\",\"chartSettings\":{\"showLegend\":true},\"mapSettings\":{\"locInfo\":\"CountryRegion\",\"locInfoColumn\":\"country_name\",\"sizeSettings\":\"sum_count_\",\"sizeAggregation\":\"Sum\",\"legendMetric\":\"sum_count_\",\"legendAggregation\":\"Sum\",\"itemColorSettings\":{\"nodeColorField\":\"sum_count_\",\"colorAggregation\":\"Sum\",\"type\":\"heatmap\",\"heatmapPalette\":\"greenRed\"}}},\"customWidth\":\"70\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| summarize AvgLogintime = avg(toint(RunTime)), MaxLoginTime = max(toint(RunTime)), TotalLoginRequests = count() by EventType\\r\\n| project-away EventType\",\"size\":1,\"title\":\"Overview - User login requests\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"AvgLogintime\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":23,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"MaxLoginTime\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":23,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"TotalLoginRequests\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\"}}}],\"rowLimit\":1},\"tileSettings\":{\"showBorder\":false}},\"customWidth\":\"30\",\"name\":\"query - 8\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| summarize count() by bin(TimeGenerated, 1h),User, ClientIp \\r\\n| top 10 by count_\",\"size\":0,\"title\":\"Top 10 users with maximun logins - {TimeRange:label}\",\"exportFieldName\":\"UserId\",\"exportParameterName\":\"RetUser\",\"exportDefaultValue\":\"all users\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"user_name_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TimeGenerated\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false},\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"60\",\"name\":\"query - 2\"},{\"type\":1,\"content\":{\"json\":\"To leverage infomation about Malicious IP, Threat Indicator solution should be configured and ThreatIntelligenceIndicator table should have information of malicious IP.\",\"style\":\"info\"},\"customWidth\":\"10\",\"name\":\"text - 8\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\" let malicious_ips =\\r\\n ThreatIntelligenceIndicator\\r\\n | where isnotempty(NetworkIP)\\r\\n | summarize make_list(NetworkIP); \\r\\n SalesforceServiceCloud\\r\\n | where EventType == 'Login'\\r\\n | distinct User,ClientIp\\r\\n | where ClientIp in (malicious_ips)\\r\\n | project UserName = User, MaliciousIP = ClientIp\\r\\n\",\"size\":1,\"title\":\"Malicious IP- User Login\",\"noDataMessage\":\"No Malicious IP found\",\"timeBrushParameterName\":\"TimeBrush\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"MaliciousIP\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}]},\"graphSettings\":{\"type\":0},\"chartSettings\":{\"showMetrics\":false}},\"customWidth\":\"30\",\"name\":\"query - 23\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'LoginAS'\\r\\n| project UserID = UserId,DerivedUSerID = UserIdDerived,EventType = EventType, IPAddress = ClientIp, LoginKey = LoginKey, OrgID = OrganizationId, RequestID = RequestId, SessionKey = SessionKey\\r\\n| limit 10\",\"size\":0,\"title\":\"User Activity- LoginAS(Top 10)\",\"noDataMessage\":\"No user impersonation found\",\"exportFieldName\":\"IPAddress\",\"exportParameterName\":\"RetIP\",\"exportDefaultValue\":\"all IP addresses\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"IPAddress\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalRecords\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"60\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'LoginAs'\\r\\n| where isnotempty(User)\\r\\n| summarize count() by User,UserIdDerived,ClientIp\\r\\n| project UserName = User,DerivedUSerID = UserIdDerived,IPAddress = ClientIp, count_\",\"size\":1,\"title\":\"User Impersonation from different IP Addresses\",\"color\":\"blue\",\"noDataMessage\":\"No user impersonation found\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"DerivedUSerID\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"IPAddress\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"count_\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}],\"labelSettings\":[{\"columnId\":\"UserName\",\"label\":\"User Name\"},{\"columnId\":\"DerivedUSerID\",\"label\":\"Impersonated ID\"},{\"columnId\":\"IPAddress\",\"label\":\"IP Address\"},{\"columnId\":\"count_\",\"label\":\"Total Login\"}]},\"chartSettings\":{\"xAxis\":\"IPAddress\",\"yAxis\":[\"count_\"],\"showLegend\":true}},\"customWidth\":\"40\",\"name\":\"query - 24\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| where isnotempty(User)\\r\\n| project UserName= User,APIType= ApiType, Browser= BrowserType, CipherSuite =CipherSuite, IP =ClientIp, CPUTime=CpuTime, UserType = UserType\\r\\n| take 200\",\"size\":0,\"title\":\"User Successful Login Activity\",\"timeContext\":{\"durationMs\":86400000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\"},\"customWidth\":\"60\",\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| where isnotempty(User)\\r\\n| where LoginStatus !has('LOGIN_NO_ERROR')\\r\\n| summarize count() by User, ClientIp\\r\\n| project UserName = User, IP = ClientIp, Count = count_\",\"size\":1,\"title\":\"User Unsuccessful Logins by IP\",\"noDataMessage\":\"No Unsucessful Login found\",\"timeContext\":{\"durationMs\":86400000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"IP\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"Count\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}],\"labelSettings\":[{\"columnId\":\"UserName\",\"label\":\"User Name\"},{\"columnId\":\"IP\",\"label\":\"IP Address\"},{\"columnId\":\"Count\",\"label\":\"Count\"}]},\"chartSettings\":{\"xAxis\":\"UserName\",\"yAxis\":[\"Count\"],\"ySettings\":{\"numberFormatSettings\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"useGrouping\":true}}}}},\"customWidth\":\"30\",\"name\":\"query - 5\"}]},\"conditionalVisibility\":{\"parameterName\":\"view_tab\",\"comparison\":\"isEqualTo\",\"value\":\"1\"},\"name\":\"Retrieval Events\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"title\":\"API Usage\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| summarize count() by EventType\",\"size\":0,\"title\":\"Most fired events\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":50,\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == \\\"ApiTotalUsage\\\"\\r\\n| summarize count() by IPAddress = ClientIp,Entity = EntityName\\r\\n| order by Entity\",\"size\":0,\"title\":\"Most accessed entities by IP Address\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"user_id_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"entity_name_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"client_ip_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"count_\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\"}}}],\"labelSettings\":[{\"columnId\":\"count_\",\"label\":\"Count\"}]}},\"customWidth\":\"50\",\"name\":\"query - 5\",\"styleSettings\":{\"maxWidth\":\"30%\",\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == \\\"ApiTotalUsage\\\"\\r\\n| summarize count() by EntityName\",\"size\":0,\"title\":\"Most accessed Entities\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\"},\"name\":\"query - 6\"}]},\"conditionalVisibility\":{\"parameterName\":\"view_tab\",\"comparison\":\"isEqualTo\",\"value\":\"2\"},\"name\":\"APIUsage\"}],\"fromTemplateId\":\"sentinel-SalesforceServiceCloudWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\n", + "version": "1.0", + "sourceId": "[variables('workspaceResourceId')]", + "category": "sentinel" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", + "description": "@{workbookKey=SalesforceServiceCloudWorkbook; logoFileName=salesforce_logo.svg; description=Sets the time name for analysis.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Salesforce Service Cloud; templateRelativePath=SalesforceServiceCloud.json; subtitle=; provider=Salesforce}.description", + "parentId": "[variables('workbookId1')]", + "contentId": "[variables('_workbookContentId1')]", + "kind": "Workbook", + "version": "[variables('workbookVersion1')]", "source": { "kind": "Solution", "name": "Salesforce Service Cloud", @@ -614,247 +680,224 @@ "email": "support@microsoft.com", "tier": "Microsoft", "link": "https://support.microsoft.com/" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "contentId": "SalesforceServiceCloud", + "kind": "DataType" + }, + { + "contentId": "SalesforceServiceCloud_CL", + "kind": "DataConnector" + } + ] } } } ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId1')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", - "source": { - "kind": "Solution", - "name": "Salesforce Service Cloud", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com/" - } + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_workbookContentId1')]", + "contentKind": "Workbook", + "displayName": "[parameters('workbook1-name')]", + "contentProductId": "[variables('_workbookcontentProductId1')]", + "id": "[variables('_workbookcontentProductId1')]", + "version": "[variables('workbookVersion1')]" } }, { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "kind": "GenericUI", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], "properties": { - "connectorUiConfig": { - "title": "Salesforce Service Cloud (using Azure Function)", - "publisher": "Salesforce", - "descriptionMarkdown": "The Salesforce Service Cloud data connector provides the capability to ingest information about your Salesforce operational events into Microsoft Sentinel through the REST API. The connector provides ability to review events in your org on an accelerated basis, get [event log files](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/event_log_file_hourly_overview.htm) in hourly increments for recent activity.", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "SalesforceServiceCloud_CL", - "baseQuery": "SalesforceServiceCloud_CL" - } - ], - "dataTypes": [ - { - "name": "SalesforceServiceCloud_CL", - "lastDataReceivedQuery": "SalesforceServiceCloud_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "SalesforceServiceCloud_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(30d)" - ] - } - ], - "sampleQueries": [ + "description": "Salesforce-BruteForce_AnalyticalRules Analytics Rule with template version 3.0.0", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('analyticRuleVersion1')]", + "parameters": {}, + "variables": {}, + "resources": [ { - "description": "Last Salesforce Service Cloud EventLogFile Events", - "query": "SalesforceServiceCloud\n | sort by TimeGenerated desc" - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, - { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId1')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", + "location": "[parameters('workspace-location')]", + "properties": { + "description": "Identifies evidence of brute force activity against a user based on multiple authentication failures \nand at least one successful authentication within a given time window. This query limits IPAddresses to 100 and may not potentially cover all IPAddresses\nThe default failure threshold is 10, success threshold is 1, and the default time window is 20 minutes.", + "displayName": "Brute force attack against user credentials", + "enabled": false, + "query": "let failureCountThreshold = 10;\nlet successCountThreshold = 1;\nlet Failures =\nSalesforceServiceCloud\n| where EventType == \"Login\" and LoginStatus != \"LOGIN_NO_ERROR\"\n| summarize\n FailureStartTime = min(TimeGenerated),\n FailureEndTime = max(TimeGenerated),\n IpAddresses = make_set (ClientIp, 100),\n FailureCount = count() by User, UserId, UserType;\n SalesforceServiceCloud\n | where EventType == \"Login\" and LoginStatus == \"LOGIN_NO_ERROR\"\n | summarize\n SuccessStartTime = min(TimeGenerated),\n SuccessEndTime = max(TimeGenerated),\n IpAddresses = make_set (ClientIp, 100),\n SuccessCount = count() by User, UserId, UserType\n | join kind=leftouter Failures on UserId\n | where FailureCount >= failureCountThreshold and SuccessCount >= successCountThreshold\n | where FailureEndTime < SuccessStartTime\n | project User, EventStartTime = FailureStartTime, EventEndTime = SuccessEndTime, IpAddresses\n", + "queryFrequency": "PT20M", + "queryPeriod": "PT20M", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "dataTypes": [ + "SalesforceServiceCloud" + ], + "connectorId": "SalesforceServiceCloud" + } + ], + "tactics": [ + "CredentialAccess" + ], + "techniques": [ + "T1110" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "FullName", + "columnName": "User" + } + ], + "entityType": "Account" + } + ], + "customDetails": { + "EventStartTime": "FailureStartTime", + "IPAddresses": "IpAddresses", + "EventEndTime": "SuccessEndTime" } } - ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "REST API Credentials/permissions", - "description": "**Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** is required for REST API. [See the documentation to learn more about API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm)." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Salesforce Lightning Platform REST API to pull its logs into Microsoft Sentinel. This might result in additional data ingestion costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": "**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected which is deployed as part of the solution. To view the function code in Log Analytics, open Log Analytics/Microsoft Sentinel Logs blade, click Functions and search for the alias SalesforceServiceCloud and load the function code or click [here](https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Salesforce%20Service%20Cloud/Parsers/SalesforceServiceCloud.txt). The function usually takes 10-15 minutes to activate after solution installation/update." - }, - { - "description": "**STEP 1 - Configuration steps for the Salesforce Lightning Platform REST API**\n\n1. See the [link](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart.htm) and follow the instructions for obtaining Salesforce API Authorization credentials. \n2. On the **Set Up Authorization** step choose **Session ID Authorization** method.\n3. You must provide your client id, client secret, username, and password with user security token." }, { - "description": ">**NOTE:** Ingesting data from on an hourly interval may require additional licensing based on the edition of the Salesforce Service Cloud being used. Please refer to [Salesforce documentation](https://www.salesforce.com/editions-pricing/service-cloud/) and/or support for more details." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the Salesforce Service Cloud data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Salesforce API Authorization credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", + "properties": { + "description": "Salesforce Service Cloud Analytics Rule 1", + "parentId": "[variables('analyticRuleId1')]", + "contentId": "[variables('_analyticRulecontentId1')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion1')]", + "source": { + "kind": "Solution", + "name": "Salesforce Service Cloud", + "sourceId": "[variables('_solutionId')]" }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com/" } - ] - }, - { - "description": "Use this method for automated deployment of the Salesforce Service Cloud data connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SalesforceServiceCloud-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Salesforce API Username**, **Salesforce API Password**, **Salesforce Security Token**, **Salesforce Consumer Key**, **Salesforce Consumer Secret** and deploy. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy.", - "title": "Option 1 - Azure Resource Manager (ARM) Template" - }, - { - "description": "Use the following step-by-step instructions to deploy the Salesforce Service Cloud data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "title": "Option 2 - Manual Deployment of Azure Functions" - }, - { - "description": "**1. Deploy a Function App**\n\n> NOTE:You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/functions-create-first-function-python#prerequisites) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SalesforceServiceCloud-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. SalesforceXXXXX).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." - }, - { - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSalesforceUser\n\t\tSalesforcePass\n\t\tSalesforceSecurityToken\n\t\tSalesforceConsumerKey\n\t\tSalesforceConsumerSecret\n\t\tWorkspaceID\n\t\tWorkspaceKey\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://.ods.opinsights.azure.us`\n3. Once all application settings have been entered, click **Save**." + } } - ], - "id": "[variables('_uiConfigId1')]", - "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution." - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('parserTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Parser" - }, - "properties": { - "description": "SalesforceServiceCloud Data Parser with template", - "displayName": "SalesforceServiceCloud Data Parser template" + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId1')]", + "contentKind": "AnalyticsRule", + "displayName": "Brute force attack against user credentials", + "contentProductId": "[variables('_analyticRulecontentProductId1')]", + "id": "[variables('_analyticRulecontentProductId1')]", + "version": "[variables('analyticRuleVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('parserTemplateSpecName1'),'/',variables('parserVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName2')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Parser" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('parserTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SalesforceServiceCloud Data Parser with template version 2.0.4", + "description": "Salesforce-PasswordSpray_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('parserVersion1')]", + "contentVersion": "[variables('analyticRuleVersion2')]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[variables('_parserName1')]", - "apiVersion": "2020-08-01", - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId2')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "SalesforceServiceCloud", - "category": "Samples", - "functionAlias": "SalesforceServiceCloud", - "query": "\nSalesforceServiceCloud_CL \r\n| extend \r\n\t\tRequestSize=column_ifexists('request_size_s',''),\r\n\t\tExecTime=column_ifexists('exec_time_s',''),\r\n\t\tAction=column_ifexists('action_s',''),\r\n\t\tPlatformType=column_ifexists('platform_type_s',''),\r\n\t\tOsName=column_ifexists('os_name_s',''),\r\n\t\tOsVersion=column_ifexists('os_version_s',''),\r\n\t\tTimestamp=column_ifexists('timestamp_s',''),\r\n\t\tStatusCode=column_ifexists('status_code_s',''),\r\n\t\tEventType=column_ifexists('event_type_s',''),\r\n\t\tReferrerUri=column_ifexists('referrer_uri_s',''),\r\n\t\tUserAgent=column_ifexists('user_agent_s',''),\r\n\t\tBrowserType=column_ifexists('browser_type_s',''),\r\n\t\tTime=column_ifexists('time_s',''),\r\n\t\tResponseSize=column_ifexists('response_size_s',''),\r\n\t\tDeviceId=column_ifexists('device_id_s',''),\r\n\t\tDeviceModel=column_ifexists('device_model_s',''),\r\n\t\tSourceIp=column_ifexists('source_ip_s',''),\r\n\t\tClientIp=column_ifexists('client_ip_s',''),\r\n\t\tSuccess=column_ifexists('success_s',''),\r\n\t\tUri=column_ifexists('uri_s',''),\r\n\t\tUrl=column_ifexists('url_s',''),\r\n\t\tClientName=column_ifexists('client_name_s',''),\r\n\t\tUserType=column_ifexists('user_type_s',''),\r\n\t\tUserInitiatedLogout=column_ifexists('user_initiated_logout_s',''),\r\n\t\tUserIdDerived=column_ifexists('user_id_derived_s',''),\r\n\t\tUserId=column_ifexists('user_id_s',''),\r\n\t\tUserEmail=column_ifexists('user_email_s',''),\r\n\t\tUser=column_ifexists('user_name_s',''),\r\n\t\tUriIdDerived=column_ifexists('uri_id_derived_s',''),\r\n\t\tUiEventType=column_ifexists('ui_event_type_s',''),\r\n\t\tUiEventTimestamp=column_ifexists('ui_event_timestamp_s',''),\r\n\t\tUiEventSource=column_ifexists('ui_event_source_s',''),\r\n\t\tUiEventSequenceNum=column_ifexists('ui_event_sequence_num_s',''),\r\n\t\tUiEventId=column_ifexists('ui_event_id_s',''),\r\n\t\tTlsProtocol=column_ifexists('tls_protocol_s',''),\r\n\t\tTimestampDerived=column_ifexists('timestamp_derived_t',''),\r\n\t\tTargetUiElement=column_ifexists('target_ui_element_s',''),\r\n\t\tSort=column_ifexists('sort_s',''),\r\n\t\tSessionType=column_ifexists('session_type_s',''),\r\n\t\tSessionLevel=column_ifexists('session_level_s',''),\r\n\t\tSessionKey=column_ifexists('session_key_s',''),\r\n\t\tSearchQuery=column_ifexists('search_query_s',''),\r\n\t\tSdkVersion=column_ifexists('sdk_version_s',''),\r\n\t\tSdkAppVersion=column_ifexists('sdk_app_version_s',''),\r\n\t\tSdkAppType=column_ifexists('sdk_app_type_s',''),\r\n\t\tRunTime=column_ifexists('run_time_s',''),\r\n\t\tRowsProcessed=column_ifexists('rows_processed_s',''),\r\n\t\tRowCount=column_ifexists('row_count_s',''),\r\n\t\tResolutionType=column_ifexists('resolution_type_s',''),\r\n\t\tRequestStatus=column_ifexists('request_status_s',''),\r\n\t\tRequestId=column_ifexists('request_id_s',''),\r\n\t\tReportIdDerived=column_ifexists('report_id_derived_s',''),\r\n\t\tReportId=column_ifexists('report_id_s',''),\r\n\t\tRenderingType=column_ifexists('rendering_type_s',''),\r\n\t\tRelatedList=column_ifexists('related_list_s',''),\r\n\t\tRecordType=column_ifexists('record_type_s',''),\r\n\t\tRecordId=column_ifexists('record_id_s',''),\r\n\t\tQuiddity=column_ifexists('quiddity_s',''),\r\n\t\tQueryId=column_ifexists('query_id_s',''),\r\n\t\tPrevpageUrl=column_ifexists('prevpage_url_s',''),\r\n\t\tPrevpageEntityType=column_ifexists('prevpage_entity_type_s',''),\r\n\t\tPrevpageEntityId=column_ifexists('prevpage_entity_id_s',''),\r\n\t\tPrevpageContext=column_ifexists('prevpage_context_s',''),\r\n\t\tPrevpageAppName=column_ifexists('prevpage_app_name_s',''),\r\n\t\tPrefixesSearched=column_ifexists('prefixes_searched_s',''),\r\n\t\tParentUiElement=column_ifexists('parent_ui_element_s',''),\r\n\t\tPageUrl=column_ifexists('page_url_s',''),\r\n\t\tPageStartTime=column_ifexists('page_start_time_s',''),\r\n\t\tPageEntityType=column_ifexists('page_entity_type_s',''),\r\n\t\tPageEntityId=column_ifexists('page_entity_id_s',''),\r\n\t\tPageContext=column_ifexists('page_context_s',''),\r\n\t\tPageAppName=column_ifexists('page_app_name_s',''),\r\n\t\tOrigin=column_ifexists('origin_s',''),\r\n\t\tOrganizationId=column_ifexists('organization_id_s',''),\r\n\t\tNumResults=column_ifexists('num_results_s',''),\r\n\t\tNumberSoqlQueries=column_ifexists('number_soql_queries_s',''),\r\n\t\tNumberFields=column_ifexists('number_fields_s',''),\r\n\t\tNumberExceptionFilters=column_ifexists('number_exception_filters_s',''),\r\n\t\tNumberColumns=column_ifexists('number_columns_s',''),\r\n\t\tNumberBuckets=column_ifexists('number_buckets_s',''),\r\n\t\tMethodName=column_ifexists('method_name_s',''),\r\n\t\tMethod=column_ifexists('method_s',''),\r\n\t\tMediaType=column_ifexists('media_type_s',''),\r\n\t\tLoginStatus=column_ifexists('login_status_s',''),\r\n\t\tLoginKey=column_ifexists('login_key_s',''),\r\n\t\tHttpMethod=column_ifexists('http_method_s',''),\r\n\t\tGrandparentUiElement=column_ifexists('grandparent_ui_element_s',''),\r\n\t\tEntryPoint=column_ifexists('entry_point_s',''),\r\n\t\tEntityName=column_ifexists('entity_name_s',''),\r\n\t\tEntity=column_ifexists('entity_s',''),\r\n\t\tEffectivePageTime=column_ifexists('effective_page_time_s',''),\r\n\t\tDuration=column_ifexists('duration_s',''),\r\n\t\tDisplayType=column_ifexists('display_type_s',''),\r\n\t\tDeviceSessionId=column_ifexists('device_session_id_s',''),\r\n\t\tDevicePlatform=column_ifexists('device_platform_s',''),\r\n\t\tDbTotalTime=column_ifexists('db_total_time_s',''),\r\n\t\tDbCpuTime=column_ifexists('db_cpu_time_s',''),\r\n\t\tDbBlocks=column_ifexists('db_blocks_s',''),\r\n\t\tCpuTime=column_ifexists('cpu_time_s',''),\r\n\t\tConnectionType=column_ifexists('connection_type_s',''),\r\n\t\tComponentName=column_ifexists('component_name_s',''),\r\n\t\tClientVersion=column_ifexists('client_version_s',''),\r\n\t\tClientId=column_ifexists('client_id_s',''),\r\n\t\tCipherSuite=column_ifexists('cipher_suite_s',''),\r\n\t\tCalloutTime=column_ifexists('callout_time_s',''),\r\n\t\tBrowserVersion=column_ifexists('browser_version_s',''),\r\n\t\tBrowserName=column_ifexists('browser_name_s',''),\r\n\t\tAverageRowSize=column_ifexists('average_row_size_s',''),\r\n\t\tAppType=column_ifexists('app_type_s',''),\r\n\t\tAppName=column_ifexists('app_name_s',''),\r\n\t\tApiVersion=column_ifexists('api_version_s',''),\r\n\t\tApiType=column_ifexists('api_type_s',''),\r\n ArticleVersionId=column_ifexists('article_version_id_s',''),\r\n\t\tArticleVersion=column_ifexists('article_version_s',''),\r\n\t\tArticleStatus=column_ifexists('article_status_s',''),\r\n\t\tArticleId=column_ifexists('article_id_s',''),\r\n AnalyticsMode=column_ifexists('analytics_mode_s',''),\r\n BatchId=column_ifexists('batch_id_s',''),\r\n ClickedRecordId=column_ifexists('clicked_record_id_s',''),\r\n\t\tClassName=column_ifexists('class_name_s',''),\r\n ComponentIdDerived=column_ifexists('component_id_derived_s',''),\r\n\t\tComponentId=column_ifexists('component_id_s',''),\r\n ControllerType=column_ifexists('controller_type_s',''),\r\n\t\tContext=column_ifexists('context_s',''),\r\n\t\tConsoleIdDerived=column_ifexists('console_id_derived_s',''),\r\n\t\tConsoleId=column_ifexists('console_id_s',''), \r\n ClientInfo=column_ifexists('client_info_s',''),\r\n DstBytes=column_ifexists('request_size_s',''),\r\n\t\tDstUser=column_ifexists('delegated_user_name_s',''),\r\n DstUserSid=column_ifexists('delegated_user_id_s',''),\r\n\t\tDstUserSidDerived=column_ifexists('delegated_user_id_derived_s',''),\r\n Data=column_ifexists('data_s',''),\r\n\t\tDashboardType=column_ifexists('dashboard_type_s',''),\r\n\t\tDashboardIdDerived=column_ifexists('dashboard_id_derived_s',''),\r\n\t\tDashboardId=column_ifexists('dashboard_id_s',''),\r\n\t\tDashboardComponentId=column_ifexists('dashboard_component_id_s',''),\r\n\t\tDvcAction=column_ifexists('action_s',''),\r\n\t\tDvcOS=column_ifexists('platform_type_s',''),\r\n\t\tDvcOSName=column_ifexists('os_name_s',''),\r\n\t\tDvcOSVersion=column_ifexists('os_version_s',''),\r\n DeliveryLocation=column_ifexists('delivery_location_s',''),\r\n\t\tDeliveryId=column_ifexists('delivery_id_s',''),\r\n DocumentIdDerived=column_ifexists('document_id_derived_s',''),\r\n\t\tDocumentId=column_ifexists('document_id_s',''),\r\n EntityType=column_ifexists('entity_type_s',''),\r\n EntityId=column_ifexists('entity_id_s',''),\r\n FileType=column_ifexists('file_type_s',''),\r\n\t\tFilePreviewType=column_ifexists('file_preview_type_s',''),\r\n\t\tExceptionType=column_ifexists('exception_type_s',''),\r\n\t\tExceptionMessage=column_ifexists('exception_message_s',''),\r\n\t\tEpt=column_ifexists('ept_s',''),\r\n EventCount=column_ifexists('number_of_records_s',''),\r\n\t\tEventEndTime=column_ifexists('timestamp_s',''),\r\n\t\tEventResult=column_ifexists('status_code_s',''),\r\n\t\tFileSize=column_ifexists('size_bytes_s',''),\r\n HttpReferrerOriginal=column_ifexists('referrer_uri_s',''),\r\n\t\tHttpUserAgentOriginal=column_ifexists('user_agent_s',''),\r\n\t\tHttpUserAgent=column_ifexists('browser_type_s',''),\r\n LogGroupId=column_ifexists('log_group_id_s',''),\r\n\t\tLimitUsagePercent=column_ifexists('limit_usage_percent_s',''),\r\n\t\tLicenseContext=column_ifexists('license_context_s',''),\r\n\t\tLastVersion=column_ifexists('last_version_s',''),\r\n\t\tLanguage=column_ifexists('language_s',''),\r\n\t\tJobId=column_ifexists('job_id_s',''),\r\n\t\tIsSuccess=column_ifexists('is_success_s',''),\r\n\t\tIsSecure=column_ifexists('is_secure_s',''),\r\n\t\tIsScheduled=column_ifexists('is_scheduled_s',''),\r\n\t\tIsNew=column_ifexists('is_new_s',''),\r\n\t\tIsMobile=column_ifexists('is_mobile_s',''),\r\n\t\tIsLongRunningRequest=column_ifexists('is_long_running_request_s',''),\r\n\t\tIsGuest=column_ifexists('is_guest_s',''),\r\n\t\tIsFirstRequest=column_ifexists('is_first_request_s',''),\r\n\t\tIsError=column_ifexists('is_error_s',''),\r\n\t\tIsApi=column_ifexists('is_api_s',''),\r\n\t\tIsAjaxRequest=column_ifexists('is_ajax_request_s',''),\r\n ManagedPackageNamespace=column_ifexists('managed_package_namespace_s',''),\r\n HttpHeaders=column_ifexists('http_headers_s',''),\r\n\t\tNetworkDuration=column_ifexists('time_s',''),\r\n Name=column_ifexists('name_s',''),\r\n NumberFailures=column_ifexists('number_failures_s',''),\r\n NumClicks=column_ifexists('num_clicks_s',''),\r\n OperationType=column_ifexists('operation_type_s',''),\r\n\t\tNumSessions=column_ifexists('num_sessions_s',''),\r\n PageName=column_ifexists('page_name_s',''),\r\n Query=column_ifexists('query_s',''),\r\n RequestType=column_ifexists('request_type_s',''),\r\n ReportDescription=column_ifexists('report_description_s',''),\r\n\t\tReopenCount=column_ifexists('reopen_count_s',''),\r\n RelatedEntityId=column_ifexists('related_entity_id_s',''),\r\n RecordIdDerived=column_ifexists('record_id_derived_s',''),\r\n ReadTime=column_ifexists('read_time_s',''),\r\n\t\tRank=column_ifexists('rank_s',''),\r\n\t\tSrcBytes=column_ifexists('response_size_s',''),\r\n\t\tSrcDvcId=column_ifexists('device_id_s',''),\r\n\t\tSrcDvcModelName=column_ifexists('device_model_s',''),\r\n\t\tSrcIpAddr=column_ifexists('source_ip_s',''),\r\n\t\tSrcNatIpAddr=column_ifexists('client_ip_s',''),\r\n SessionId=column_ifexists('session_id_s',''),\r\n SiteId=column_ifexists('site_id_s',''),\r\n\t\tSharingPermission=column_ifexists('sharing_permission_s',''),\r\n\t\tSharingOperation=column_ifexists('sharing_operation_s',''),\r\n\t\tSharedWithEntityId=column_ifexists('shared_with_entity_id_s',''),\r\n\t\tUrlOriginal=column_ifexists('url_s',''),\r\n\t\tWaveTimestamp=column_ifexists('wave_timestamp_s',''),\r\n\t\tWaveSessionId=column_ifexists('wave_session_id_g',''),\r\n\t\tViewStateSize=column_ifexists('view_state_size_s',''),\r\n\t\tVersionIdDerived=column_ifexists('version_id_derived_s',''),\r\n\t\tVersionId=column_ifexists('version_id_s',''),\r\n TriggerType=column_ifexists('trigger_type_s',''),\r\n\t\tTriggerName=column_ifexists('trigger_name_s',''),\r\n\t\tTriggerId=column_ifexists('trigger_id_s',''),\r\n\t\tTransactionType=column_ifexists('transaction_type_s',''),\r\n\t\tTotalTime=column_ifexists('total_time_s',''),\r\n TabId=column_ifexists('tab_id_s',''),\r\n\t\tStackTrace=column_ifexists('stack_trace_s','')\r\n| project-away *_s", - "version": 1, - "tags": [ + "description": "This query searches for failed attempts to log in from more than 15 various users within a 5 minute timeframe from the same source. This is a potential indication of a password spray attack.", + "displayName": "Potential Password Spray Attack", + "enabled": false, + "query": "let FailureThreshold = 15; \nSalesforceServiceCloud\n| where EventType =~ 'Login' and LoginStatus != 'LOGIN_NO_ERROR'\n| where LoginStatus in~ ('LOGIN_ERROR_INVALID_PASSWORD', 'LOGIN_ERROR_SSO_PWD_INVALID')\n| summarize UserCount=dcount(UserId), Users = make_set(UserId,100) by ClientIp, bin(TimeGenerated, 5m)\n| where UserCount > FailureThreshold\n", + "queryFrequency": "PT5M", + "queryPeriod": "PT5M", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "SalesforceServiceCloud" + "dataTypes": [ + "SalesforceServiceCloud" + ], + "connectorId": "SalesforceServiceCloud" } - ] + ], + "tactics": [ + "CredentialAccess" + ], + "techniques": [ + "T1110" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "ClientIp" + } + ], + "entityType": "IP" + } + ], + "customDetails": { + "Users": "Users" + } } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserName1')]" - ], + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", + "description": "Salesforce Service Cloud Analytics Rule 2", + "parentId": "[variables('analyticRuleId2')]", + "contentId": "[variables('_analyticRulecontentId2')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion2')]", "source": { - "name": "Salesforce Service Cloud", "kind": "Solution", + "name": "Salesforce Service Cloud", "sourceId": "[variables('_solutionId')]" }, "author": { @@ -870,114 +913,92 @@ } } ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", - "apiVersion": "2021-06-01", - "name": "[variables('_parserName1')]", - "location": "[parameters('workspace-location')]", - "properties": { - "eTag": "*", - "displayName": "SalesforceServiceCloud", - "category": "Samples", - "functionAlias": "SalesforceServiceCloud", - "query": "\nSalesforceServiceCloud_CL \r\n| extend \r\n\t\tRequestSize=column_ifexists('request_size_s',''),\r\n\t\tExecTime=column_ifexists('exec_time_s',''),\r\n\t\tAction=column_ifexists('action_s',''),\r\n\t\tPlatformType=column_ifexists('platform_type_s',''),\r\n\t\tOsName=column_ifexists('os_name_s',''),\r\n\t\tOsVersion=column_ifexists('os_version_s',''),\r\n\t\tTimestamp=column_ifexists('timestamp_s',''),\r\n\t\tStatusCode=column_ifexists('status_code_s',''),\r\n\t\tEventType=column_ifexists('event_type_s',''),\r\n\t\tReferrerUri=column_ifexists('referrer_uri_s',''),\r\n\t\tUserAgent=column_ifexists('user_agent_s',''),\r\n\t\tBrowserType=column_ifexists('browser_type_s',''),\r\n\t\tTime=column_ifexists('time_s',''),\r\n\t\tResponseSize=column_ifexists('response_size_s',''),\r\n\t\tDeviceId=column_ifexists('device_id_s',''),\r\n\t\tDeviceModel=column_ifexists('device_model_s',''),\r\n\t\tSourceIp=column_ifexists('source_ip_s',''),\r\n\t\tClientIp=column_ifexists('client_ip_s',''),\r\n\t\tSuccess=column_ifexists('success_s',''),\r\n\t\tUri=column_ifexists('uri_s',''),\r\n\t\tUrl=column_ifexists('url_s',''),\r\n\t\tClientName=column_ifexists('client_name_s',''),\r\n\t\tUserType=column_ifexists('user_type_s',''),\r\n\t\tUserInitiatedLogout=column_ifexists('user_initiated_logout_s',''),\r\n\t\tUserIdDerived=column_ifexists('user_id_derived_s',''),\r\n\t\tUserId=column_ifexists('user_id_s',''),\r\n\t\tUserEmail=column_ifexists('user_email_s',''),\r\n\t\tUser=column_ifexists('user_name_s',''),\r\n\t\tUriIdDerived=column_ifexists('uri_id_derived_s',''),\r\n\t\tUiEventType=column_ifexists('ui_event_type_s',''),\r\n\t\tUiEventTimestamp=column_ifexists('ui_event_timestamp_s',''),\r\n\t\tUiEventSource=column_ifexists('ui_event_source_s',''),\r\n\t\tUiEventSequenceNum=column_ifexists('ui_event_sequence_num_s',''),\r\n\t\tUiEventId=column_ifexists('ui_event_id_s',''),\r\n\t\tTlsProtocol=column_ifexists('tls_protocol_s',''),\r\n\t\tTimestampDerived=column_ifexists('timestamp_derived_t',''),\r\n\t\tTargetUiElement=column_ifexists('target_ui_element_s',''),\r\n\t\tSort=column_ifexists('sort_s',''),\r\n\t\tSessionType=column_ifexists('session_type_s',''),\r\n\t\tSessionLevel=column_ifexists('session_level_s',''),\r\n\t\tSessionKey=column_ifexists('session_key_s',''),\r\n\t\tSearchQuery=column_ifexists('search_query_s',''),\r\n\t\tSdkVersion=column_ifexists('sdk_version_s',''),\r\n\t\tSdkAppVersion=column_ifexists('sdk_app_version_s',''),\r\n\t\tSdkAppType=column_ifexists('sdk_app_type_s',''),\r\n\t\tRunTime=column_ifexists('run_time_s',''),\r\n\t\tRowsProcessed=column_ifexists('rows_processed_s',''),\r\n\t\tRowCount=column_ifexists('row_count_s',''),\r\n\t\tResolutionType=column_ifexists('resolution_type_s',''),\r\n\t\tRequestStatus=column_ifexists('request_status_s',''),\r\n\t\tRequestId=column_ifexists('request_id_s',''),\r\n\t\tReportIdDerived=column_ifexists('report_id_derived_s',''),\r\n\t\tReportId=column_ifexists('report_id_s',''),\r\n\t\tRenderingType=column_ifexists('rendering_type_s',''),\r\n\t\tRelatedList=column_ifexists('related_list_s',''),\r\n\t\tRecordType=column_ifexists('record_type_s',''),\r\n\t\tRecordId=column_ifexists('record_id_s',''),\r\n\t\tQuiddity=column_ifexists('quiddity_s',''),\r\n\t\tQueryId=column_ifexists('query_id_s',''),\r\n\t\tPrevpageUrl=column_ifexists('prevpage_url_s',''),\r\n\t\tPrevpageEntityType=column_ifexists('prevpage_entity_type_s',''),\r\n\t\tPrevpageEntityId=column_ifexists('prevpage_entity_id_s',''),\r\n\t\tPrevpageContext=column_ifexists('prevpage_context_s',''),\r\n\t\tPrevpageAppName=column_ifexists('prevpage_app_name_s',''),\r\n\t\tPrefixesSearched=column_ifexists('prefixes_searched_s',''),\r\n\t\tParentUiElement=column_ifexists('parent_ui_element_s',''),\r\n\t\tPageUrl=column_ifexists('page_url_s',''),\r\n\t\tPageStartTime=column_ifexists('page_start_time_s',''),\r\n\t\tPageEntityType=column_ifexists('page_entity_type_s',''),\r\n\t\tPageEntityId=column_ifexists('page_entity_id_s',''),\r\n\t\tPageContext=column_ifexists('page_context_s',''),\r\n\t\tPageAppName=column_ifexists('page_app_name_s',''),\r\n\t\tOrigin=column_ifexists('origin_s',''),\r\n\t\tOrganizationId=column_ifexists('organization_id_s',''),\r\n\t\tNumResults=column_ifexists('num_results_s',''),\r\n\t\tNumberSoqlQueries=column_ifexists('number_soql_queries_s',''),\r\n\t\tNumberFields=column_ifexists('number_fields_s',''),\r\n\t\tNumberExceptionFilters=column_ifexists('number_exception_filters_s',''),\r\n\t\tNumberColumns=column_ifexists('number_columns_s',''),\r\n\t\tNumberBuckets=column_ifexists('number_buckets_s',''),\r\n\t\tMethodName=column_ifexists('method_name_s',''),\r\n\t\tMethod=column_ifexists('method_s',''),\r\n\t\tMediaType=column_ifexists('media_type_s',''),\r\n\t\tLoginStatus=column_ifexists('login_status_s',''),\r\n\t\tLoginKey=column_ifexists('login_key_s',''),\r\n\t\tHttpMethod=column_ifexists('http_method_s',''),\r\n\t\tGrandparentUiElement=column_ifexists('grandparent_ui_element_s',''),\r\n\t\tEntryPoint=column_ifexists('entry_point_s',''),\r\n\t\tEntityName=column_ifexists('entity_name_s',''),\r\n\t\tEntity=column_ifexists('entity_s',''),\r\n\t\tEffectivePageTime=column_ifexists('effective_page_time_s',''),\r\n\t\tDuration=column_ifexists('duration_s',''),\r\n\t\tDisplayType=column_ifexists('display_type_s',''),\r\n\t\tDeviceSessionId=column_ifexists('device_session_id_s',''),\r\n\t\tDevicePlatform=column_ifexists('device_platform_s',''),\r\n\t\tDbTotalTime=column_ifexists('db_total_time_s',''),\r\n\t\tDbCpuTime=column_ifexists('db_cpu_time_s',''),\r\n\t\tDbBlocks=column_ifexists('db_blocks_s',''),\r\n\t\tCpuTime=column_ifexists('cpu_time_s',''),\r\n\t\tConnectionType=column_ifexists('connection_type_s',''),\r\n\t\tComponentName=column_ifexists('component_name_s',''),\r\n\t\tClientVersion=column_ifexists('client_version_s',''),\r\n\t\tClientId=column_ifexists('client_id_s',''),\r\n\t\tCipherSuite=column_ifexists('cipher_suite_s',''),\r\n\t\tCalloutTime=column_ifexists('callout_time_s',''),\r\n\t\tBrowserVersion=column_ifexists('browser_version_s',''),\r\n\t\tBrowserName=column_ifexists('browser_name_s',''),\r\n\t\tAverageRowSize=column_ifexists('average_row_size_s',''),\r\n\t\tAppType=column_ifexists('app_type_s',''),\r\n\t\tAppName=column_ifexists('app_name_s',''),\r\n\t\tApiVersion=column_ifexists('api_version_s',''),\r\n\t\tApiType=column_ifexists('api_type_s',''),\r\n ArticleVersionId=column_ifexists('article_version_id_s',''),\r\n\t\tArticleVersion=column_ifexists('article_version_s',''),\r\n\t\tArticleStatus=column_ifexists('article_status_s',''),\r\n\t\tArticleId=column_ifexists('article_id_s',''),\r\n AnalyticsMode=column_ifexists('analytics_mode_s',''),\r\n BatchId=column_ifexists('batch_id_s',''),\r\n ClickedRecordId=column_ifexists('clicked_record_id_s',''),\r\n\t\tClassName=column_ifexists('class_name_s',''),\r\n ComponentIdDerived=column_ifexists('component_id_derived_s',''),\r\n\t\tComponentId=column_ifexists('component_id_s',''),\r\n ControllerType=column_ifexists('controller_type_s',''),\r\n\t\tContext=column_ifexists('context_s',''),\r\n\t\tConsoleIdDerived=column_ifexists('console_id_derived_s',''),\r\n\t\tConsoleId=column_ifexists('console_id_s',''), \r\n ClientInfo=column_ifexists('client_info_s',''),\r\n DstBytes=column_ifexists('request_size_s',''),\r\n\t\tDstUser=column_ifexists('delegated_user_name_s',''),\r\n DstUserSid=column_ifexists('delegated_user_id_s',''),\r\n\t\tDstUserSidDerived=column_ifexists('delegated_user_id_derived_s',''),\r\n Data=column_ifexists('data_s',''),\r\n\t\tDashboardType=column_ifexists('dashboard_type_s',''),\r\n\t\tDashboardIdDerived=column_ifexists('dashboard_id_derived_s',''),\r\n\t\tDashboardId=column_ifexists('dashboard_id_s',''),\r\n\t\tDashboardComponentId=column_ifexists('dashboard_component_id_s',''),\r\n\t\tDvcAction=column_ifexists('action_s',''),\r\n\t\tDvcOS=column_ifexists('platform_type_s',''),\r\n\t\tDvcOSName=column_ifexists('os_name_s',''),\r\n\t\tDvcOSVersion=column_ifexists('os_version_s',''),\r\n DeliveryLocation=column_ifexists('delivery_location_s',''),\r\n\t\tDeliveryId=column_ifexists('delivery_id_s',''),\r\n DocumentIdDerived=column_ifexists('document_id_derived_s',''),\r\n\t\tDocumentId=column_ifexists('document_id_s',''),\r\n EntityType=column_ifexists('entity_type_s',''),\r\n EntityId=column_ifexists('entity_id_s',''),\r\n FileType=column_ifexists('file_type_s',''),\r\n\t\tFilePreviewType=column_ifexists('file_preview_type_s',''),\r\n\t\tExceptionType=column_ifexists('exception_type_s',''),\r\n\t\tExceptionMessage=column_ifexists('exception_message_s',''),\r\n\t\tEpt=column_ifexists('ept_s',''),\r\n EventCount=column_ifexists('number_of_records_s',''),\r\n\t\tEventEndTime=column_ifexists('timestamp_s',''),\r\n\t\tEventResult=column_ifexists('status_code_s',''),\r\n\t\tFileSize=column_ifexists('size_bytes_s',''),\r\n HttpReferrerOriginal=column_ifexists('referrer_uri_s',''),\r\n\t\tHttpUserAgentOriginal=column_ifexists('user_agent_s',''),\r\n\t\tHttpUserAgent=column_ifexists('browser_type_s',''),\r\n LogGroupId=column_ifexists('log_group_id_s',''),\r\n\t\tLimitUsagePercent=column_ifexists('limit_usage_percent_s',''),\r\n\t\tLicenseContext=column_ifexists('license_context_s',''),\r\n\t\tLastVersion=column_ifexists('last_version_s',''),\r\n\t\tLanguage=column_ifexists('language_s',''),\r\n\t\tJobId=column_ifexists('job_id_s',''),\r\n\t\tIsSuccess=column_ifexists('is_success_s',''),\r\n\t\tIsSecure=column_ifexists('is_secure_s',''),\r\n\t\tIsScheduled=column_ifexists('is_scheduled_s',''),\r\n\t\tIsNew=column_ifexists('is_new_s',''),\r\n\t\tIsMobile=column_ifexists('is_mobile_s',''),\r\n\t\tIsLongRunningRequest=column_ifexists('is_long_running_request_s',''),\r\n\t\tIsGuest=column_ifexists('is_guest_s',''),\r\n\t\tIsFirstRequest=column_ifexists('is_first_request_s',''),\r\n\t\tIsError=column_ifexists('is_error_s',''),\r\n\t\tIsApi=column_ifexists('is_api_s',''),\r\n\t\tIsAjaxRequest=column_ifexists('is_ajax_request_s',''),\r\n ManagedPackageNamespace=column_ifexists('managed_package_namespace_s',''),\r\n HttpHeaders=column_ifexists('http_headers_s',''),\r\n\t\tNetworkDuration=column_ifexists('time_s',''),\r\n Name=column_ifexists('name_s',''),\r\n NumberFailures=column_ifexists('number_failures_s',''),\r\n NumClicks=column_ifexists('num_clicks_s',''),\r\n OperationType=column_ifexists('operation_type_s',''),\r\n\t\tNumSessions=column_ifexists('num_sessions_s',''),\r\n PageName=column_ifexists('page_name_s',''),\r\n Query=column_ifexists('query_s',''),\r\n RequestType=column_ifexists('request_type_s',''),\r\n ReportDescription=column_ifexists('report_description_s',''),\r\n\t\tReopenCount=column_ifexists('reopen_count_s',''),\r\n RelatedEntityId=column_ifexists('related_entity_id_s',''),\r\n RecordIdDerived=column_ifexists('record_id_derived_s',''),\r\n ReadTime=column_ifexists('read_time_s',''),\r\n\t\tRank=column_ifexists('rank_s',''),\r\n\t\tSrcBytes=column_ifexists('response_size_s',''),\r\n\t\tSrcDvcId=column_ifexists('device_id_s',''),\r\n\t\tSrcDvcModelName=column_ifexists('device_model_s',''),\r\n\t\tSrcIpAddr=column_ifexists('source_ip_s',''),\r\n\t\tSrcNatIpAddr=column_ifexists('client_ip_s',''),\r\n SessionId=column_ifexists('session_id_s',''),\r\n SiteId=column_ifexists('site_id_s',''),\r\n\t\tSharingPermission=column_ifexists('sharing_permission_s',''),\r\n\t\tSharingOperation=column_ifexists('sharing_operation_s',''),\r\n\t\tSharedWithEntityId=column_ifexists('shared_with_entity_id_s',''),\r\n\t\tUrlOriginal=column_ifexists('url_s',''),\r\n\t\tWaveTimestamp=column_ifexists('wave_timestamp_s',''),\r\n\t\tWaveSessionId=column_ifexists('wave_session_id_g',''),\r\n\t\tViewStateSize=column_ifexists('view_state_size_s',''),\r\n\t\tVersionIdDerived=column_ifexists('version_id_derived_s',''),\r\n\t\tVersionId=column_ifexists('version_id_s',''),\r\n TriggerType=column_ifexists('trigger_type_s',''),\r\n\t\tTriggerName=column_ifexists('trigger_name_s',''),\r\n\t\tTriggerId=column_ifexists('trigger_id_s',''),\r\n\t\tTransactionType=column_ifexists('transaction_type_s',''),\r\n\t\tTotalTime=column_ifexists('total_time_s',''),\r\n TabId=column_ifexists('tab_id_s',''),\r\n\t\tStackTrace=column_ifexists('stack_trace_s','')\r\n| project-away *_s", - "version": 1 - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "location": "[parameters('workspace-location')]", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserId1')]" - ], - "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", - "source": { - "kind": "Solution", - "name": "Salesforce Service Cloud", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com/" - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('workbookTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, - "properties": { - "description": "Salesforce Service Cloud Workbook with template", - "displayName": "Salesforce Service Cloud workbook template" + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId2')]", + "contentKind": "AnalyticsRule", + "displayName": "Potential Password Spray Attack", + "contentProductId": "[variables('_analyticRulecontentProductId2')]", + "id": "[variables('_analyticRulecontentProductId2')]", + "version": "[variables('analyticRuleVersion2')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('workbookTemplateSpecName1'),'/',variables('workbookVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName3')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('workbookTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SalesforceServiceCloudWorkbook with template version 2.0.4", + "description": "Salesforce-SigninsMultipleCountries_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('workbookVersion1')]", + "contentVersion": "[variables('analyticRuleVersion3')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.Insights/workbooks", - "name": "[variables('workbookContentId1')]", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId3')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", - "kind": "shared", - "apiVersion": "2021-08-01", - "metadata": { - "description": "Sets the time name for analysis." - }, "properties": { - "displayName": "[parameters('workbook1-name')]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Salesforce Service Cloud Workbook\\n---\\n\\nThis workbook brings together queries and visualizations to assist you in identifying potential threats in your Salesforce Service cloud audit data. Visualizations may not appear if no data is present.\\n\\nTo begin select the desired TimeRange to filter the data to the timeframe you want to focus on. Note if you have a large amount of salesforce service cloud data, queries may timeout with a large time range, if this is the case simply select a smaller time range.: \",\"style\":\"info\"},\"name\":\"text - 2\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"412a09a0-64ae-4614-aec6-cbfc9273b82b\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":1800000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}],\"allowCustom\":true},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 32\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"ae90d1dc-20da-4948-80da-127b210bf152\",\"cellValue\":\"view_tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"User Logins\",\"subTarget\":\"1\",\"style\":\"link\"},{\"id\":\"af58b4d9-a888-43ed-91a9-6e9f539a61d4\",\"cellValue\":\"view_tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"API Usage\",\"subTarget\":\"2\",\"style\":\"link\"}]},\"name\":\"links - 34\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"title\":\"User login locations\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let Countrydb = externaldata(Network:string, geoname_id:string, continent_code:string, continent_name:string, country_iso_code:string, country_name:string)\\n[@\\\"https://raw.githubusercontent.com/datasets/geoip2-ipv4/master/data/geoip2-ipv4.csv\\\"];\\nlet UsersLocation = SalesforceServiceCloud\\n| where EventType == \\\"Login\\\"\\n| project TimeGenerated, SourceIp;\\nUsersLocation\\n| extend Dummy=1\\n| summarize count() by Hour=bin(TimeGenerated,24h), SourceIp,Dummy\\n| partition by Hour(\\n lookup (Countrydb|extend Dummy=1) on Dummy\\n | where ipv4_is_match(SourceIp, Network)\\n )\\n| summarize sum(count_) by country_name\",\"size\":3,\"title\":\"Heat Map- Geographical - {TimeRange:label}\",\"timeContextFromParameter\":\"TimeRange\",\"exportedParameters\":[{\"fieldName\":\"TimeGenerated\",\"parameterName\":\"RetTime\"},{\"parameterType\":1}],\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"map\",\"chartSettings\":{\"showLegend\":true},\"mapSettings\":{\"locInfo\":\"CountryRegion\",\"locInfoColumn\":\"country_name\",\"sizeSettings\":\"sum_count_\",\"sizeAggregation\":\"Sum\",\"legendMetric\":\"sum_count_\",\"legendAggregation\":\"Sum\",\"itemColorSettings\":{\"nodeColorField\":\"sum_count_\",\"colorAggregation\":\"Sum\",\"type\":\"heatmap\",\"heatmapPalette\":\"greenRed\"}}},\"customWidth\":\"70\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| summarize AvgLogintime = avg(toint(RunTime)), MaxLoginTime = max(toint(RunTime)), TotalLoginRequests = count() by EventType\\r\\n| project-away EventType\",\"size\":1,\"title\":\"Overview - User login requests\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"AvgLogintime\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":23,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"MaxLoginTime\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":23,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"TotalLoginRequests\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\"}}}],\"rowLimit\":1},\"tileSettings\":{\"showBorder\":false}},\"customWidth\":\"30\",\"name\":\"query - 8\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| summarize count() by bin(TimeGenerated, 1h),User, ClientIp \\r\\n| top 10 by count_\",\"size\":0,\"title\":\"Top 10 users with maximun logins - {TimeRange:label}\",\"exportFieldName\":\"UserId\",\"exportParameterName\":\"RetUser\",\"exportDefaultValue\":\"all users\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"user_name_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TimeGenerated\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false},\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"60\",\"name\":\"query - 2\"},{\"type\":1,\"content\":{\"json\":\"To leverage infomation about Malicious IP, Threat Indicator solution should be configured and ThreatIntelligenceIndicator table should have information of malicious IP.\",\"style\":\"info\"},\"customWidth\":\"10\",\"name\":\"text - 8\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\" let malicious_ips =\\r\\n ThreatIntelligenceIndicator\\r\\n | where isnotempty(NetworkIP)\\r\\n | summarize make_list(NetworkIP); \\r\\n SalesforceServiceCloud\\r\\n | where EventType == 'Login'\\r\\n | distinct User,ClientIp\\r\\n | where ClientIp in (malicious_ips)\\r\\n | project UserName = User, MaliciousIP = ClientIp\\r\\n\",\"size\":1,\"title\":\"Malicious IP- User Login\",\"noDataMessage\":\"No Malicious IP found\",\"timeBrushParameterName\":\"TimeBrush\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"min\":0,\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"MaliciousIP\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}]},\"graphSettings\":{\"type\":0},\"chartSettings\":{\"showMetrics\":false}},\"customWidth\":\"30\",\"name\":\"query - 23\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'LoginAS'\\r\\n| project UserID = UserId,DerivedUSerID = UserIdDerived,EventType = EventType, IPAddress = ClientIp, LoginKey = LoginKey, OrgID = OrganizationId, RequestID = RequestId, SessionKey = SessionKey\\r\\n| limit 10\",\"size\":0,\"title\":\"User Activity- LoginAS(Top 10)\",\"noDataMessage\":\"No user impersonation found\",\"exportFieldName\":\"IPAddress\",\"exportParameterName\":\"RetIP\",\"exportDefaultValue\":\"all IP addresses\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"IPAddress\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalRecords\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"60\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'LoginAs'\\r\\n| where isnotempty(User)\\r\\n| summarize count() by User,UserIdDerived,ClientIp\\r\\n| project UserName = User,DerivedUSerID = UserIdDerived,IPAddress = ClientIp, count_\",\"size\":1,\"title\":\"User Impersonation from different IP Addresses\",\"color\":\"blue\",\"noDataMessage\":\"No user impersonation found\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"DerivedUSerID\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"IPAddress\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"count_\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}],\"labelSettings\":[{\"columnId\":\"UserName\",\"label\":\"User Name\"},{\"columnId\":\"DerivedUSerID\",\"label\":\"Impersonated ID\"},{\"columnId\":\"IPAddress\",\"label\":\"IP Address\"},{\"columnId\":\"count_\",\"label\":\"Total Login\"}]},\"chartSettings\":{\"xAxis\":\"IPAddress\",\"yAxis\":[\"count_\"],\"showLegend\":true}},\"customWidth\":\"40\",\"name\":\"query - 24\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| where isnotempty(User)\\r\\n| project UserName= User,APIType= ApiType, Browser= BrowserType, CipherSuite =CipherSuite, IP =ClientIp, CPUTime=CpuTime, UserType = UserType\\r\\n| take 200\",\"size\":0,\"title\":\"User Successful Login Activity\",\"timeContext\":{\"durationMs\":86400000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\"},\"customWidth\":\"60\",\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == 'Login'\\r\\n| where isnotempty(User)\\r\\n| where LoginStatus !has('LOGIN_NO_ERROR')\\r\\n| summarize count() by User, ClientIp\\r\\n| project UserName = User, IP = ClientIp, Count = count_\",\"size\":1,\"title\":\"User Unsuccessful Logins by IP\",\"noDataMessage\":\"No Unsucessful Login found\",\"timeContext\":{\"durationMs\":86400000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"UserName\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"IP\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"Count\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}}],\"labelSettings\":[{\"columnId\":\"UserName\",\"label\":\"User Name\"},{\"columnId\":\"IP\",\"label\":\"IP Address\"},{\"columnId\":\"Count\",\"label\":\"Count\"}]},\"chartSettings\":{\"xAxis\":\"UserName\",\"yAxis\":[\"Count\"],\"ySettings\":{\"numberFormatSettings\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"useGrouping\":true}}}}},\"customWidth\":\"30\",\"name\":\"query - 5\"}]},\"conditionalVisibility\":{\"parameterName\":\"view_tab\",\"comparison\":\"isEqualTo\",\"value\":\"1\"},\"name\":\"Retrieval Events\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"title\":\"API Usage\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| summarize count() by EventType\",\"size\":0,\"title\":\"Most fired events\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":50,\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == \\\"ApiTotalUsage\\\"\\r\\n| summarize count() by IPAddress = ClientIp,Entity = EntityName\\r\\n| order by Entity\",\"size\":0,\"title\":\"Most accessed entities by IP Address\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"user_id_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\"}}},{\"columnMatch\":\"entity_name_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"client_ip_s\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"}},{\"columnMatch\":\"count_\",\"formatter\":8,\"formatOptions\":{\"palette\":\"categorical\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\"}}}],\"labelSettings\":[{\"columnId\":\"count_\",\"label\":\"Count\"}]}},\"customWidth\":\"50\",\"name\":\"query - 5\",\"styleSettings\":{\"maxWidth\":\"30%\",\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SalesforceServiceCloud\\r\\n| where EventType == \\\"ApiTotalUsage\\\"\\r\\n| summarize count() by EntityName\",\"size\":0,\"title\":\"Most accessed Entities\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\"},\"name\":\"query - 6\"}]},\"conditionalVisibility\":{\"parameterName\":\"view_tab\",\"comparison\":\"isEqualTo\",\"value\":\"2\"},\"name\":\"APIUsage\"}],\"fromTemplateId\":\"sentinel-SalesforceServiceCloudWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", - "version": "1.0", - "sourceId": "[variables('workspaceResourceId')]", - "category": "sentinel" + "description": "This query searches for successful user logins from different countries within 30min.", + "displayName": "User Sign in from different countries", + "enabled": false, + "query": "let threshold = 2;\nlet Countrydb = externaldata(Network:string, geoname_id:string, continent_code:string, continent_name:string, country_iso_code:string, country_name:string)\n[@\"https://raw.githubusercontent.com/datasets/geoip2-ipv4/master/data/geoip2-ipv4.csv\"];\nlet UsersLocation = SalesforceServiceCloud\n| where EventType =~ 'Login' and LoginStatus=~'LOGIN_NO_ERROR'\n| project TimeGenerated, ClientIp, UserId, User, UserType ;\nUsersLocation\n| extend Dummy=1\n| summarize count() by Hour=bin(TimeGenerated,30m), ClientIp,User, Dummy\n| partition by Hour(\n lookup (Countrydb|extend Dummy=1) on Dummy\n | where ipv4_is_match(ClientIp, Network)\n )\n| summarize NumOfCountries = dcount(country_name) by User, Hour\n| where NumOfCountries >= threshold\n", + "queryFrequency": "PT30M", + "queryPeriod": "PT30M", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "dataTypes": [ + "SalesforceServiceCloud" + ], + "connectorId": "SalesforceServiceCloud" + } + ], + "tactics": [ + "InitialAccess" + ], + "techniques": [ + "T1078" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "AadUserId", + "columnName": "User" + } + ], + "entityType": "Account" + } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", "properties": { - "description": "@{workbookKey=SalesforceServiceCloudWorkbook; logoFileName=salesforce_logo.svg; description=Sets the time name for analysis.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Salesforce Service Cloud; templateRelativePath=SalesforceServiceCloud.json; subtitle=; provider=Salesforce}.description", - "parentId": "[variables('workbookId1')]", - "contentId": "[variables('_workbookContentId1')]", - "kind": "Workbook", - "version": "[variables('workbookVersion1')]", + "description": "Salesforce Service Cloud Analytics Rule 3", + "parentId": "[variables('analyticRuleId3')]", + "contentId": "[variables('_analyticRulecontentId3')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion3')]", "source": { "kind": "Solution", "name": "Salesforce Service Cloud", @@ -992,34 +1013,39 @@ "email": "support@microsoft.com", "tier": "Microsoft", "link": "https://support.microsoft.com/" - }, - "dependencies": { - "operator": "AND", - "criteria": [ - { - "contentId": "SalesforceServiceCloud", - "kind": "DataType" - }, - { - "contentId": "SalesforceServiceCloud_CL", - "kind": "DataConnector" - } - ] } } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId3')]", + "contentKind": "AnalyticsRule", + "displayName": "User Sign in from different countries", + "contentProductId": "[variables('_analyticRulecontentProductId3')]", + "id": "[variables('_analyticRulecontentProductId3')]", + "version": "[variables('analyticRuleVersion3')]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", + "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "2.0.4", + "version": "3.0.0", "kind": "Solution", - "contentSchemaVersion": "2.0.0", + "contentSchemaVersion": "3.0.0", + "displayName": "Salesforce Service Cloud", + "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", + "descriptionHtml": "

Note: There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Salesforce Service Cloud solution for Microsoft Sentinel enables you to ingest Service Cloud events into Microsoft Sentinel.

\n

Underlying Microsoft Technologies used:

\n

This solution takes a dependency on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Azure Monitor HTTP Data Collector API

    \n
  2. \n
  3. Azure Functions.

    \n
  4. \n
\n

Data Connectors: 1, Parsers: 1, Workbooks: 1, Analytic Rules: 3

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "contentKind": "Solution", + "contentProductId": "[variables('_solutioncontentProductId')]", + "id": "[variables('_solutioncontentProductId')]", + "icon": "", "contentId": "[variables('_solutionId')]", "parentId": "[variables('_solutionId')]", "source": { @@ -1040,21 +1066,6 @@ "dependencies": { "operator": "AND", "criteria": [ - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId1')]", - "version": "[variables('analyticRuleVersion1')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId2')]", - "version": "[variables('analyticRuleVersion2')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId3')]", - "version": "[variables('analyticRuleVersion3')]" - }, { "kind": "DataConnector", "contentId": "[variables('_dataConnectorContentId1')]", @@ -1069,6 +1080,21 @@ "kind": "Workbook", "contentId": "[variables('_workbookContentId1')]", "version": "[variables('workbookVersion1')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId1')]", + "version": "[variables('analyticRuleVersion1')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId2')]", + "version": "[variables('analyticRuleVersion2')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId3')]", + "version": "[variables('analyticRuleVersion3')]" } ] }, diff --git a/Solutions/Salesforce Service Cloud/Parsers/SalesforceServiceCloud.txt b/Solutions/Salesforce Service Cloud/Parsers/SalesforceServiceCloud.txt deleted file mode 100644 index 36527634a05..00000000000 --- a/Solutions/Salesforce Service Cloud/Parsers/SalesforceServiceCloud.txt +++ /dev/null @@ -1,218 +0,0 @@ -SalesforceServiceCloud_CL -| extend - RequestSize=column_ifexists('request_size_s',''), - ExecTime=column_ifexists('exec_time_s',''), - Action=column_ifexists('action_s',''), - PlatformType=column_ifexists('platform_type_s',''), - OsName=column_ifexists('os_name_s',''), - OsVersion=column_ifexists('os_version_s',''), - Timestamp=column_ifexists('timestamp_s',''), - StatusCode=column_ifexists('status_code_s',''), - EventType=column_ifexists('event_type_s',''), - ReferrerUri=column_ifexists('referrer_uri_s',''), - UserAgent=column_ifexists('user_agent_s',''), - BrowserType=column_ifexists('browser_type_s',''), - Time=column_ifexists('time_s',''), - ResponseSize=column_ifexists('response_size_s',''), - DeviceId=column_ifexists('device_id_s',''), - DeviceModel=column_ifexists('device_model_s',''), - SourceIp=column_ifexists('source_ip_s',''), - ClientIp=column_ifexists('client_ip_s',''), - Success=column_ifexists('success_s',''), - Uri=column_ifexists('uri_s',''), - Url=column_ifexists('url_s',''), - ClientName=column_ifexists('client_name_s',''), - UserType=column_ifexists('user_type_s',''), - UserInitiatedLogout=column_ifexists('user_initiated_logout_s',''), - UserIdDerived=column_ifexists('user_id_derived_s',''), - UserId=column_ifexists('user_id_s',''), - UserEmail=column_ifexists('user_email_s',''), - User=column_ifexists('user_name_s',''), - UriIdDerived=column_ifexists('uri_id_derived_s',''), - UiEventType=column_ifexists('ui_event_type_s',''), - UiEventTimestamp=column_ifexists('ui_event_timestamp_s',''), - UiEventSource=column_ifexists('ui_event_source_s',''), - UiEventSequenceNum=column_ifexists('ui_event_sequence_num_s',''), - UiEventId=column_ifexists('ui_event_id_s',''), - TlsProtocol=column_ifexists('tls_protocol_s',''), - TimestampDerived=column_ifexists('timestamp_derived_t',''), - TargetUiElement=column_ifexists('target_ui_element_s',''), - Sort=column_ifexists('sort_s',''), - SessionType=column_ifexists('session_type_s',''), - SessionLevel=column_ifexists('session_level_s',''), - SessionKey=column_ifexists('session_key_s',''), - SearchQuery=column_ifexists('search_query_s',''), - SdkVersion=column_ifexists('sdk_version_s',''), - SdkAppVersion=column_ifexists('sdk_app_version_s',''), - SdkAppType=column_ifexists('sdk_app_type_s',''), - RunTime=column_ifexists('run_time_s',''), - RowsProcessed=column_ifexists('rows_processed_s',''), - RowCount=column_ifexists('row_count_s',''), - ResolutionType=column_ifexists('resolution_type_s',''), - RequestStatus=column_ifexists('request_status_s',''), - RequestId=column_ifexists('request_id_s',''), - ReportIdDerived=column_ifexists('report_id_derived_s',''), - ReportId=column_ifexists('report_id_s',''), - RenderingType=column_ifexists('rendering_type_s',''), - RelatedList=column_ifexists('related_list_s',''), - RecordType=column_ifexists('record_type_s',''), - RecordId=column_ifexists('record_id_s',''), - Quiddity=column_ifexists('quiddity_s',''), - QueryId=column_ifexists('query_id_s',''), - PrevpageUrl=column_ifexists('prevpage_url_s',''), - PrevpageEntityType=column_ifexists('prevpage_entity_type_s',''), - PrevpageEntityId=column_ifexists('prevpage_entity_id_s',''), - PrevpageContext=column_ifexists('prevpage_context_s',''), - PrevpageAppName=column_ifexists('prevpage_app_name_s',''), - PrefixesSearched=column_ifexists('prefixes_searched_s',''), - ParentUiElement=column_ifexists('parent_ui_element_s',''), - PageUrl=column_ifexists('page_url_s',''), - PageStartTime=column_ifexists('page_start_time_s',''), - PageEntityType=column_ifexists('page_entity_type_s',''), - PageEntityId=column_ifexists('page_entity_id_s',''), - PageContext=column_ifexists('page_context_s',''), - PageAppName=column_ifexists('page_app_name_s',''), - Origin=column_ifexists('origin_s',''), - OrganizationId=column_ifexists('organization_id_s',''), - NumResults=column_ifexists('num_results_s',''), - NumberSoqlQueries=column_ifexists('number_soql_queries_s',''), - NumberFields=column_ifexists('number_fields_s',''), - NumberExceptionFilters=column_ifexists('number_exception_filters_s',''), - NumberColumns=column_ifexists('number_columns_s',''), - NumberBuckets=column_ifexists('number_buckets_s',''), - MethodName=column_ifexists('method_name_s',''), - Method=column_ifexists('method_s',''), - MediaType=column_ifexists('media_type_s',''), - LoginStatus=column_ifexists('login_status_s',''), - LoginKey=column_ifexists('login_key_s',''), - HttpMethod=column_ifexists('http_method_s',''), - GrandparentUiElement=column_ifexists('grandparent_ui_element_s',''), - EntryPoint=column_ifexists('entry_point_s',''), - EntityName=column_ifexists('entity_name_s',''), - Entity=column_ifexists('entity_s',''), - EffectivePageTime=column_ifexists('effective_page_time_s',''), - Duration=column_ifexists('duration_s',''), - DisplayType=column_ifexists('display_type_s',''), - DeviceSessionId=column_ifexists('device_session_id_s',''), - DevicePlatform=column_ifexists('device_platform_s',''), - DbTotalTime=column_ifexists('db_total_time_s',''), - DbCpuTime=column_ifexists('db_cpu_time_s',''), - DbBlocks=column_ifexists('db_blocks_s',''), - CpuTime=column_ifexists('cpu_time_s',''), - ConnectionType=column_ifexists('connection_type_s',''), - ComponentName=column_ifexists('component_name_s',''), - ClientVersion=column_ifexists('client_version_s',''), - ClientId=column_ifexists('client_id_s',''), - CipherSuite=column_ifexists('cipher_suite_s',''), - CalloutTime=column_ifexists('callout_time_s',''), - BrowserVersion=column_ifexists('browser_version_s',''), - BrowserName=column_ifexists('browser_name_s',''), - AverageRowSize=column_ifexists('average_row_size_s',''), - AppType=column_ifexists('app_type_s',''), - AppName=column_ifexists('app_name_s',''), - ApiVersion=column_ifexists('api_version_s',''), - ApiType=column_ifexists('api_type_s',''), - ArticleVersionId=column_ifexists('article_version_id_s',''), - ArticleVersion=column_ifexists('article_version_s',''), - ArticleStatus=column_ifexists('article_status_s',''), - ArticleId=column_ifexists('article_id_s',''), - AnalyticsMode=column_ifexists('analytics_mode_s',''), - BatchId=column_ifexists('batch_id_s',''), - ClickedRecordId=column_ifexists('clicked_record_id_s',''), - ClassName=column_ifexists('class_name_s',''), - ComponentIdDerived=column_ifexists('component_id_derived_s',''), - ComponentId=column_ifexists('component_id_s',''), - ControllerType=column_ifexists('controller_type_s',''), - Context=column_ifexists('context_s',''), - ConsoleIdDerived=column_ifexists('console_id_derived_s',''), - ConsoleId=column_ifexists('console_id_s',''), - ClientInfo=column_ifexists('client_info_s',''), - DstBytes=column_ifexists('request_size_s',''), - DstUser=column_ifexists('delegated_user_name_s',''), - DstUserSid=column_ifexists('delegated_user_id_s',''), - DstUserSidDerived=column_ifexists('delegated_user_id_derived_s',''), - Data=column_ifexists('data_s',''), - DashboardType=column_ifexists('dashboard_type_s',''), - DashboardIdDerived=column_ifexists('dashboard_id_derived_s',''), - DashboardId=column_ifexists('dashboard_id_s',''), - DashboardComponentId=column_ifexists('dashboard_component_id_s',''), - DvcAction=column_ifexists('action_s',''), - DvcOS=column_ifexists('platform_type_s',''), - DvcOSName=column_ifexists('os_name_s',''), - DvcOSVersion=column_ifexists('os_version_s',''), - DeliveryLocation=column_ifexists('delivery_location_s',''), - DeliveryId=column_ifexists('delivery_id_s',''), - DocumentIdDerived=column_ifexists('document_id_derived_s',''), - DocumentId=column_ifexists('document_id_s',''), - EntityType=column_ifexists('entity_type_s',''), - EntityId=column_ifexists('entity_id_s',''), - FileType=column_ifexists('file_type_s',''), - FilePreviewType=column_ifexists('file_preview_type_s',''), - ExceptionType=column_ifexists('exception_type_s',''), - ExceptionMessage=column_ifexists('exception_message_s',''), - Ept=column_ifexists('ept_s',''), - EventCount=column_ifexists('number_of_records_s',''), - EventEndTime=column_ifexists('timestamp_s',''), - EventResult=column_ifexists('status_code_s',''), - FileSize=column_ifexists('size_bytes_s',''), - HttpReferrerOriginal=column_ifexists('referrer_uri_s',''), - HttpUserAgentOriginal=column_ifexists('user_agent_s',''), - HttpUserAgent=column_ifexists('browser_type_s',''), - LogGroupId=column_ifexists('log_group_id_s',''), - LimitUsagePercent=column_ifexists('limit_usage_percent_s',''), - LicenseContext=column_ifexists('license_context_s',''), - LastVersion=column_ifexists('last_version_s',''), - Language=column_ifexists('language_s',''), - JobId=column_ifexists('job_id_s',''), - IsSuccess=column_ifexists('is_success_s',''), - IsSecure=column_ifexists('is_secure_s',''), - IsScheduled=column_ifexists('is_scheduled_s',''), - IsNew=column_ifexists('is_new_s',''), - IsMobile=column_ifexists('is_mobile_s',''), - IsLongRunningRequest=column_ifexists('is_long_running_request_s',''), - IsGuest=column_ifexists('is_guest_s',''), - IsFirstRequest=column_ifexists('is_first_request_s',''), - IsError=column_ifexists('is_error_s',''), - IsApi=column_ifexists('is_api_s',''), - IsAjaxRequest=column_ifexists('is_ajax_request_s',''), - ManagedPackageNamespace=column_ifexists('managed_package_namespace_s',''), - HttpHeaders=column_ifexists('http_headers_s',''), - NetworkDuration=column_ifexists('time_s',''), - Name=column_ifexists('name_s',''), - NumberFailures=column_ifexists('number_failures_s',''), - NumClicks=column_ifexists('num_clicks_s',''), - OperationType=column_ifexists('operation_type_s',''), - NumSessions=column_ifexists('num_sessions_s',''), - PageName=column_ifexists('page_name_s',''), - Query=column_ifexists('query_s',''), - RequestType=column_ifexists('request_type_s',''), - ReportDescription=column_ifexists('report_description_s',''), - ReopenCount=column_ifexists('reopen_count_s',''), - RelatedEntityId=column_ifexists('related_entity_id_s',''), - RecordIdDerived=column_ifexists('record_id_derived_s',''), - ReadTime=column_ifexists('read_time_s',''), - Rank=column_ifexists('rank_s',''), - SrcBytes=column_ifexists('response_size_s',''), - SrcDvcId=column_ifexists('device_id_s',''), - SrcDvcModelName=column_ifexists('device_model_s',''), - SrcIpAddr=column_ifexists('source_ip_s',''), - SrcNatIpAddr=column_ifexists('client_ip_s',''), - SessionId=column_ifexists('session_id_s',''), - SiteId=column_ifexists('site_id_s',''), - SharingPermission=column_ifexists('sharing_permission_s',''), - SharingOperation=column_ifexists('sharing_operation_s',''), - SharedWithEntityId=column_ifexists('shared_with_entity_id_s',''), - UrlOriginal=column_ifexists('url_s',''), - WaveTimestamp=column_ifexists('wave_timestamp_s',''), - WaveSessionId=column_ifexists('wave_session_id_g',''), - ViewStateSize=column_ifexists('view_state_size_s',''), - VersionIdDerived=column_ifexists('version_id_derived_s',''), - VersionId=column_ifexists('version_id_s',''), - TriggerType=column_ifexists('trigger_type_s',''), - TriggerName=column_ifexists('trigger_name_s',''), - TriggerId=column_ifexists('trigger_id_s',''), - TransactionType=column_ifexists('transaction_type_s',''), - TotalTime=column_ifexists('total_time_s',''), - TabId=column_ifexists('tab_id_s',''), - StackTrace=column_ifexists('stack_trace_s','') -| project-away *_s \ No newline at end of file diff --git a/Solutions/Salesforce Service Cloud/ReleaseNotes.md b/Solutions/Salesforce Service Cloud/ReleaseNotes.md new file mode 100644 index 00000000000..6c1f40e5e37 --- /dev/null +++ b/Solutions/Salesforce Service Cloud/ReleaseNotes.md @@ -0,0 +1,4 @@ +| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | +|-------------|--------------------------------|--------------------------------------------------------------------| +| 3.0.0 | 05-09-2023 | Manual deployment instructions updated for **Data Connector** | +