diff --git a/Playbooks/Advanced-SNOW-Teams-Integration/Media/animated.gif b/Playbooks/Advanced-SNOW-Teams-Integration/Media/animated.gif new file mode 100644 index 0000000000..252051f2b5 Binary files /dev/null and b/Playbooks/Advanced-SNOW-Teams-Integration/Media/animated.gif differ diff --git a/Playbooks/Advanced-SNOW-Teams-Integration/Media/teams.PNG b/Playbooks/Advanced-SNOW-Teams-Integration/Media/teams.PNG new file mode 100644 index 0000000000..afe50e1c5e Binary files /dev/null and b/Playbooks/Advanced-SNOW-Teams-Integration/Media/teams.PNG differ diff --git a/Playbooks/Advanced-SNOW-Teams-Integration/README.md b/Playbooks/Advanced-SNOW-Teams-Integration/README.md new file mode 100644 index 0000000000..bee55197e9 --- /dev/null +++ b/Playbooks/Advanced-SNOW-Teams-Integration/README.md @@ -0,0 +1,48 @@ +# Advanced - ServiceNow & Teams Integration +Author: Jing Nghik + +![Alt Text](./Media/animated.gif) + +This arm template will deploy multiple logic app playbooks and api connectors. +- (Main playbook) \-\ +- (playbook function) - \-GetPlaybooksbyTag +This playbooks purpose is to locate any playbooks that have been tagged with playbook to populate the Investigation Response list dynamically. +- (Check IP - Example playbook) - \-CheckIPonVirusTotal - Simple playbook to checkIPonVirusTotal. This playbook is an example that will be available in Azure Sentinel and the main playbook. +- All the API connectors are reused across the same playbook to prevent duplicate API connectors created. + +There are a number of pre-configuration steps required before deploying the Logic App. + +## Requirements +In order to fully utilize this playbook. You will need the following: +- ServiceNow instance URL, Username, and password +You can create a dev environment to test with for free at https://developer.servicenow.com/dev.do +- access/authorization to enable api connectors for Azure resource manager, teams, and azure sentinel. +- Teams Group ID, Alert Channel ID, Investigation Response Channel ID +The group ID and Channel ID can be obtained by going to Teams and getting the link which has the values you need for the parameters. (Will need to URL decode it if there are special characters) [URL Decoder Link](https://www.urldecoder.org/) +![Alt Text](./Media/teams.png) +-- Investigation Channel ID can also use the same ID as alert channel if desired. + +## Workflow +1. Based on the rules, Azure Sentinel triggers an incident or alert. +2. This runs a linked playbook that first will check if an existing serviceNow ticket already exists (to prevent duplicate tickets) +3. The ticket is opened is serviceNow and a Teams message is sent to the Alert channel with alert/incident details. +4. A corresponding investigation response message is sent with a list of available playbooks that can be run from teams. +5. Based on the input provided, the selected playbooks are ran ad-hoc and playbook results/response is attached to the same alert channel message thread. + +## Setup Steps +1. Click Deploy to Azure and fill in parameters +2. Search for API connectors and find the deployment prefix and fix any connectors by authorizing the connection. +3. Populate the Teams Group and Channel IDs to ensure it messages are generated in the right channel. +3. Manually trigger an azure sentinel alert to test. + +Thanks the following people for contributing to my efforts in building this playbook! +- Twitter@thijslecomte - For showing me how to make my first template! +- Jan Ignacio, Joey Cruz, Sreedhar Ande, Nicholas Dicola, Rod Trent, Nathan Swift + +## Deploy the ARM template + + + + + + \ No newline at end of file diff --git a/Playbooks/Advanced-SNOW-Teams-Integration/azuredeploy.json b/Playbooks/Advanced-SNOW-Teams-Integration/azuredeploy.json new file mode 100644 index 0000000000..c6080d0ba5 --- /dev/null +++ b/Playbooks/Advanced-SNOW-Teams-Integration/azuredeploy.json @@ -0,0 +1,1108 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "deploymentGroupName": { + "defaultValue": "playbook", + "type": "String", + "metadata": { + "description": "This name will be prefixed on all the resources" + } + }, + "playbookName": { + "defaultValue": "ServiceNow-Teams-Integration", + "type": "String", + "metadata": { + "description": "Name of the primary playbook that will be called from Azure Sentinel" + } + }, + "MSUserName": { + "defaultValue": "", + "type": "String", + "metadata": { + "description": "Username with authority API connectors (Teams, ARM, and Sentinel)." + } + }, + "Snow_Instance": { + "defaultValue": "https://..com", + "type": "String", + "metadata": { + "description": "Can be found with .service-now.com or https://..com for migrated account" + } + }, + "Snow_Username": { + "defaultValue": "", + "type": "String" + }, + "Snow_Password": { + "defaultValue": "", + "type": "securestring" + }, + "TeamsGroupId": { + "defaultValue": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx", + "type": "String", + "metadata": { + "description": "The Teams Group ID where the channel is located." + } + }, + "AlertChannelId": { + "defaultValue": "xx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@thread.skype", + "type": "String", + "metadata": { + "description": "The particular Teams channel ID where the alert should go" + } + }, + "InvestigationChannelId": { + "defaultValue": "xx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@thread.skype", + "type": "String", + "metadata": { + "description": "The particular Teams channel ID where the Investigation Playbook options should go." + } + }, + "VirusTotalAPIKey": { + "type": "securestring", + "defaultValue": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "type": "String", + "metadata": { + "description": "Virus Total API Key. https://developers.virustotal.com/v3.0/reference#overview" + } + } + }, + "variables": { + "AzureSentinelConnectionName": "[concat(parameters('deploymentGroupName'),'-apiconnector-azuresentinel')]", + "ARMConnectionName": "[concat(parameters('deploymentGroupName'),'-apiconnector-arm')]", + "TeamsConnectionName": "[concat(parameters('deploymentGroupName'),'-apiconnector-teams')]", + "SNOWConnectionName": "[concat(parameters('deploymentGroupName'),'-apiconnector-snow')]", + "VirusTotalConnectionName": "[concat(parameters('deploymentGroupName'),'-apiconnector-virusTotal')]" + }, + "resources": [ + { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[variables('AzureSentinelConnectionName')]", + "location": "[resourceGroup().location]", + "properties": { + "displayName": "[parameters('MSUserName')]", + "customParameterValues": {}, + "api": { + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/azuresentinel')]" + } + } + }, + { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[variables('TeamsConnectionName')]", + "location": "[resourceGroup().location]", + "kind": "V1", + "properties": { + "displayName": "[parameters('MSUserName')]", + "customParameterValues": {}, + "api": { + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/teams')]" + } + } + }, + { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[variables('SNOWConnectionName')]", + "location": "[resourceGroup().location]", + "properties": { + "displayName": "[parameters('Snow_Username')]", + "customParameterValues": {}, + "api": { + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/service-now')]" + }, + "parameterValues" : { + "instance" : "[parameters('Snow_Instance')]", + "username" : "[parameters('Snow_Username')]", + "password" : "[parameters('Snow_Password')]" + } + } + }, + { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[variables('ARMConnectionName')]", + "location": "[resourceGroup().location]", + "properties": { + "displayName": "[parameters('MSUserName')]", + "customParameterValues": {}, + "api": { + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/arm')]" + } + } + }, + { + "type": "Microsoft.Web/connections", + "apiVersion": "2018-07-01-preview", + "location": "[resourceGroup().location]", + "name": "[variables('VirusTotalConnectionName')]", + "properties": { + "api": { + "id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/virustotal')]" + }, + "displayName": "[variables('VirusTotalConnectionName')]", + "customParameterValues": { + "x-api_key" : "[parameters('VirusTotalApiKey')]" + }, + "parameterValues": { + "api_key" : "[parameters('VirusTotalApiKey')]" + } + } + }, + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2017-07-01", + "name": "[concat(parameters('deploymentGroupName'),'-workflow-',parameters('playbookName'))]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[resourceId('Microsoft.Web/connections', variables('AzureSentinelConnectionName'))]", + "[resourceId('Microsoft.Web/connections', variables('SNOWConnectionName'))]", + "[resourceId('Microsoft.Web/connections', variables('TeamsConnectionName'))]", + "[resourceId('Microsoft.Web/connections', variables('ARMConnectionName'))]", + "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Logic/workflows/',parameters('deploymentGroupName'),'-function-getListOfTaggedPlaybooks')]" + ], + "tags": { + "LogicAppsCategory": "security" + }, + "properties": { + "state": "Enabled", + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "defaultValue": {}, + "type": "Object" + }, + "AlertChannelId": { + "defaultValue": "[parameters('AlertChannelId')]", + "type": "String" + }, + "InvestigationChannelId": { + "defaultValue": "[parameters('InvestigationChannelId')]", + "type": "String" + }, + "TeamsGroupId": { + "defaultValue": "[parameters('TeamsGroupId')]", + "type": "String" + } + }, + "triggers": { + "When_a_response_to_an_Azure_Sentinel_alert_is_triggered": { + "type": "ApiConnectionWebhook", + "inputs": { + "body": { + "callback_url": "@{listCallbackUrl()}" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "path": "/subscribe" + } + } + }, + "actions": { + "Check_to_see_if_ServiceNow_Incident_exists": { + "actions": { + "Set_the_ServiceNow_Variable_of_existing_Record": { + "runAfter": {}, + "type": "SetVariable", + "inputs": { + "name": "ServiceNowSystemID", + "value": "@{body('ServiceNow_-_Query_for_Sentinel_Incident_Number')?['result'][0]?['sys_id']}" + } + } + }, + "runAfter": { + "ServiceNow_-_Query_for_Sentinel_Incident_Number": [ + "Succeeded" + ] + }, + "else": { + "actions": { + "ServiceNow_-_Create_Record_for_Incident": { + "runAfter": {}, + "type": "ApiConnection", + "inputs": { + "body": { + "short_description": "@{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentNumber']} - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['title']}", + "sys_tags": "Azure Sentinel" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['service-now']['connectionId']" + } + }, + "method": "post", + "path": "/api/now/v2/table/@{encodeURIComponent('incident')}", + "queries": { + "sysparm_display_value": false, + "sysparm_exclude_reference_link": true + } + } + }, + "Set_the_ServiceNow_Variable_of_Created_Record": { + "runAfter": { + "ServiceNow_-_Create_Record_for_Incident": [ + "Succeeded" + ] + }, + "type": "SetVariable", + "inputs": { + "name": "ServiceNowSystemID", + "value": "@body('ServiceNow_-_Create_Record_for_Incident')?['result']?['sys_id']" + } + } + } + }, + "expression": { + "and": [ + { + "greater": [ + "@length(body('ServiceNow_-_Query_for_Sentinel_Incident_Number')?['result'])", + 0 + ] + } + ] + }, + "type": "If" + }, + "Extract_Entities": { + "actions": { + "Compose": { + "runAfter": { + "Get_Users": [ + "Succeeded" + ] + }, + "type": "Compose", + "inputs": { + "test": "cool" + } + }, + "For_each_account_entity": { + "foreach": "@body('Get_Users')?['Accounts']", + "actions": { + "Add_to_accounts_string_variable": { + "runAfter": {}, + "type": "AppendToStringVariable", + "inputs": { + "name": "entitiesAccounts", + "value": "@{items('For_each_account_entity')?['Name']}; " + } + } + }, + "runAfter": { + "Compose": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "For_each_host": { + "foreach": "@body('Get_Hosts')?['Hosts']", + "actions": { + "Append_host_to_string_variable": { + "runAfter": {}, + "type": "AppendToStringVariable", + "inputs": { + "name": "entitiesHosts", + "value": "@{items('For_each_host')?['HostName']}; " + } + } + }, + "runAfter": { + "Get_Hosts": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "Get_Hosts": { + "runAfter": { + "For_each_account_entity": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": "@triggerBody()?['Entities']", + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "method": "post", + "path": "/entities/host" + } + }, + "Get_Users": { + "runAfter": {}, + "type": "ApiConnection", + "inputs": { + "body": "@triggerBody()?['Entities']", + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "method": "post", + "path": "/entities/account" + } + }, + "Get_the_alert_entity_types": { + "runAfter": { + "For_each_host": [ + "Succeeded" + ] + }, + "type": "Select", + "inputs": { + "from": "@triggerBody()?['Entities']", + "select": { + "type": "@item()?['Type']" + } + } + }, + "LogicApp_-_Get_tagged_playbooks": { + "runAfter": { + "Get_the_alert_entity_types": [ + "Succeeded" + ] + }, + "type": "Workflow", + "inputs": { + "host": { + "triggerName": "manual", + "workflow": { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Logic/workflows/',parameters('deploymentGroupName'),'-function-getListOfTaggedPlaybooks')]" + } + } + }, + "description": "Gets any playbooks that are tagged with the key 'playbook' and values of (ip, user, device)" + } + }, + "runAfter": { + "Variable_-_ServiceNow_Incident_Number": [ + "Succeeded" + ] + }, + "type": "Scope" + }, + "Grab_selected_playbooks_from_Investigation_Response": { + "runAfter": { + "ServiceNow_-_Update_Record_with_Response_from_User": [ + "Succeeded" + ] + }, + "type": "SetVariable", + "inputs": { + "name": "playbooks", + "value": "@split(body('Post_Actions_Required_in_Investigation_Requests_Channel')?['data']?['playbooks'],',')" + } + }, + "Incident_-_Get_alerts_parent_incident": { + "runAfter": { + "Extract_Entities": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "method": "get", + "path": "/Incidents/subscriptions/@{encodeURIComponent(triggerBody()?['WorkspaceSubscriptionId'])}/resourceGroups/@{encodeURIComponent(triggerBody()?['WorkspaceResourceGroup'])}/workspaces/@{encodeURIComponent(triggerBody()?['WorkspaceId'])}/alerts/@{encodeURIComponent(triggerBody()?['SystemAlertId'])}" + } + }, + "Initialize_Playbook_Variable": { + "runAfter": { + "Variable_-_Hosts": [ + "Succeeded" + ] + }, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "playbooks", + "type": "array" + } + ] + } + }, + "Loop_through_each_playbook_and_run_it": { + "foreach": "@variables('playbooks')", + "actions": { + "Azure_Sentinel_-_Add_comment_to_related_Incident": { + "runAfter": { + "ServiceNow_-_Add_additional_comments_in_ServiceNow_Ticket": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "incidentArmId": "@body('Incident_-_Get_alerts_parent_incident')?['id']", + "message": "

Playbook (@{items('Loop_through_each_playbook_and_run_it')}) executed with the following response.
\n
\n@{body('Call_the_playbook_and_pass_alert_to_playbook')}

" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "method": "post", + "path": "/Incidents/Comment" + } + }, + "Call_the_playbook_and_pass_alert_to_playbook": { + "runAfter": { + "Find_playbook_based_on_playbook_name_provided": [ + "Succeeded" + ] + }, + "type": "Http", + "inputs": { + "body": "@triggerBody()", + "method": "POST", + "uri": "@{body('Find_playbook_based_on_playbook_name_provided')[0]?['callbackUrl']}" + } + }, + "Find_playbook_based_on_playbook_name_provided": { + "runAfter": {}, + "type": "Query", + "inputs": { + "from": "@array(body('LogicApp_-_Get_tagged_playbooks'))", + "where": "@equals(item()?['name'], items('Loop_through_each_playbook_and_run_it'))" + } + }, + "ServiceNow_-_Add_additional_comments_in_ServiceNow_Ticket": { + "runAfter": { + "Teams_-_Reply_to_Alert_Thread": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "comments": "Playbook (@{items('Loop_through_each_playbook_and_run_it')}) executed with the following response.\n@{body('Call_the_playbook_and_pass_alert_to_playbook')}\n" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['service-now']['connectionId']" + } + }, + "method": "put", + "path": "/api/now/v2/table/@{encodeURIComponent('incident')}/@{encodeURIComponent(variables('ServiceNowSystemID'))}", + "queries": { + "sysparm_display_value": false, + "sysparm_exclude_reference_link": true + } + } + }, + "Teams_-_Reply_to_Alert_Thread": { + "runAfter": { + "Call_the_playbook_and_pass_alert_to_playbook": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "body": { + "content": "

Playbook (@{items('Loop_through_each_playbook_and_run_it')}) executed with the following response.
\n
\n@{body('Call_the_playbook_and_pass_alert_to_playbook')}

", + "contentType": "html" + } + }, + "host": { + "connection": { + "name": "@parameters('$connections')['teams']['connectionId']" + } + }, + "method": "post", + "path": "/v2/beta/teams/@{encodeURIComponent(parameters('TeamsGroupId'))}/channels/@{encodeURIComponent(parameters('AlertChannelId'))}/messages/@{encodeURIComponent(body('Post_Incident_in_SOC_Alerts_Channel')?['id'])}/replies" + } + } + }, + "runAfter": { + "Grab_selected_playbooks_from_Investigation_Response": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "Post_Actions_Required_in_Investigation_Requests_Channel": { + "runAfter": { + "Post_Incident_in_SOC_Alerts_Channel": [ + "Succeeded" + ] + }, + "type": "ApiConnectionWebhook", + "inputs": { + "body": { + "body": { + "messageBody": "{\n \"msTeams\": {\n \"width\": \"full\"\n },\n \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",\n \"type\": \"AdaptiveCard\",\n \"version\": \"1.2\",\n \"body\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\t\t\"size\": \"large\",\n\t\t\t\t\t\t\"color\": \"accent\",\n\t\t\t\t\t\t\"text\": \"**Azure Sentinel Alert - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentNumber']}** - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['title']}\",\n\t\t\t\t\t\t\"wrap\": true\n\t\t\t\t\t},\n {\n \"type\": \"TextBlock\",\n \"text\": \"Please Select the playbooks to run for the incident:\",\n \"weight\": \"Bolder\"\n },\n {\n \"type\": \"TextBlock\",\n \"text\": \"Available tagged Logic App playbooks\",\n \"wrap\": true,\n \"weight\": \"Bolder\",\n \"color\": \"Accent\"\n },\n {\n \"type\": \"Input.ChoiceSet\",\n \"choices\": @{body('LogicApp_-_Get_tagged_playbooks')},\n \"placeholder\": \"IP Playbooks\",\n \"isMultiSelect\": true,\n \"style\": \"expanded\",\n \"id\": \"playbooks\"\n }\n ],\n \"actions\": [\n {\n \"type\": \"Action.Submit\",\n \"title\": \"Submit\"\n }\n ]\n}", + "recipient": { + "channelId": "[parameters('InvestigationChannelId')]" + }, + "shouldUpdateCard": true, + "updateMessage": "Azure Sentinel Incident - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentNumber']} \n@{body('Incident_-_Get_alerts_parent_incident')?['properties']?['title']}" + }, + "notificationUrl": "@{listCallbackUrl()}" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['teams']['connectionId']" + } + }, + "path": "/flowbot/actions/flowcontinuation/recipienttypes/channel/$subscriptions", + "queries": { + "groupId": "[parameters('TeamsGroupId')]" + } + } + }, + "Post_Incident_in_SOC_Alerts_Channel": { + "runAfter": { + "Check_to_see_if_ServiceNow_Incident_exists": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "messageBody": "{\n \"msTeams\": {\n \"width\": \"full\"\n },\n \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",\n \"type\": \"AdaptiveCard\",\n \"version\": \"1.2\",\n \"body\": [\n\t\t{\n\t\t\t\"type\": \"TextBlock\",\n\t\t\t\"size\": \"large\",\n\t\t\t\"color\": \"accent\",\n\t\t\t\"text\": \"Azure Sentinel Alert - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentNumber']} - @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['title']} \",\n\t\t\t\"wrap\": true\n\t\t},\n\t{\n\t\t\"type\": \"Container\",\n\t\t\"spacing\": \"padding\",\n\t\t\"style\": \"default\",\n\t\t\"items\": [\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"text\": \"**Owner: \"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"spacing\": \"none\",\n\t\t\t\t\"text\": \"**Date:** @{triggerBody()?['TimeGenerated']}\",\n\t\t\t\t\"wrap\": true\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"spacing\" : \"none\",\n\t\t\t\t\"text\": \"**ServiceNow ID#:** @{variables('ServiceNowSystemID')}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"spacing\" : \"none\",\n\t\t\t\t\"text\": \"**Incident Status:** @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['status']}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"spacing\" : \"none\",\n\t\t\t\t\"text\": \"**Incident Severity:** @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['severity']}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"wrap\": true,\n\t\t\t\t\"text\": \"**Description:** @{body('Incident_-_Get_alerts_parent_incident')?['properties']?['description']}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"wrap\": true,\n\t\t\t\t\"text\": \"**User(s) affected:** @{variables('entitiesAccounts')}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"TextBlock\",\n\t\t\t\t\"wrap\": true,\n\t\t\t\t\"text\": \"**Host(s) affected:** @{variables('entitiesHosts')}\"\n\t\t\t}\n\t\t]\n\t}\n ],\n \"actions\": [\n {\n \"type\": \"Action.OpenUrl\",\n \"title\": \"Open Incident in Sentinel\",\n \"url\": \"@{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentUrl']}\"\n },\n {\n \"type\": \"Action.OpenUrl\",\n \"title\": \"Open Service Now Incident\",\n \"url\": \"https://ven03842.service-now.com/nav_to.do?uri=/incident_list.do?sysparm_query=active=true\",\n \"style\" : \"destructive\"\n }\n ]\n}", + "recipient": { + "channelId": "[parameters('AlertChannelId')]", + "groupId": "[parameters('TeamsGroupId')]" + } + }, + "host": { + "connection": { + "name": "@parameters('$connections')['teams']['connectionId']" + } + }, + "method": "post", + "path": "/v1.0/teams/conversation/adaptivecard/poster/@{encodeURIComponent('User')}/location/@{encodeURIComponent('Channel')}" + } + }, + "ServiceNow_-_Query_for_Sentinel_Incident_Number": { + "runAfter": { + "Incident_-_Get_alerts_parent_incident": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['service-now']['connectionId']" + } + }, + "method": "get", + "path": "/api/now/v2/table/@{encodeURIComponent('incident')}", + "queries": { + "sysparm_display_value": false, + "sysparm_exclude_reference_link": true, + "sysparm_query": "123TEXTQUERY321=@{body('Incident_-_Get_alerts_parent_incident')?['properties']?['incidentNumber']}^active=true" + } + } + }, + "ServiceNow_-_Update_Record_with_Response_from_User": { + "runAfter": { + "Update_Incident_Thread_from_Investigation_Response": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "comments": "\n@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['responder']?['displayName']} <@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['responder']?['userPrincipalName']}> has ran the following playbooks:\n@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['data']?['playbooks']}" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['service-now']['connectionId']" + } + }, + "method": "put", + "path": "/api/now/v2/table/@{encodeURIComponent('incident')}/@{encodeURIComponent(variables('ServiceNowSystemID'))}", + "queries": { + "sysparm_display_value": false, + "sysparm_exclude_reference_link": true + } + } + }, + "Update_Incident_Thread_from_Investigation_Response": { + "runAfter": { + "Post_Actions_Required_in_Investigation_Requests_Channel": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "body": { + "body": { + "content": "


\n
@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['responder']?['displayName']} <@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['responder']?['userPrincipalName']}> has ran the following playbooks:
\n@{body('Post_Actions_Required_in_Investigation_Requests_Channel')?['data']?['playbooks']}

", + "contentType": "html" + } + }, + "host": { + "connection": { + "name": "@parameters('$connections')['teams']['connectionId']" + } + }, + "method": "post", + "path": "/v2/beta/teams/@{encodeURIComponent(parameters('TeamsGroupId'))}/channels/@{encodeURIComponent(parameters('AlertChannelId'))}/messages/@{encodeURIComponent(body('Post_Incident_in_SOC_Alerts_Channel')?['id'])}/replies" + } + }, + "Variable_-_Accounts": { + "runAfter": {}, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "entitiesAccounts", + "type": "string" + } + ] + } + }, + "Variable_-_Hosts": { + "runAfter": { + "Variable_-_Accounts": [ + "Succeeded" + ] + }, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "entitiesHosts", + "type": "string" + } + ] + } + }, + "Variable_-_ServiceNow_Incident_Number": { + "runAfter": { + "Initialize_Playbook_Variable": [ + "Succeeded" + ] + }, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "ServiceNowSystemID", + "type": "string" + } + ] + } + } + }, + "outputs": {} + }, + "parameters": { + "$connections": { + "value": { + "azuresentinel": { + "connectionId": "[resourceId('Microsoft.Web/connections', variables('AzureSentinelConnectionName'))]", + "connectionName": "[variables('AzureSentinelConnectionName')]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/azuresentinel')]" + }, + "service-now": { + "connectionId": "[resourceId('Microsoft.Web/connections', variables('SNOWConnectionName'))]", + "connectionName": "[variables('SNOWConnectionName')]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/service-now')]" + }, + "teams": { + "connectionId": "[resourceId('Microsoft.Web/connections', variables('TeamsConnectionName'))]", + "connectionName": "[variables('TeamsConnectionName')]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/teams')]" + } + } + }, + "AlertChannelId": { + "value" : "[parameters('AlertChannelId')]" + }, + "TeamsGroupId": { + "value" : "[parameters('TeamsGroupId')]" + } + } + } + }, + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2017-07-01", + "name": "[concat(parameters('deploymentGroupName'),'-function-getListOfTaggedPlaybooks')]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[resourceId('Microsoft.Web/connections', variables('AzureSentinelConnectionName'))]", + "[resourceId('Microsoft.Web/connections', variables('ARMConnectionName'))]" + ], + "properties": { + "state": "Enabled", + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "defaultValue": {}, + "type": "Object" + } + }, + "triggers": { + "manual": { + "type": "Request", + "kind": "Http", + "inputs": { + "schema": { + "properties": { + "tagName": { + "type": "string" + }, + "tagValue": { + "type": "string" + } + }, + "type": "object" + } + }, + "description": "This playbook receives an request to get a list of resources that match the playbook tag value and responds with JSON content" + } + }, + "actions": { + "Compose": { + "runAfter": { + "For_each_subscription": [ + "Succeeded" + ] + }, + "type": "Compose", + "inputs": "@variables('playbooks')" + }, + "For_each_subscription": { + "foreach": "@body('List_subscriptions')?['value']", + "actions": { + "For_each_playbook": { + "foreach": "@body('List_resources_by_subscription')?['value']", + "actions": { + "Append_to_array_variable": { + "runAfter": { + "Compose_new_object_including_callback_URL": [ + "Succeeded" + ] + }, + "type": "AppendToArrayVariable", + "inputs": { + "name": "playbooks", + "value": "@outputs('Compose_new_object_including_callback_URL')" + } + }, + "Compose_new_object_including_callback_URL": { + "runAfter": { + "Get_playbook_callback_URL": [ + "Succeeded" + ] + }, + "type": "Compose", + "inputs": { + "callbackUrl": "@{body('Get_playbook_callback_URL')?['value']}", + "id": "@{body('Read_a_resource')?['id']}", + "name": "@{body('Read_a_resource')?['name']}", + "resourceGroup": "@{outputs('split_the_resource_ID')[4]}", + "subscription": "@{outputs('split_the_resource_ID')[2]}", + "tags": "@{body('Read_a_resource')?['tags']}", + "title": "@{items('For_each_playbook')?['name']}", + "trigger": "@{split(body('Get_playbook_callback_URL')?['value'], '/')[6]}", + "type": "@{items('For_each_playbook')?['type']}", + "value": "@{items('For_each_playbook')?['name']}" + } + }, + "Get_playbook_callback_URL": { + "runAfter": { + "Read_a_resource": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['arm']['connectionId']" + } + }, + "method": "post", + "path": "/subscriptions/@{encodeURIComponent(outputs('split_the_resource_ID')[2])}/resourcegroups/@{encodeURIComponent(outputs('split_the_resource_ID')[4])}/providers/@{encodeURIComponent('Microsoft.Logic')}/@{encodeURIComponent('workflows/',outputs('split_the_resource_ID')[8])}/@{encodeURIComponent('triggers/',if(contains(body('Read_a_resource')?['properties']?['definition']?['triggers'],'When_a_response_to_an_Azure_Sentinel_alert_is_triggered'),'When_a_response_to_an_Azure_Sentinel_alert_is_triggered','manual'),'/listCallbackUrl')}", + "queries": { + "x-ms-api-version": "2016-06-01" + } + } + }, + "Read_a_resource": { + "runAfter": { + "split_the_resource_ID": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['arm']['connectionId']" + } + }, + "method": "get", + "path": "/subscriptions/@{encodeURIComponent(outputs('split_the_resource_ID')[2])}/resourcegroups/@{encodeURIComponent(outputs('split_the_resource_ID')[4])}/providers/@{encodeURIComponent('Microsoft.Logic')}/@{encodeURIComponent('workflows/',outputs('split_the_resource_ID')[8])}", + "queries": { + "x-ms-api-version": "2016-06-01" + } + } + }, + "split_the_resource_ID": { + "runAfter": {}, + "type": "Compose", + "inputs": "@split(items('For_each_playbook')?['id'],'/')" + } + }, + "runAfter": { + "List_resources_by_subscription": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "List_resources_by_subscription": { + "runAfter": {}, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['arm']['connectionId']" + } + }, + "method": "get", + "path": "/subscriptions/@{encodeURIComponent(item()?['subscriptionId'])}/resources", + "queries": { + "$filter": "tagName eq 'playbook'", + "x-ms-api-version": "2016-06-01" + } + } + } + }, + "runAfter": { + "List_subscriptions": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "List_subscriptions": { + "runAfter": { + "Variable_-_playbooks": [ + "Succeeded" + ] + }, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['arm']['connectionId']" + } + }, + "method": "get", + "path": "/subscriptions", + "queries": { + "x-ms-api-version": "2016-06-01" + } + } + }, + "Response": { + "runAfter": { + "Compose": [ + "Succeeded" + ] + }, + "type": "Response", + "kind": "Http", + "inputs": { + "body": "@variables('playbooks')", + "statusCode": 200 + } + }, + "Variable_-_playbooks": { + "runAfter": {}, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "playbooks", + "type": "array" + } + ] + } + } + }, + "outputs": {} + }, + "parameters": { + "$connections": { + "value": { + "arm": { + "connectionId": "[resourceId('Microsoft.Web/connections', variables('ARMConnectionName'))]", + "connectionName": "[variables('ARMConnectionName')]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/arm')]" + }, + "azuresentinel": { + "connectionId": "[resourceId('Microsoft.Web/connections', variables('AzureSentinelConnectionName'))]", + "connectionName": "[variables('AzureSentinelConnectionName')]", + "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/azuresentinel')]" + } + } + } + } + } + }, + + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2017-07-01", + "name": "[concat(parameters('deploymentGroupName'),'-ip-checkIPOnVirusTotal')]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[resourceId('Microsoft.Web/connections', variables('VirusTotalConnectionName'))]" + ], + "tags": { + "playbook": "ip" + }, + "properties": { + "state": "Enabled", + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "defaultValue": {}, + "type": "Object" + } + }, + "triggers": { + "When_a_response_to_an_Azure_Sentinel_alert_is_triggered": { + "type": "ApiConnectionWebhook", + "inputs": { + "body": { + "callback_url": "@{listCallbackUrl()}" + }, + "host": { + "connection": { + "name": "@parameters('$connections')['azuresentinel']['connectionId']" + } + }, + "path": "/subscribe" + } + } + }, + "actions": { + "Filter_for_IP_Entities": { + "runAfter": { + "Initialize_variable": [ + "Succeeded" + ] + }, + "type": "Query", + "inputs": { + "from": "@triggerBody()?['Entities']", + "where": "@equals(item()?['Type'], 'ip')" + } + }, + "For_each": { + "foreach": "@body('Filter_for_IP_Entities')", + "actions": { + "Append_to_string_variable": { + "runAfter": { + "Get_an_IP_report": [ + "Succeeded" + ] + }, + "type": "AppendToStringVariable", + "inputs": { + "name": "responseMessage", + "value": "Virus Total scanned IP @{items('For_each')?['Address']} and came back @{body('Get_an_IP_report')?['data']?['attributes']?['total_votes']}
" + } + }, + "Get_an_IP_report": { + "runAfter": {}, + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "name": "@parameters('$connections')['virustotal']['connectionId']" + } + }, + "method": "get", + "path": "/api/v3/ip_addresses/@{encodeURIComponent(items('For_each')?['Address'])}" + } + } + }, + "runAfter": { + "Filter_for_IP_Entities": [ + "Succeeded" + ] + }, + "type": "Foreach" + }, + "Initialize_variable": { + "runAfter": {}, + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "responseMessage", + "type": "string" + } + ] + } + }, + "Response": { + "runAfter": { + "For_each": [ + "Succeeded" + ] + }, + "type": "Response", + "kind": "Http", + "inputs": { + "body": "@variables('responseMessage')", + "statusCode": 200 + } + } + }, + "outputs": {} + }, + "parameters": { + "$connections": { + "value": { + "azuresentinel": { + "id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/azuresentinel')]", + "connectionName": "[variables('VirusTotalConnectionName')]", + "connectionId": "[resourceId('Microsoft.Web/connections', variables('VirusTotalConnectionName'))]" + }, + "virustotal": { + "id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/virustotal')]", + "connectionName": "[variables('VirusTotalConnectionName')]", + "connectionId": "[resourceId('Microsoft.Web/connections', variables('VirusTotalConnectionName'))]" + } + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/Playbooks/Advanced-SNOW-Teams-Integration/parametersFile.json b/Playbooks/Advanced-SNOW-Teams-Integration/parametersFile.json new file mode 100644 index 0000000000..42f6c47d3a --- /dev/null +++ b/Playbooks/Advanced-SNOW-Teams-Integration/parametersFile.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "deploymentGroupName": { + "value": "playbook" + }, + "playbookName": { + "value": "ServiceNow-Teams-Integration" + }, + "MSUserName": { + "value": "" + }, + "Snow_Instance": { + "value": "https://..com" + }, + "Snow_Username": { + "value": "" + }, + "Snow_Password": { + "value": "" + }, + "TeamsGroupId": { + "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx" + }, + "AlertChannelId": { + "value": "xx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@thread.skype" + }, + "InvestigationChannelId": { + "value": "xx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@thread.skype" + }, + "VirusTotalAPIKey": { + "value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } + } +} \ No newline at end of file