diff --git a/Solutions/Dragos/Analytic Rules/DragosNotifiction.yaml b/Solutions/Dragos/Analytic Rules/DragosNotifiction.yaml index 0198745ab8e..c309833f426 100644 --- a/Solutions/Dragos/Analytic Rules/DragosNotifiction.yaml +++ b/Solutions/Dragos/Analytic Rules/DragosNotifiction.yaml @@ -37,7 +37,7 @@ alertDetailsOverride: - alertProperty: ProductName value: AlertProductName customDetails: - DragosNotificationId: id + DragosIdentifier: id DragosSeverity: severity DragosDetectionQuads: detectionQuads DragosCreatedAt: createdAt @@ -60,6 +60,6 @@ incidentConfiguration: lookbackDuration: PT1H matchingMethod: Selected groupByCustomDetails: - - DragosNotificationId -version: 1.0.0 + - DragosIdentifier +version: 1.0.1 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Dragos/Package/3.0.0.zip b/Solutions/Dragos/Package/3.0.0.zip index 498ee7bfc50..0548619c22c 100644 Binary files a/Solutions/Dragos/Package/3.0.0.zip and b/Solutions/Dragos/Package/3.0.0.zip differ diff --git a/Solutions/Dragos/Package/mainTemplate.json b/Solutions/Dragos/Package/mainTemplate.json index f3c23494f63..7769ad5ed0d 100644 --- a/Solutions/Dragos/Package/mainTemplate.json +++ b/Solutions/Dragos/Package/mainTemplate.json @@ -48,7 +48,7 @@ "_email": "[variables('email')]", "_solutionName": "Dragos", "_solutionVersion": "3.0.0", - "solutionId": "dragosinc1734451815609.azure-sentinel-solution-dragos", + "solutionId": "dragosinc1734451815609.microsoft-sentinel-solution-dragos", "_solutionId": "[variables('solutionId')]", "parserObject1": { "_parserName1": "[concat(parameters('workspace'),'/','DragosNotificationsToSentinel')]", @@ -87,11 +87,11 @@ "dataCollectionEndpointId": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/dataCollectionEndpoints/',parameters('workspace'))]", "blanks": "[replace('b', 'b', '')]", "analyticRuleObject1": { - "analyticRuleVersion1": "1.0.0", + "analyticRuleVersion1": "1.0.1", "_analyticRulecontentId1": "9a74fe72-4c21-4ac5-80d9-37434e809721", "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', '9a74fe72-4c21-4ac5-80d9-37434e809721')]", "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring('9a74fe72-4c21-4ac5-80d9-37434e809721')))]", - "_analyticRulecontentProductId1": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-','9a74fe72-4c21-4ac5-80d9-37434e809721','-', '1.0.0')))]" + "_analyticRulecontentProductId1": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-','9a74fe72-4c21-4ac5-80d9-37434e809721','-', '1.0.1')))]" }, "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" }, @@ -122,7 +122,7 @@ "displayName": "Dragos Notifications Sentinel Incidents", "category": "Microsoft Sentinel Parser", "functionAlias": "DragosNotificationsToSentinel", - "query": "let existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosNotificationId[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nunion isfuzzy=true DragosPushNotificationsToSentinel, DragosPullNotificationsToSentinel\n | join kind=leftouter (existingIncidents) on id\n | where isempty(SystemAlertId)\n | sort by severity desc\n", + "query": "let existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosIdentifier[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nunion isfuzzy=true DragosPushNotificationsToSentinel, DragosPullNotificationsToSentinel\n | join kind=leftouter (existingIncidents) on id\n | where isempty(SystemAlertId)\n | sort by severity desc\n", "functionParameters": "", "version": 2, "tags": [ @@ -187,7 +187,7 @@ "displayName": "Dragos Notifications Sentinel Incidents", "category": "Microsoft Sentinel Parser", "functionAlias": "DragosNotificationsToSentinel", - "query": "let existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosNotificationId[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nunion isfuzzy=true DragosPushNotificationsToSentinel, DragosPullNotificationsToSentinel\n | join kind=leftouter (existingIncidents) on id\n | where isempty(SystemAlertId)\n | sort by severity desc\n", + "query": "let existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosIdentifier[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nunion isfuzzy=true DragosPushNotificationsToSentinel, DragosPullNotificationsToSentinel\n | join kind=leftouter (existingIncidents) on id\n | where isempty(SystemAlertId)\n | sort by severity desc\n", "functionParameters": "", "version": 2, "tags": [ @@ -254,7 +254,7 @@ "displayName": "Dragos Pull Notifications Sentinel Incidents", "category": "Microsoft Sentinel Parser", "functionAlias": "DragosPullNotificationsToSentinel", - "query": "let Addresses = DragosAlerts_CL\n| mv-expand asset=assets\n| mv-expand address=asset.addresses\n| extend SentinelEntities=case(address.type == \"IP\",\n bag_pack(\"Type\", \"IP\", \"Address\", address.value, \"AddressScope\", address.networkId),\n address.type == \"HOSTNAME\",\n bag_pack(\"Type\", \"Host\", \"HostName\", address.value),\n address.type == \"DOMAIN\",\n bag_pack(\"Type\", \"Host\", \"HostName\", split(address.value, '.')[0], \"DnsDomain\", strcat_array(array_slice(split(address.value, '.'), 1, -1), '.')),\n dynamic(null))\n| extend MacAddresses = case(address.type == 'MAC', address.value, '')\n| extend IpAddresses = case(address.type == \"IP\", address.value, '');\nlet MitreThreatInfo = DragosAlerts_CL\n| mv-expand threat=threatInfo\n| extend MitreTactics=case(threat.framework == \"MITRE ATT&CK FOR ICS\" and threat.tactic.name != \"N/A\", replace_string(tostring(threat.tactic.name), \" \", \"\"), '')\n| extend MitreTechniques=case(threat.framework == \"MITRE ATT&CK FOR ICS\", threat.technique.id, '');\nlet existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosNotificationId[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nDragosAlerts_CL\n| extend detectionQuads=strcat_array(detectionQuads, \",\")\n| extend threatInfo=strcat_array(threatInfo, \",\")\n| join kind=leftouter Addresses on id\n| join kind=leftouter MitreThreatInfo on id\n| extend notification_id = id\n| summarize SentinelEntities=make_list(SentinelEntities, 250), MacAddresses=make_list(MacAddresses, 250), IpAddresses=make_list(IpAddresses, 250), MitreTactics=make_set_if(MitreTactics, strlen(MitreTactics) > 0), MitreTechniques=make_set_if(MitreTechniques, strlen(MitreTechniques) > 0) by id=notification_id, source, summary, content, severity, detectionQuads, createdAt, firstSeenAt, lastSeenAt, occurredAt, state, threatInfo\n| extend MacAddresses = set_difference(MacAddresses,dynamic([\"\"]))\n| extend IpAddresses = set_difference(IpAddresses,dynamic([\"\"]))\n| extend MitreTactics=strcat_array(MitreTactics, \",\")\n| extend AlertProductName=\"Dragos\"\n| extend DragosConnectorSource=\"DragosCcp\"\n| extend MSSentinelSeverity = DragosSeverityToSentinelSeverity(severity)\n| join kind=leftouter (existingIncidents) on id\n| where isempty(SystemAlertId)\n| summarize arg_max(createdAt, *) by id\n", + "query": "let Addresses = DragosAlerts_CL\n| mv-expand asset=assets\n| mv-expand address=asset.addresses\n| extend SentinelEntities=case(address.type == \"IP\",\n bag_pack(\"Type\", \"IP\", \"Address\", address.value, \"AddressScope\", address.networkId),\n address.type == \"HOSTNAME\",\n bag_pack(\"Type\", \"Host\", \"HostName\", address.value),\n address.type == \"DOMAIN\",\n bag_pack(\"Type\", \"Host\", \"HostName\", split(address.value, '.')[0], \"DnsDomain\", strcat_array(array_slice(split(address.value, '.'), 1, -1), '.')),\n dynamic(null))\n| extend MacAddresses = case(address.type == 'MAC', address.value, '')\n| extend IpAddresses = case(address.type == \"IP\", address.value, '');\nlet MitreThreatInfo = DragosAlerts_CL\n| mv-expand threat=threatInfo\n| extend MitreTactics=case(threat.framework == \"MITRE ATT&CK FOR ICS\" and threat.tactic.name != \"N/A\", replace_string(tostring(threat.tactic.name), \" \", \"\"), '')\n| extend MitreTechniques=case(threat.framework == \"MITRE ATT&CK FOR ICS\", threat.technique.id, '');\nlet existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosIdentifier[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nDragosAlerts_CL\n| extend detectionQuads=strcat_array(detectionQuads, \",\")\n| extend threatInfo=strcat_array(threatInfo, \",\")\n| join kind=leftouter Addresses on id\n| join kind=leftouter MitreThreatInfo on id\n| extend notification_id = id\n| summarize SentinelEntities=make_list(SentinelEntities, 250), MacAddresses=make_list(MacAddresses, 250), IpAddresses=make_list(IpAddresses, 250), MitreTactics=make_set_if(MitreTactics, strlen(MitreTactics) > 0), MitreTechniques=make_set_if(MitreTechniques, strlen(MitreTechniques) > 0) by id=notification_id, source, summary, content, severity, detectionQuads, createdAt, firstSeenAt, lastSeenAt, occurredAt, state, threatInfo\n| extend MacAddresses = set_difference(MacAddresses,dynamic([\"\"]))\n| extend IpAddresses = set_difference(IpAddresses,dynamic([\"\"]))\n| extend MitreTactics=strcat_array(MitreTactics, \",\")\n| extend AlertProductName=\"Dragos\"\n| extend DragosConnectorSource=\"DragosCcp\"\n| extend MSSentinelSeverity = DragosSeverityToSentinelSeverity(severity)\n| join kind=leftouter (existingIncidents) on id\n| where isempty(SystemAlertId)\n| summarize arg_max(createdAt, *) by id\n", "functionParameters": "", "version": 2, "tags": [ @@ -319,7 +319,7 @@ "displayName": "Dragos Pull Notifications Sentinel Incidents", "category": "Microsoft Sentinel Parser", "functionAlias": "DragosPullNotificationsToSentinel", - "query": "let Addresses = DragosAlerts_CL\n| mv-expand asset=assets\n| mv-expand address=asset.addresses\n| extend SentinelEntities=case(address.type == \"IP\",\n bag_pack(\"Type\", \"IP\", \"Address\", address.value, \"AddressScope\", address.networkId),\n address.type == \"HOSTNAME\",\n bag_pack(\"Type\", \"Host\", \"HostName\", address.value),\n address.type == \"DOMAIN\",\n bag_pack(\"Type\", \"Host\", \"HostName\", split(address.value, '.')[0], \"DnsDomain\", strcat_array(array_slice(split(address.value, '.'), 1, -1), '.')),\n dynamic(null))\n| extend MacAddresses = case(address.type == 'MAC', address.value, '')\n| extend IpAddresses = case(address.type == \"IP\", address.value, '');\nlet MitreThreatInfo = DragosAlerts_CL\n| mv-expand threat=threatInfo\n| extend MitreTactics=case(threat.framework == \"MITRE ATT&CK FOR ICS\" and threat.tactic.name != \"N/A\", replace_string(tostring(threat.tactic.name), \" \", \"\"), '')\n| extend MitreTechniques=case(threat.framework == \"MITRE ATT&CK FOR ICS\", threat.technique.id, '');\nlet existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosNotificationId[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nDragosAlerts_CL\n| extend detectionQuads=strcat_array(detectionQuads, \",\")\n| extend threatInfo=strcat_array(threatInfo, \",\")\n| join kind=leftouter Addresses on id\n| join kind=leftouter MitreThreatInfo on id\n| extend notification_id = id\n| summarize SentinelEntities=make_list(SentinelEntities, 250), MacAddresses=make_list(MacAddresses, 250), IpAddresses=make_list(IpAddresses, 250), MitreTactics=make_set_if(MitreTactics, strlen(MitreTactics) > 0), MitreTechniques=make_set_if(MitreTechniques, strlen(MitreTechniques) > 0) by id=notification_id, source, summary, content, severity, detectionQuads, createdAt, firstSeenAt, lastSeenAt, occurredAt, state, threatInfo\n| extend MacAddresses = set_difference(MacAddresses,dynamic([\"\"]))\n| extend IpAddresses = set_difference(IpAddresses,dynamic([\"\"]))\n| extend MitreTactics=strcat_array(MitreTactics, \",\")\n| extend AlertProductName=\"Dragos\"\n| extend DragosConnectorSource=\"DragosCcp\"\n| extend MSSentinelSeverity = DragosSeverityToSentinelSeverity(severity)\n| join kind=leftouter (existingIncidents) on id\n| where isempty(SystemAlertId)\n| summarize arg_max(createdAt, *) by id\n", + "query": "let Addresses = DragosAlerts_CL\n| mv-expand asset=assets\n| mv-expand address=asset.addresses\n| extend SentinelEntities=case(address.type == \"IP\",\n bag_pack(\"Type\", \"IP\", \"Address\", address.value, \"AddressScope\", address.networkId),\n address.type == \"HOSTNAME\",\n bag_pack(\"Type\", \"Host\", \"HostName\", address.value),\n address.type == \"DOMAIN\",\n bag_pack(\"Type\", \"Host\", \"HostName\", split(address.value, '.')[0], \"DnsDomain\", strcat_array(array_slice(split(address.value, '.'), 1, -1), '.')),\n dynamic(null))\n| extend MacAddresses = case(address.type == 'MAC', address.value, '')\n| extend IpAddresses = case(address.type == \"IP\", address.value, '');\nlet MitreThreatInfo = DragosAlerts_CL\n| mv-expand threat=threatInfo\n| extend MitreTactics=case(threat.framework == \"MITRE ATT&CK FOR ICS\" and threat.tactic.name != \"N/A\", replace_string(tostring(threat.tactic.name), \" \", \"\"), '')\n| extend MitreTechniques=case(threat.framework == \"MITRE ATT&CK FOR ICS\", threat.technique.id, '');\nlet existingIncidents = SecurityAlert\n | where ProductName == \"Dragos\"\n | extend CustomDetails=tostring(parse_json(ExtendedProperties)[\"Custom Details\"])\n | extend id = toint(extract_json(\"$.DragosIdentifier[0]\", CustomDetails))\n | project-keep SystemAlertId, id;\nDragosAlerts_CL\n| extend detectionQuads=strcat_array(detectionQuads, \",\")\n| extend threatInfo=strcat_array(threatInfo, \",\")\n| join kind=leftouter Addresses on id\n| join kind=leftouter MitreThreatInfo on id\n| extend notification_id = id\n| summarize SentinelEntities=make_list(SentinelEntities, 250), MacAddresses=make_list(MacAddresses, 250), IpAddresses=make_list(IpAddresses, 250), MitreTactics=make_set_if(MitreTactics, strlen(MitreTactics) > 0), MitreTechniques=make_set_if(MitreTechniques, strlen(MitreTechniques) > 0) by id=notification_id, source, summary, content, severity, detectionQuads, createdAt, firstSeenAt, lastSeenAt, occurredAt, state, threatInfo\n| extend MacAddresses = set_difference(MacAddresses,dynamic([\"\"]))\n| extend IpAddresses = set_difference(IpAddresses,dynamic([\"\"]))\n| extend MitreTactics=strcat_array(MitreTactics, \",\")\n| extend AlertProductName=\"Dragos\"\n| extend DragosConnectorSource=\"DragosCcp\"\n| extend MSSentinelSeverity = DragosSeverityToSentinelSeverity(severity)\n| join kind=leftouter (existingIncidents) on id\n| where isempty(SystemAlertId)\n| summarize arg_max(createdAt, *) by id\n", "functionParameters": "", "version": 2, "tags": [ @@ -1256,12 +1256,12 @@ "username": { "defaultValue": "Enter username value", "type": "string", - "minLength": 1 + "minLength": 4 }, "password": { "defaultValue": "-NA-", "type": "securestring", - "minLength": 1 + "minLength": 4 }, "dragosSitestoreHostname": { "defaultValue": "Enter dragosSitestoreHostname value", @@ -1422,24 +1422,24 @@ "status": "Available", "requiredDataConnectors": [ { + "connectorId": "DragosSitestoreCCP", "dataTypes": [ "DragosAlerts_CL" - ], - "connectorId": "DragosSitestoreCCP" + ] }, { + "connectorId": "CefAma", "dataTypes": [ "CommonSecurityLog" - ], - "connectorId": "CefAma" + ] } ], "entityMappings": [ { "fieldMappings": [ { - "identifier": "Entities", - "columnName": "SentinelEntities" + "columnName": "SentinelEntities", + "identifier": "Entities" } ], "entityType": "SentinelEntities" @@ -1449,23 +1449,25 @@ "aggregationKind": "AlertPerResult" }, "customDetails": { - "DragosCreatedAt": "createdAt", - "DragosSeverity": "severity", - "DragosState": "state", - "DragosNotificationId": "id", "DragosSource": "source", "DragosIpAddresses": "IpAddresses", + "DragosCreatedAt": "createdAt", "DragosFirstSeenAt": "firstSeenAt", "DragosDetectionQuads": "detectionQuads", - "DragosOccurredAt": "occurredAt", "DragosMacAddresses": "MacAddresses", - "DragosLastSeenAt": "lastSeenAt", + "DragosConnectSrc": "DragosConnectorSource", + "DragosSeverity": "severity", + "DragosOccurredAt": "occurredAt", "DragosThreatInfo": "threatInfo", - "DragosConnectSrc": "DragosConnectorSource" + "DragosState": "state", + "DragosIdentifier": "id", + "DragosLastSeenAt": "lastSeenAt" }, "alertDetailsOverride": { - "alertTacticsColumnName": "MitreTactics", + "alertDisplayNameFormat": "Dragos: {{summary}}", + "alertSeverityColumnName": "MSSentinelSeverity", "alertDescriptionFormat": "{{content}}", + "alertTacticsColumnName": "MitreTactics", "alertDynamicProperties": [ { "value": "MitreTechniques", @@ -1475,20 +1477,18 @@ "value": "AlertProductName", "alertProperty": "ProductName" } - ], - "alertSeverityColumnName": "MSSentinelSeverity", - "alertDisplayNameFormat": "Dragos: {{summary}}" + ] }, "incidentConfiguration": { "createIncident": true, "groupingConfiguration": { "matchingMethod": "Selected", + "enabled": true, "lookbackDuration": "PT1H", - "groupByCustomDetails": [ - "DragosNotificationId" - ], "reopenClosedIncident": false, - "enabled": true + "groupByCustomDetails": [ + "DragosIdentifier" + ] } } } diff --git a/Solutions/Dragos/Parsers/DragosNotificationsToSentinel.yaml b/Solutions/Dragos/Parsers/DragosNotificationsToSentinel.yaml index e19701c93d1..0ad4e428120 100644 --- a/Solutions/Dragos/Parsers/DragosNotificationsToSentinel.yaml +++ b/Solutions/Dragos/Parsers/DragosNotificationsToSentinel.yaml @@ -10,7 +10,7 @@ FunctionQuery: | let existingIncidents = SecurityAlert | where ProductName == "Dragos" | extend CustomDetails=tostring(parse_json(ExtendedProperties)["Custom Details"]) - | extend id = toint(extract_json("$.DragosNotificationId[0]", CustomDetails)) + | extend id = toint(extract_json("$.DragosIdentifier[0]", CustomDetails)) | project-keep SystemAlertId, id; union isfuzzy=true DragosPushNotificationsToSentinel, DragosPullNotificationsToSentinel | join kind=leftouter (existingIncidents) on id diff --git a/Solutions/Dragos/Parsers/DragosPullNotificationsToSentinel.yaml b/Solutions/Dragos/Parsers/DragosPullNotificationsToSentinel.yaml index afc283da006..148ed7aba61 100644 --- a/Solutions/Dragos/Parsers/DragosPullNotificationsToSentinel.yaml +++ b/Solutions/Dragos/Parsers/DragosPullNotificationsToSentinel.yaml @@ -26,7 +26,7 @@ FunctionQuery: | let existingIncidents = SecurityAlert | where ProductName == "Dragos" | extend CustomDetails=tostring(parse_json(ExtendedProperties)["Custom Details"]) - | extend id = toint(extract_json("$.DragosNotificationId[0]", CustomDetails)) + | extend id = toint(extract_json("$.DragosIdentifier[0]", CustomDetails)) | project-keep SystemAlertId, id; DragosAlerts_CL | extend detectionQuads=strcat_array(detectionQuads, ",") diff --git a/Solutions/Dragos/SolutionMetadata.json b/Solutions/Dragos/SolutionMetadata.json index afc3a53dbbc..96c22c41279 100644 --- a/Solutions/Dragos/SolutionMetadata.json +++ b/Solutions/Dragos/SolutionMetadata.json @@ -1,6 +1,6 @@ { "publisherId": "dragosinc1734451815609", - "offerId": "azure-sentinel-solution-dragos", + "offerId": "microsoft-sentinel-solution-dragos", "firstPublishDate": "2025-01-23", "lastPublishDate": "2025-01-23", "providers": [