Resolved: Azure Lighthouse – Call HTTP endpoint once everything is deployed

Question:

I want to onboard a subscription into my tenant and once it’s finished, I want to call an HTTP endpoint, to process some other logic on my side.
Since my ARM template executes on the subscription scope, I cannot use deployment script, as it requires a resource group. The other workaround I found, is to use a deployment that gets the template from a URL. But, there is a problem with this as well. In my case, the endpoint gets called three times, even though I set the dependsOn parameter. It gets called:
  1. Once validated
  2. Once the deployment is initialized
  3. Once all other resources are deployed.

Here’s some part of the ARM template:
{
    "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    // Other properties
    "resources": [
        {
            "type": "Microsoft.ManagedServices/registrationDefinitions",
            "apiVersion": "2019-09-01",
            "name": "[variables('mspRegistrationName')]",
            "properties": {
                "registrationDefinitionName": "[parameters('mspOfferName')]",
                "description": "[parameters('mspOfferDescription')]",
                "managedByTenantId": "[variables('managedByTenantId')]",
                "authorizations": "[variables('authorizations')]"
            }
        },
        {
            "type": "Microsoft.ManagedServices/registrationAssignments",
            "apiVersion": "2019-09-01",
            "name": "[variables('mspAssignmentName')]",
            "dependsOn": [
                "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"
            ],
            "properties": {
                "registrationDefinitionId": "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"
            }
        },
        {
            "name": "Callback",
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2020-10-01",
            "location": "westus",
            "dependsOn": [
                "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]",
                "[resourceId('Microsoft.ManagedServices/registrationAssignments/', variables('mspRegistrationName'))]"
            ],
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "uri": "[variables('TemplateUri')]"
                },
                "parameters":  {}
            }
        }
    ],
Of course, I can hardcode that the third call is valid, but that’s not a good approach. Is there any “safer” way of calling the endpoint from ARM template?

Answer:

You could create a resource group with the ARM template, then deploy a nested template containing a deployment script into it. Both RGs and RG-level deployments can be created as resources in a subscription-level template.
An alternative would be to create an Azure function with an event grid trigger, listening for ARM events, though this would also require resources that can only be deployed at the resource group level.

If you have better answer, please add a comment about this, thank you!