Azure Automation Week: Run a Runbook Without the Cmdlets!
Now that I have an Azure Automation account, and a user with the correct permissions, I have the ability to run Azure Automation runbooks without relying on the cmdlets or webhooks. I don’t want to have to rely on cmdlets in WinPE, and I also don’t want to have to rely on webhooks because you cannot get the results back from them.
Before I can start, I need a runbook to test! So, let’s fire up portal.azure.com and select our Automation Account:
Now, you’ll want to select Runbooks:
Add a runbook
Quick Create
Then give it a name and use the type PowerShell:
Now you have a screen that is similar to the PowerShell ISE window. I’m not going to do anything fancy here. I’ll just have a parameter and return the parameter:
Save it, then publish it:
You now have a runbook you can use in a script!
Now, we want to be able to call the runbook in PowerShell and wait for a response. To do this, I’ll be using the Azure Automation REST API. There is a great guide on Laurie Rhode’s blog that details how to do this in PowerShell, but they don’t leave us with a workable function. I took this information and put it into a function so we can easily use it in OSD! Here’s my function:
Function Run-AzureRunbook { Param ( $AutomationAccount, $adTenant, $UserName, $Password, $RunBookName, $RunBookParamHash, $HybridWorkerGroup, $Params ) $ARMResource = 'https://management.core.windows.net/' $resourceAppIdURI = 'https://management.core.windows.net/' $ClientID = '1950a258-227b-4e31-a9cf-717495945fc2' $FullUserName = "$UserName@$($adTenant)" $TokenEndpoint = "https://login.windows.net/$($adTenant)/oauth2/token" $UserAuthPayload = "resource=$($resourceAppIdURI)&client_id=$($clientId)"+"&grant_type=password&username=$($FullUserName)&password=$($password)&scope=openid" $null = [System.Reflection.Assembly]::LoadWithPartialName("System.Web") $payload =@" $($UserAuthPayload), $([System.Web.HttpUtility]::UrlEncode($ARMResource)), $([System.Web.HttpUtility]::UrlEncode($FullUserName)), $([System.Web.HttpUtility]::UrlEncode($Password)), "@ $Header = @{ "Content-Type" = "application/x-www-form-urlencoded"; } try { $AuthResult = Invoke-RestMethod -Uri $TokenEndpoint -Method Post -body $Payload -Headers $Header } catch { $ThrowMessage = "Could not create the authorization token. Error Message: $($_.Exception.Message)" throw $ThrowMessage Exit } $JobId = [GUID]::NewGuid().ToString() $RequestHeader = @{ "Content-Type" = "application/json"; "x-ms-version" = "2013-08-01"; "Authorization" = "$($authResult.token_type) $($authResult.access_token)" } $Body = @" { "properties":{ "runbook":{ "name":"$RunBookName" }, "parameters":{ $Params }, "runOn":"$HybridWorkerGroup", "isEncrypted":1 } } "@ $URI = 'https://management.azure.com' + "$($AutomationAccount)/jobs/$($jobid)?api-version=2015-10-31" try { $Response = Invoke-RestMethod -Uri $URI -Method Put -body $body -Headers $RequestHeader } catch { $ThrowMessage = "Could not start job. Error Message: $($_.Exception.Message)" Throw $ThrowMessage Exit } $LoopStart = Get-Date $Loop = $true while($Loop) { $job = $null try { $job = Invoke-RestMethod -Uri $URI -Method GET -Headers $RequestHeader } catch { $ThrowMessage = "Could not get the job results. Error Message: $($_.Exception.Message)" Throw $ThrowMessage exit } $Script:Status = $Job.Properties.provisioningState $Loop = (($Status -ne 'Succeeded') -and ($Status -ne 'Failed') -and ($Status -ne 'Suspended') -and ($Status -ne 'Stopped')) $TimeElapsed = (Get-Date) - $LoopStart if ($TimeElapsed.Minutes -ge 5) { $Loop = $false } } $responseURI = 'https://management.azure.com' + "$($AutomationAccount)/jobs/$($jobid)/output?api-version=2015-10-31" $Response = $null try { $Response = Invoke-RestMethod -Uri $responseURI -Method Get -Headers $RequestHeader } catch { $ThrowMessage = "Could not get the job output. Error Message: $($_.Exception.Message)" Throw $ThrowMessage exit } return $Response }
The parameters and where you get them from are:
RunbookName: The name of the runbook you created Params: The parameters in this format: “myinput”:”datahere” HybridWorkerGroup: The name of the hybrid worker group from yesterday UserName: OSD Service Account username that was set up yesterday Password: OSD Service Account password that was set up yesterday Automation Account: If you go to your runbook and then select settings –> Properties, you’ll see the Automation Account. It’s a VERY long string that starts with /subscriptions adTenant: The adTenant of UserName. If you don’t already know it, you can go to manage.windowsazure.com, go down to Active Directory, select your domain, find the username, then it’s whatever is after @.
Now, run the runbook with this command, and you should get the right data returned!
Leave a Comment