diff --git a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-BruteForce.yaml b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-BruteForce.yaml index 4e9671a385a..4beb903745a 100644 --- a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-BruteForce.yaml +++ b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-BruteForce.yaml @@ -9,8 +9,8 @@ requiredDataConnectors: - connectorId: SalesforceServiceCloud dataTypes: - SalesforceServiceCloud -queryFrequency: 20m -queryPeriod: 20m +queryFrequency: 1h +queryPeriod: 1h triggerOperator: gt triggerThreshold: 0 tactics: @@ -48,5 +48,5 @@ entityMappings: fieldMappings: - identifier: FullName columnName: User -version: 1.0.2 +version: 1.0.3 kind: Scheduled diff --git a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-PasswordSpray.yaml b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-PasswordSpray.yaml index 87e876cc6f4..c0f529eb24e 100644 --- a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-PasswordSpray.yaml +++ b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-PasswordSpray.yaml @@ -1,15 +1,15 @@ id: 64d16e62-1a17-4a35-9ea7-2b9fe6f07118 name: Potential Password Spray Attack 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.' + 'This query searches for failed attempts to log in from more than 15 various users within a 5 minutes timeframe from the same source. This is a potential indication of a password spray attack.' severity: Medium status: Available requiredDataConnectors: - connectorId: SalesforceServiceCloud dataTypes: - SalesforceServiceCloud -queryFrequency: 5m -queryPeriod: 5m +queryFrequency: 1h +queryPeriod: 1h triggerOperator: gt triggerThreshold: 0 tactics: @@ -30,5 +30,5 @@ entityMappings: fieldMappings: - identifier: Address columnName: ClientIp -version: 1.0.1 +version: 1.0.2 kind: Scheduled diff --git a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-SigninsMultipleCountries.yaml b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-SigninsMultipleCountries.yaml index ab5110384cf..be83c9a9b72 100644 --- a/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-SigninsMultipleCountries.yaml +++ b/Solutions/Salesforce Service Cloud/Analytic Rules/Salesforce-SigninsMultipleCountries.yaml @@ -1,15 +1,15 @@ id: 3094e036-e5ae-4d6e-8626-b0f86ebc71f2 name: User Sign in from different countries description: | - 'This query searches for successful user logins from different countries within 30min.' + 'This query searches for successful user logins from different countries within 30 mins.' severity: Medium status: Available requiredDataConnectors: - connectorId: SalesforceServiceCloud dataTypes: - SalesforceServiceCloud -queryFrequency: 30m -queryPeriod: 30m +queryFrequency: 1h +queryPeriod: 1h triggerOperator: gt triggerThreshold: 0 tactics: @@ -37,5 +37,5 @@ entityMappings: fieldMappings: - identifier: AadUserId columnName: User -version: 1.0.1 +version: 1.0.2 kind: Scheduled diff --git a/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json b/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json index 5ea02a1e7c2..abc268eef29 100644 --- a/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json +++ b/Solutions/Salesforce Service Cloud/Data/Solution_TSalesforceCloudtemplateSpec.json @@ -18,7 +18,7 @@ "Workbooks/SalesforceServiceCloud.json" ], "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Salesforce Service Cloud", - "Version": "3.0.0", + "Version": "3.0.1", "Metadata": "SolutionMetadata.json", "TemplateSpec": true, "Is1PConnector": false diff --git a/Solutions/Salesforce Service Cloud/Package/3.0.1.zip b/Solutions/Salesforce Service Cloud/Package/3.0.1.zip new file mode 100644 index 00000000000..dce111c4e42 Binary files /dev/null and b/Solutions/Salesforce Service Cloud/Package/3.0.1.zip differ diff --git a/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json b/Solutions/Salesforce Service Cloud/Package/createUiDefinition.json index 09c7fec5421..e530e25d63f 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:** 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)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Salesforce%20Service%20Cloud/ReleaseNotes.md)\n\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": "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." + "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." } }, { "name": "dataconnectors-parser-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The solution installs a parser that transforms ingested data. The transformed logs can be accessed using the SalesforceServiceCloud Kusto Function alias." + "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." } }, { @@ -159,7 +159,7 @@ "name": "analytic1-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "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." + "text": "Identifies evidence of brute force activity against a user based on multiple authentication failures and 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." } } ] @@ -173,7 +173,7 @@ "name": "analytic2-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "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." + "text": "This query searches for failed attempts to log in from more than 15 various users within a 5 minutes timeframe from the same source. This is a potential indication of a password spray attack." } } ] @@ -187,7 +187,7 @@ "name": "analytic3-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This query searches for successful user logins from different countries within 30min." + "text": "This query searches for successful user logins from different countries within 30 mins." } } ] diff --git a/Solutions/Salesforce Service Cloud/Package/mainTemplate.json b/Solutions/Salesforce Service Cloud/Package/mainTemplate.json index b114a3242f1..22b044525a9 100644 --- a/Solutions/Salesforce Service Cloud/Package/mainTemplate.json +++ b/Solutions/Salesforce Service Cloud/Package/mainTemplate.json @@ -38,12 +38,33 @@ } }, "variables": { - "solutionId": "azuresentinel.azure-sentinel-solution-salesforceservicecloud", - "_solutionId": "[variables('solutionId')]", "email": "support@microsoft.com", "_email": "[variables('email')]", "_solutionName": "Salesforce Service Cloud", - "_solutionVersion": "3.0.0", + "_solutionVersion": "3.0.1", + "solutionId": "azuresentinel.azure-sentinel-solution-salesforceservicecloud", + "_solutionId": "[variables('solutionId')]", + "analyticRuleObject1": { + "analyticRuleVersion1": "1.0.3", + "_analyticRulecontentId1": "5a6ce089-e756-40fb-b022-c8e8864a973a", + "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', '5a6ce089-e756-40fb-b022-c8e8864a973a')]", + "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring('5a6ce089-e756-40fb-b022-c8e8864a973a')))]", + "_analyticRulecontentProductId1": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-','5a6ce089-e756-40fb-b022-c8e8864a973a','-', '1.0.3')))]" + }, + "analyticRuleObject2": { + "analyticRuleVersion2": "1.0.2", + "_analyticRulecontentId2": "64d16e62-1a17-4a35-9ea7-2b9fe6f07118", + "analyticRuleId2": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', '64d16e62-1a17-4a35-9ea7-2b9fe6f07118')]", + "analyticRuleTemplateSpecName2": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring('64d16e62-1a17-4a35-9ea7-2b9fe6f07118')))]", + "_analyticRulecontentProductId2": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-','64d16e62-1a17-4a35-9ea7-2b9fe6f07118','-', '1.0.2')))]" + }, + "analyticRuleObject3": { + "analyticRuleVersion3": "1.0.2", + "_analyticRulecontentId3": "3094e036-e5ae-4d6e-8626-b0f86ebc71f2", + "analyticRuleId3": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', '3094e036-e5ae-4d6e-8626-b0f86ebc71f2')]", + "analyticRuleTemplateSpecName3": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring('3094e036-e5ae-4d6e-8626-b0f86ebc71f2')))]", + "_analyticRulecontentProductId3": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-','3094e036-e5ae-4d6e-8626-b0f86ebc71f2','-', '1.0.2')))]" + }, "uiConfigId1": "SalesforceServiceCloud", "_uiConfigId1": "[variables('uiConfigId1')]", "dataConnectorContentId1": "SalesforceServiceCloud", @@ -53,15 +74,13 @@ "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", "dataConnectorVersion1": "1.0.0", "_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'),'/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'))))]", + "parserObject1": { + "_parserName1": "[concat(parameters('workspace'),'/','SalesforceServiceCloud')]", + "_parserId1": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), 'SalesforceServiceCloud')]", + "parserTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-pr-',uniquestring('SalesforceServiceCloud-Parser')))]", + "parserVersion1": "1.0.0", + "parserContentId1": "SalesforceServiceCloud-Parser" + }, "workbookVersion1": "1.0.0", "workbookContentId1": "SalesforceServiceCloudWorkbook", "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", @@ -69,209 +88,86 @@ "_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.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName1')]", + "name": "[variables('analyticRuleObject1').analyticRuleTemplateSpecName1]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Salesforce Service Cloud data connector with template version 3.0.0", + "description": "Salesforce-BruteForce_AnalyticalRules Analytics Rule with template version 3.0.1", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion1')]", + "contentVersion": "[variables('analyticRuleObject1').analyticRuleVersion1]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRuleObject1')._analyticRulecontentId1]", + "apiVersion": "2023-02-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", - "kind": "GenericUI", "properties": { - "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 - } - }, - { - "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 - } - } + "description": "Identifies evidence of brute force activity against a user based on multiple authentication failures and 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": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "dataTypes": [ + "SalesforceServiceCloud" ], - "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/)." - }, + "connectorId": "SalesforceServiceCloud" + } + ], + "tactics": [ + "CredentialAccess" + ], + "techniques": [ + "T1110" + ], + "entityMappings": [ + { + "fieldMappings": [ { - "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)." + "identifier": "FullName", + "columnName": "User" } - ] - }, - "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" - } - ] - } - ] + ], + "entityType": "Account" + } + ], + "customDetails": { + "EventStartTime": "FailureStartTime", + "IPAddresses": "IpAddresses", + "EventEndTime": "SuccessEndTime" } } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleObject1').analyticRuleId1,'/'))))]", "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", + "description": "Salesforce Service Cloud Analytics Rule 1", + "parentId": "[variables('analyticRuleObject1').analyticRuleId1]", + "contentId": "[variables('analyticRuleObject1')._analyticRulecontentId1]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleObject1').analyticRuleVersion1]", "source": { "kind": "Solution", "name": "Salesforce Service Cloud", @@ -296,234 +192,179 @@ "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')]" + "contentId": "[variables('analyticRuleObject1')._analyticRulecontentId1]", + "contentKind": "AnalyticsRule", + "displayName": "Brute force attack against user credentials", + "contentProductId": "[variables('analyticRuleObject1')._analyticRulecontentProductId1]", + "id": "[variables('analyticRuleObject1')._analyticRulecontentProductId1]", + "version": "[variables('analyticRuleObject1').analyticRuleVersion1]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "name": "[variables('analyticRuleObject2').analyticRuleTemplateSpecName2]", + "location": "[parameters('workspace-location')]", "dependsOn": [ - "[variables('_dataConnectorId1')]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], - "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/" - } - } - }, - { - "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": { - "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": [ - { - "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." - }, - { - "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": "Salesforce-PasswordSpray_AnalyticalRules Analytics Rule with template version 3.0.1", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('analyticRuleObject2').analyticRuleVersion2]", + "parameters": {}, + "variables": {}, + "resources": [ { - "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" + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRuleObject2')._analyticRulecontentId2]", + "apiVersion": "2023-02-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 minutes 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": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "dataTypes": [ + "SalesforceServiceCloud" ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" + "connectorId": "SalesforceServiceCloud" + } + ], + "tactics": [ + "CredentialAccess" + ], + "techniques": [ + "T1110" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "ClientIp" + } ], - "label": "Primary Key" - }, - "type": "CopyableLabel" + "entityType": "IP" + } + ], + "customDetails": { + "Users": "Users" } - ] + } }, { - "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('analyticRuleObject2').analyticRuleId2,'/'))))]", + "properties": { + "description": "Salesforce Service Cloud Analytics Rule 2", + "parentId": "[variables('analyticRuleObject2').analyticRuleId2]", + "contentId": "[variables('analyticRuleObject2')._analyticRulecontentId2]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleObject2').analyticRuleVersion2]", + "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/" } - ] + } } - ], - "id": "[variables('_uiConfigId1')]", - "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution." - } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('analyticRuleObject2')._analyticRulecontentId2]", + "contentKind": "AnalyticsRule", + "displayName": "Potential Password Spray Attack", + "contentProductId": "[variables('analyticRuleObject2')._analyticRulecontentProductId2]", + "id": "[variables('analyticRuleObject2')._analyticRulecontentProductId2]", + "version": "[variables('analyticRuleObject2').analyticRuleVersion2]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('parserTemplateSpecName1')]", + "name": "[variables('analyticRuleObject3').analyticRuleTemplateSpecName3]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SalesforceServiceCloud Data Parser with template version 3.0.0", + "description": "Salesforce-SigninsMultipleCountries_AnalyticalRules Analytics Rule with template version 3.0.1", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('parserVersion1')]", + "contentVersion": "[variables('analyticRuleObject3').analyticRuleVersion3]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[variables('_parserName1')]", - "apiVersion": "2022-10-01", - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRuleObject3')._analyticRulecontentId3]", + "apiVersion": "2023-02-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "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": [ + "description": "This query searches for successful user logins from different countries within 30 mins.", + "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": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "" + "dataTypes": [ + "SalesforceServiceCloud" + ], + "connectorId": "SalesforceServiceCloud" + } + ], + "tactics": [ + "InitialAccess" + ], + "techniques": [ + "T1078" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "AadUserId", + "columnName": "User" + } + ], + "entityType": "Account" } ] } @@ -531,18 +372,16 @@ { "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('analyticRuleObject3').analyticRuleId3,'/'))))]", "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 3", + "parentId": "[variables('analyticRuleObject3').analyticRuleId3]", + "contentId": "[variables('analyticRuleObject3')._analyticRulecontentId3]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleObject3').analyticRuleVersion3]", "source": { - "name": "Salesforce Service Cloud", "kind": "Solution", + "name": "Salesforce Service Cloud", "sourceId": "[variables('_solutionId')]" }, "author": { @@ -564,108 +403,196 @@ "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.OperationalInsights/workspaces/savedSearches", - "apiVersion": "2022-10-01", - "name": "[variables('_parserName1')]", - "location": "[parameters('workspace-location')]", - "properties": { - "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.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/" - } + "contentId": "[variables('analyticRuleObject3')._analyticRulecontentId3]", + "contentKind": "AnalyticsRule", + "displayName": "User Sign in from different countries", + "contentProductId": "[variables('analyticRuleObject3')._analyticRulecontentProductId3]", + "id": "[variables('analyticRuleObject3')._analyticRulecontentProductId3]", + "version": "[variables('analyticRuleObject3').analyticRuleVersion3]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('workbookTemplateSpecName1')]", + "name": "[variables('dataConnectorTemplateSpecName1')]", "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", + "description": "Salesforce Service Cloud data connector with template version 3.0.1", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('workbookVersion1')]", + "contentVersion": "[variables('dataConnectorVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.Insights/workbooks", - "name": "[variables('workbookContentId1')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", "location": "[parameters('workspace-location')]", - "kind": "shared", - "apiVersion": "2021-08-01", - "metadata": { - "description": "Sets the time name for analysis." - }, + "kind": "GenericUI", "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\"}\n", - "version": "1.0", - "sourceId": "[variables('workspaceResourceId')]", - "category": "sentinel" + "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 + } + }, + { + "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://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('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "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')]", + "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", @@ -680,19 +607,6 @@ "email": "support@microsoft.com", "tier": "Microsoft", "link": "https://support.microsoft.com/" - }, - "dependencies": { - "operator": "AND", - "criteria": [ - { - "contentId": "SalesforceServiceCloud", - "kind": "DataType" - }, - { - "contentId": "SalesforceServiceCloud_CL", - "kind": "DataConnector" - } - ] } } } @@ -703,201 +617,253 @@ "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')]" + "contentId": "[variables('_dataConnectorContentId1')]", + "contentKind": "DataConnector", + "displayName": "Salesforce Service Cloud (using Azure Functions)", + "contentProductId": "[variables('_dataConnectorcontentProductId1')]", + "id": "[variables('_dataConnectorcontentProductId1')]", + "version": "[variables('dataConnectorVersion1')]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + "[variables('_dataConnectorId1')]" ], + "location": "[parameters('workspace-location')]", "properties": { - "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": [ + "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/" + } + } + }, + { + "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": { + "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('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" + "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." + }, + { + "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" ], - "connectorId": "SalesforceServiceCloud" - } - ], - "tactics": [ - "CredentialAccess" - ], - "techniques": [ - "T1110" - ], - "entityMappings": [ - { - "fieldMappings": [ + "label": "Workspace ID" + }, + "type": "CopyableLabel" + }, + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" + } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ { - "identifier": "FullName", - "columnName": "User" + "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" + } + ] } - ], - "entityType": "Account" - } - ], - "customDetails": { - "EventStartTime": "FailureStartTime", - "IPAddresses": "IpAddresses", - "EventEndTime": "SuccessEndTime" - } - } - }, - { - "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')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com/" + ] + }, + "type": "InstructionStepsGroup" } - } + ] } - ] - }, - "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')]" + ], + "id": "[variables('_uiConfigId1')]", + "additionalRequirementBanner": "These queries are dependent on a parser based on a Kusto Function deployed as part of the solution." + } } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName2')]", + "name": "[variables('parserObject1').parserTemplateSpecName1]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Salesforce-PasswordSpray_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SalesforceServiceCloud Data Parser with template version 3.0.1", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion2')]", + "contentVersion": "[variables('parserObject1').parserVersion1]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId2')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "name": "[variables('parserObject1')._parserName1]", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", "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": [ + "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": [ - { - "identifier": "Address", - "columnName": "ClientIp" - } - ], - "entityType": "IP" + "name": "description", + "value": "" } - ], - "customDetails": { - "Users": "Users" - } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('parserObject1')._parserId1,'/'))))]", + "dependsOn": [ + "[variables('parserObject1')._parserId1]" + ], "properties": { - "description": "Salesforce Service Cloud Analytics Rule 2", - "parentId": "[variables('analyticRuleId2')]", - "contentId": "[variables('_analyticRulecontentId2')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion2')]", + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), 'SalesforceServiceCloud')]", + "contentId": "[variables('parserObject1').parserContentId1]", + "kind": "Parser", + "version": "[variables('parserObject1').parserVersion1]", "source": { - "kind": "Solution", "name": "Salesforce Service Cloud", + "kind": "Solution", "sourceId": "[variables('_solutionId')]" }, "author": { @@ -919,86 +885,108 @@ "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')]" + "contentId": "[variables('parserObject1').parserContentId1]", + "contentKind": "Parser", + "displayName": "SalesforceServiceCloud", + "contentProductId": "[concat(take(variables('_solutionId'),50),'-','pr','-', uniqueString(concat(variables('_solutionId'),'-','Parser','-',variables('parserObject1').parserContentId1,'-', '1.0.0')))]", + "id": "[concat(take(variables('_solutionId'),50),'-','pr','-', uniqueString(concat(variables('_solutionId'),'-','Parser','-',variables('parserObject1').parserContentId1,'-', '1.0.0')))]", + "version": "[variables('parserObject1').parserVersion1]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2022-10-01", + "name": "[variables('parserObject1')._parserName1]", + "location": "[parameters('workspace-location')]", + "properties": { + "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.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "location": "[parameters('workspace-location')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('parserObject1')._parserId1,'/'))))]", + "dependsOn": [ + "[variables('parserObject1')._parserId1]" + ], + "properties": { + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), 'SalesforceServiceCloud')]", + "contentId": "[variables('parserObject1').parserContentId1]", + "kind": "Parser", + "version": "[variables('parserObject1').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('analyticRuleTemplateSpecName3')]", + "name": "[variables('workbookTemplateSpecName1')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Salesforce-SigninsMultipleCountries_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SalesforceServiceCloud Workbook with template version 3.0.1", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion3')]", + "contentVersion": "[variables('workbookVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId3')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.Insights/workbooks", + "name": "[variables('workbookContentId1')]", "location": "[parameters('workspace-location')]", + "kind": "shared", + "apiVersion": "2021-08-01", + "metadata": { + "description": "Sets the time name for analysis." + }, "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": [ - { - "fieldMappings": [ - { - "identifier": "AadUserId", - "columnName": "User" - } - ], - "entityType": "Account" - } - ] + "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" } }, { "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('Workbook-', last(split(variables('workbookId1'),'/'))))]", "properties": { - "description": "Salesforce Service Cloud Analytics Rule 3", - "parentId": "[variables('analyticRuleId3')]", - "contentId": "[variables('_analyticRulecontentId3')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion3')]", + "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", @@ -1013,6 +1001,19 @@ "email": "support@microsoft.com", "tier": "Microsoft", "link": "https://support.microsoft.com/" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "contentId": "SalesforceServiceCloud", + "kind": "DataType" + }, + { + "contentId": "SalesforceServiceCloud_CL", + "kind": "DataConnector" + } + ] } } } @@ -1023,12 +1024,12 @@ "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')]" + "contentId": "[variables('_workbookContentId1')]", + "contentKind": "Workbook", + "displayName": "[parameters('workbook1-name')]", + "contentProductId": "[variables('_workbookcontentProductId1')]", + "id": "[variables('_workbookcontentProductId1')]", + "version": "[variables('workbookVersion1')]" } }, { @@ -1036,12 +1037,12 @@ "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "3.0.0", + "version": "3.0.1", "kind": "Solution", "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", + "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• 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')]", @@ -1066,6 +1067,21 @@ "dependencies": { "operator": "AND", "criteria": [ + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRuleObject1')._analyticRulecontentId1]", + "version": "[variables('analyticRuleObject1').analyticRuleVersion1]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRuleObject2')._analyticRulecontentId2]", + "version": "[variables('analyticRuleObject2').analyticRuleVersion2]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRuleObject3')._analyticRulecontentId3]", + "version": "[variables('analyticRuleObject3').analyticRuleVersion3]" + }, { "kind": "DataConnector", "contentId": "[variables('_dataConnectorContentId1')]", @@ -1073,28 +1089,13 @@ }, { "kind": "Parser", - "contentId": "[variables('_parserContentId1')]", - "version": "[variables('parserVersion1')]" + "contentId": "[variables('parserObject1').parserContentId1]", + "version": "[variables('parserObject1').parserVersion1]" }, { "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/Package/testParameters.json b/Solutions/Salesforce Service Cloud/Package/testParameters.json new file mode 100644 index 00000000000..9b39a61620f --- /dev/null +++ b/Solutions/Salesforce Service Cloud/Package/testParameters.json @@ -0,0 +1,32 @@ +{ + "location": { + "type": "string", + "minLength": 1, + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Not used, but needed to pass arm-ttk test `Location-Should-Not-Be-Hardcoded`. We instead use the `workspace-location` which is derived from the LA workspace" + } + }, + "workspace-location": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "[concat('Region to deploy solution resources -- separate from location selection',parameters('location'))]" + } + }, + "workspace": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "Workspace name for Log Analytics where Microsoft Sentinel is setup" + } + }, + "workbook1-name": { + "type": "string", + "defaultValue": "Salesforce Service Cloud", + "minLength": 1, + "metadata": { + "description": "Name for the workbook" + } + } +} diff --git a/Solutions/Salesforce Service Cloud/ReleaseNotes.md b/Solutions/Salesforce Service Cloud/ReleaseNotes.md index 6c1f40e5e37..302ce60bf5d 100644 --- a/Solutions/Salesforce Service Cloud/ReleaseNotes.md +++ b/Solutions/Salesforce Service Cloud/ReleaseNotes.md @@ -1,4 +1,5 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | |-------------|--------------------------------|--------------------------------------------------------------------| +| 3.0.1 | 06-02-2025 | Updated timeframes for Salesforce cloud **Analytic rules** | | 3.0.0 | 05-09-2023 | Manual deployment instructions updated for **Data Connector** |