title | description | services | ms.service | ms.component | author | ms.author | ms.date | ms.topic | manager |
---|---|---|---|---|---|---|---|---|---|
Starting an Azure Automation runbook with a webhook |
A webhook that allows a client to start a runbook in Azure Automation from an HTTP call. This article describes how to create a webhook and how to call one to start a runbook. |
automation |
automation |
process-automation |
georgewallace |
gwallace |
10/06/2018 |
conceptual |
carmonm |
A webhook allows you to start a particular runbook in Azure Automation through a single HTTP request. This allows external services such as Azure DevOps Services, GitHub, Azure Log Analytics, or custom applications to start runbooks without implementing a full solution using the Azure Automation API.
You can compare webhooks to other methods of starting a runbook in Starting a runbook in Azure Automation
The following table describes the properties that you must configure for a webhook.
Property | Description |
---|---|
Name | You can provide any name you want for a webhook since this is not exposed to the client. It is only used for you to identify the runbook in Azure Automation. As a best practice, you should give the webhook a name related to the client that uses it. |
URL | The URL of the webhook is the unique address that a client calls with an HTTP POST to start the runbook linked to the webhook. It is automatically generated when you create the webhook. You cannot specify a custom URL. The URL contains a security token that allows the runbook to be invoked by a third-party system with no further authentication. For this reason, it should be treated like a password. For security reasons, you can only view the URL in the Azure portal at the time the webhook is created. Note the URL in a secure location for future use. |
Expiration date | Like a certificate, each webhook has an expiration date at which time it can no longer be used. This expiration date can be modified after the webhook is created as long as the webhook is not expired. |
Enabled | A webhook is enabled by default when it is created. If you set it to Disabled, then no client is able to use it. You can set the Enabled property when you create the webhook or anytime once it is created. |
A webhook can define values for runbook parameters that are used when the runbook is started by that webhook. The webhook must include values for any mandatory parameters of the runbook and may include values for optional parameters. A parameter value configured to a webhook can be modified even after creating the webhook. Multiple webhooks linked to a single runbook can each use different parameter values.
When a client starts a runbook using a webhook, it cannot override the parameter values defined in the webhook. To receive data from the client, the runbook can accept a single parameter called $WebhookData of type [object] that contains data that the client includes in the POST request.
The $WebhookData object has the following properties:
Property | Description |
---|---|
WebhookName | The name of the webhook. |
RequestHeader | Hash table containing the headers of the incoming POST request. |
RequestBody | The body of the incoming POST request. This retains any formatting such as string, JSON, XML, or form encoded data. The runbook must be written to work with the data format that is expected. |
There is no configuration of the webhook required to support the $WebhookData parameter, and the runbook is not required to accept it. If the runbook does not define the parameter, then any details of the request sent from the client is ignored.
If you specify a value for $WebhookData when you create the webhook, that value is overridden when the webhook starts the runbook with the data from the client POST request, even if the client does not include any data in the request body. If you start a runbook that has $WebhookData using a method other than a webhook, you can provide a value for $Webhookdata that is recognized by the runbook. This value should be an object with the same properties as $Webhookdata so that the runbook can properly work with it as if it was working with actual WebhookData passed by a webhook.
For example, if you are starting the following runbook from the Azure portal and want to pass some sample WebhookData for testing, since WebhookData is an object, it should be passed as JSON in the UI.
For the following runbook, if you have the following properties for the WebhookData parameter:
- WebhookName: MyWebhook
- RequestBody: [{'ResourceGroup': 'myResourceGroup','Name': 'vm01'},{'ResourceGroup': 'myResourceGroup','Name': 'vm02'}]
Then you would pass the following JSON value in the UI for the WebhookData parameter. The following example with the carriage returns and newline characters matches the format that is passed in from a webhook.
{"WebhookName":"mywebhook","RequestBody":"[\r\n {\r\n \"ResourceGroup\": \"vm01\",\r\n \"Name\": \"vm01\"\r\n },\r\n {\r\n \"ResourceGroup\": \"vm02\",\r\n \"Name\": \"vm02\"\r\n }\r\n]"}
Note
The values of all input parameters are logged with the runbook job. This means that any input provided by the client in the webhook request will be logged and available to anyone with access to the automation job. For this reason, you should be cautious about including sensitive information in webhook calls.
The security of a webhook relies on the privacy of its URL, which contains a security token that allows it to be invoked. Azure Automation does not perform any authentication on the request as long as it is made to the correct URL. For this reason, webhooks should not be used for runbooks that perform highly sensitive functions without using an alternate means of validating the request.
You can include logic within the runbook to determine that it was called by a webhook by checking the WebhookName property of the $WebhookData parameter. The runbook could perform further validation by looking for particular information in the RequestHeader or RequestBody properties.
Another strategy is to have the runbook perform some validation of an external condition when it received a webhook request. For example, consider a runbook that is called by GitHub whenever there is a new commit to a GitHub repository. The runbook might connect to GitHub to validate that a new commit had occurred before continuing.
Use the following procedure to create a new webhook linked to a runbook in the Azure portal.
-
From the Runbooks page in the Azure portal, click the runbook that the webhook starts to view its detail page. Ensure the runbook Status is Published.
-
Click Webhook at the top of the page to open the Add Webhook page.
-
Click Create new webhook to open the Create webhook page.
-
Specify a Name, Expiration Date for the webhook and whether it should be enabled. See Details of a webhook for more information these properties.
-
Click the copy icon and press Ctrl+C to copy the URL of the webhook. Then record it in a safe place. Once you create the webhook, you cannot retrieve the URL again.
-
Click Parameters to provide values for the runbook parameters. If the runbook has mandatory parameters, then you are not able to create the webhook unless values are provided.
-
Click Create to create the webhook.
To use a webhook after it has been created, your client application must issue an HTTP POST with the URL for the webhook. The syntax of the webhook is in the following format:
http://<Webhook Server>/token?=<Token Value>
The client receives one of the following return codes from the POST request.
Code | Text | Description |
---|---|---|
202 | Accepted | The request was accepted, and the runbook was successfully queued. |
400 | Bad Request | The request was not accepted for one of the following reasons:
|
404 | Not Found | The request was not accepted for one of the following reasons:
|
500 | Internal Server Error | The URL was valid, but an error occurred. Please resubmit the request. |
Assuming the request is successful, the webhook response contains the job ID in JSON format as follows. It will contain a single job ID, but the JSON format allows for potential future enhancements.
{"JobIds":["<JobId>"]}
The client cannot determine when the runbook job completes or its completion status from the webhook. It can determine this information using the job ID with another method such as Windows PowerShell or the Azure Automation API.
When a webhook is created it has an validity time of one year. After that year time the webhook automatically expires. Once a webhook is expired it can not be re-activated, it must be removed and recreated. If a webhook has not reached its expiry time it can be extended.
To extend a webhook, navigate to the runbook that contains the webhook. Select Webhooks under Resources. Click the webhook that you want to extend, this opens the Webhook page. Choose a new expiration date and time and click Save.
The following sample runbook accepts the webhook data and starts the virtual machines specified in the request body. To test this runbook, in your Automation Account under Runbooks, click + Add a runbook. If you do not know how to create a runbook, see Creating a runbook.
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
# If runbook was called from Webhook, WebhookData will not be null.
if ($WebhookData) {
# Check header for message to validate request
if ($WebhookData.RequestHeader.message -eq 'StartedbyContoso')
{
Write-Output "Header has required information"}
else
{
Write-Output "Header missing required information";
exit;
}
# Retrieve VM's from Webhook request body
$vms = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
# Authenticate to Azure by using the service principal and certificate. Then, set the subscription.
Write-Output "Authenticating to Azure with service principal and certificate"
$ConnectionAssetName = "AzureRunAsConnection"
Write-Output "Get connection asset: $ConnectionAssetName"
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
throw "Could not retrieve connection asset: $ConnectionAssetName. Check that this asset exists in the Automation account."
}
Write-Output "Authenticating to Azure with service principal."
Add-AzureRmAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint | Write-Output
# Start each virtual machine
foreach ($vm in $vms)
{
$vmName = $vm.Name
Write-Output "Starting $vmName"
Start-AzureRMVM -Name $vm.Name -ResourceGroup $vm.ResourceGroup
}
}
else {
# Error
write-Error "This runbook is meant to be started from an Azure alert webhook only."
}
The following example uses Windows PowerShell to start a runbook with a webhook. Any language that can make an HTTP request can use a webhook; Windows PowerShell is used here as an example.
The runbook is expecting a list of virtual machines formatted in JSON in the body of the request. The runbook validates as well that the headers contain a specifically defined message to validate the webhook caller is valid.
$uri = "<webHook Uri>"
$vms = @(
@{ Name="vm01";ResourceGroup="vm01"},
@{ Name="vm02";ResourceGroup="vm02"}
)
$body = ConvertTo-Json -InputObject $vms
$header = @{ message="StartedbyContoso"}
$response = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Headers $header
$jobid = (ConvertFrom-Json ($response.Content)).jobids[0]
The following example shows the body of the request that is available to the runbook in the RequestBody property of WebhookData. This is formatted as JSON because that was the format that was included in the body of the request.
[
{
"Name": "vm01",
"ResourceGroup": "myResourceGroup"
},
{
"Name": "vm02",
"ResourceGroup": "myResourceGroup"
}
]
The following image shows the request being sent from Windows PowerShell and the resulting response. The job ID is extracted from the response and converted to a string.
- To learn how to use Azure Automation to take action on Azure Alerts, see Use an alert to trigger an Azure Automation runbook.