azure-logic-appsazure-rm-templateazure-sentinel

Azure Sentinel: Logic App Playbook Code Migration to Another Tenant


I would like to migrate a logic app from one tenant into another tenant.

For example here is an arm template from the Sentinel GitHub - this is what i want to achieve. How would you migrate a logic app in your environment to another environment.

I understand you can copy paste the code view, however, the connections and default paths are all linked to the environment. How do you overcome this and what is best practice to do this?

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "metadata": {
        "title": "Change Incident Severity", 
        "description": "This playbook will change Incident Severity based on specific username that is part of the Incident user entity.",
        "prerequisites": "After deployment, update condition action with user names to check for",
        "lastUpdateTime": "2021-06-03T00:00:00.000Z", 
        "entities": ["Account"], 
        "tags": ["Triage"], 
        "support": {
            "tier": "community" 
        },
        "author": {
            "name": "Yaniv Shasha"
        }
    },
    "parameters": {
        "PlaybookName": {
            "defaultValue": "Change-Incident-Severity",
            "type": "string"
        }
    },
    "variables": {
        "AzureSentinelConnectionName": "[concat('azuresentinel-', parameters('PlaybookName'))]"
    },
    "resources": [
        {
            "type": "Microsoft.Web/connections",
            "apiVersion": "2016-06-01",
            "name": "[variables('AzureSentinelConnectionName')]",
            "location": "[resourceGroup().location]",
            "kind": "V1",
            "properties": {
                "displayName": "[parameters('PlaybookName')]",
                "customParameterValues": {},
                "parameterValueType": "Alternative",
                "api": {
                    "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/azuresentinel')]"
                }
            }
        },
        {
            "type": "Microsoft.Logic/workflows",
            "apiVersion": "2017-07-01",
            "name": "[parameters('PlaybookName')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "LogicAppsCategory": "security"
            },
            "identity": {
                "type": "SystemAssigned"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/connections', variables('AzureSentinelConnectionName'))]"
            ],
            "properties": {
                "state": "Enabled",
                "definition": {
                    "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
                    "actions": {
                        "Entities_-_Get_Accounts": {
                            "inputs": {
                                "body": "@triggerBody()?['object']?['properties']?['relatedEntities']",
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['azuresentinel']['connectionId']"
                                    }
                                },
                                "method": "post",
                                "path": "/entities/account"
                            },
                            "runAfter": {},
                            "type": "ApiConnection"
                        },
                        "For_each": {
                            "actions": {
                                "Condition": {
                                    "actions": {
                                        "Update_incident": {
                                            "inputs": {
                                                "body": {
                                                    "incidentArmId": "@triggerBody()?['object']?['id']",
                                                    "severity": "High"
                                                },
                                                "host": {
                                                    "connection": {
                                                        "name": "@parameters('$connections')['azuresentinel']['connectionId']"
                                                    }
                                                },
                                                "method": "put",
                                                "path": "/Incidents"
                                            },
                                            "runAfter": {},
                                            "type": "ApiConnection"
                                        }
                                    },
                                    "expression": {
                                        "or": [
                                            {
                                                "contains": [
                                                    "@items('For_each')?['Name']",
                                                    "admin"
                                                ]
                                            }
                                        ]
                                    },
                                    "runAfter": {},
                                    "type": "If"
                                }
                            },
                            "foreach": "@body('Entities_-_Get_Accounts')?['Accounts']",
                            "runAfter": {
                                "Entities_-_Get_Accounts": [
                                    "Succeeded"
                                ]
                            },
                            "type": "Foreach"
                        }
                    },
                    "contentVersion": "1.0.0.0",
                    "outputs": {},
                    "parameters": {
                        "$connections": {
                            "defaultValue": {},
                            "type": "Object"
                        }
                    },
                    "triggers": {
                        "Microsoft_Sentinel_incident": {
                            "inputs": {
                                "body": {
                                    "callback_url": "@{listCallbackUrl()}"
                                },
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['azuresentinel']['connectionId']"
                                    }
                                },
                                "path": "/incident-creation"
                            },
                            "type": "ApiConnectionWebhook"
                        }
                    }
                },
                "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')]",
                                "connectionProperties": {
                                    "authentication": {
                                        "type": "ManagedServiceIdentity"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    ]
}

Solution

  • After exploring on your requirement, I found that there is no direct way to move all the dependencies of an Azure resource (e.g. Logic App) during migration.

    Refer Q&A to check the similar information.

    There are few approaches to achieve your requirement which are listed below.

    1. You can create a new ARM template in the target tenant with all the dependent configurations like Api connections etc. to make the job easier.

    Or

    1. After deploying the provided template using ARM, I've exported it to my existing code directory using PowerShell. This allows to deploy the code directly to the target tenant without the need for any further adding or modifications.

    Resource deployed:

    enter image description here

    Export-AzResourceGroup PowerShell

    $res1 = Get-AzResource -ResourceGroupName xxxx -ResourceName Change-Incident-Severity -ResourceType Microsoft.Logic/workflows
    $res2 = Get-AzResource -ResourceGroupName xxxx -ResourceName azuresentinel-Change-Incident-Severity -ResourceType Microsoft.Web/connections
    Export-AzResourceGroup -ResourceGroupName xxxx -Resource @($res1.ResourceId, $res2.ResourceId)
    

    enter image description here

    enter image description here

    Now you can deploy it using corresponding az deployment commands with the required tenant scope.

    3.

    Export and download the entire ARM code from the existing tenant displayed below, which has all the connections and configurations, then proceed to deploy it within the new tenant.

    enter image description here

    Reference: Check this Blog for the relevant information.