Is it possible to get Powershell runbook output via HTTP?

Thomas Lu 41 Reputation points
2023-09-08T08:41:52.1833333+00:00

I've set up an Azure Automation Account and have created some Powershell runbooks which execute successfully via Powershell and HTTP POST requests.

However, while I am able to view the output from the runbook's job history, or from Powershell, I cannot find a way to retrieve the output via an HTTP GET request.

Given that I receive a jobID whenever the runbook is run, is it possible to capture the output in any way besides Powershell's Get-AzureRmAutomationJob?

(I've seen the following URL https://management.azure.com/subscriptions/{subscriptionID}/resourceGroups/{resourceGroup}/providers/Microsoft.Automation/automationAccounts/{automationAccount}/jobs/{jobID}/output?api-version=2019-06-01 but attempting to make an HTTP request against that returns an error about the refresh token not being found.)

Azure Automation
Azure Automation
An Azure service that is used to automate, configure, and install updates across hybrid environments.
1,273 questions
PowerShell
PowerShell
A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
2,671 questions
{count} votes

Accepted answer
  1. tbgangav-MSFT 10,421 Reputation points
    2023-09-12T08:52:56.49+00:00

    Hi @Thomas Lu ,

    Firstly, there were two probable typos in the code that you have shared.

    1. Value of $jobOutputURL contains unwanted "}" after $resourceGroup.
    2. Uri mentioned in the last line of the code is referring to $webhookUrl but it is supposed to consider $jobOutputURL.

    User's image

    After removing those probable typos, I have created below sample runbook to solve this issue.

    User's image

    Then, I have created webhook as shown below.

    User's image

    User's image

    User's image

    Then, I have tried the same way as you did and have received same authorization header missing error.

    User's image

    This is because the last line of the code thats using the second Invoke-RestMethod command doesn't understand using which access token or authorization it should use to send an HTTP or HTTPS request to the RESTful web service API resource URI management.azure.com that we have stored in the variable $jobOutputURL.

    So, we need to add headers parameter to that Invoke-RestMethod cmdlet which should contain access token. For that, as a one-time task, you would have to create a service principal, the one that makes the API call, grant permission, generate client secret. Next, you can use PowerShell to get bearer token and use it in our second Invoke-RestMethod command as shown below.

    User's image

    User's image

    User's image

    Job output from UI:

    User's image

    User's image

    Lastly, find the code below so it can be easily used in your environment:

    # Replace these variables with your desired values
    $spName = "xxxxxxxxxxxx" # Replace with the desired service principal name
    $role = "Contributor"  # Replace with the desired role
    
    # Create a new service principal with RBAC
    $sp = New-AzADServicePrincipal -DisplayName $spName
    
    # Assign the desired role to the service principal
    New-AzRoleAssignment -RoleDefinitionName $role -ServicePrincipalName $sp.AppId
    
    $tenantId = $sp.AppOwnerOrganizationId
    $clientId = $sp.AppId
    $clientSecret = $sp.PasswordCredentials.SecretText
    $resource = "https://management.azure.com/" # Replace with your API resource URI
    
    $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/token"
    $tokenParams = @{
        "grant_type"    = "client_credentials"
        "client_id"     = $clientId
        "client_secret" = $clientSecret
        "resource"      = $resource
    }
    
    Start-Sleep -Seconds 120
    
    $tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method Post -ContentType "application/x-www-form-urlencoded" -Body $tokenParams
    $accessToken = $tokenResponse.access_token
    
    $headers = @{
        "Authorization" = "Bearer $accessToken"
    }
    
    $webhookUrl = "xxxxxxxxxxxxxxxxxx" # Replace with your webhook Url
    
    $jsonBody = '{ "samaccountname":"thomas.lu" }'
    
    $response = Invoke-RestMethod -Uri $webhookUrl -Method Post -ContentType "application/json" -Body $jsonBody
    
    $subscriptionID = "xxxxxxxxxxxxxxxxxxx" # Replace with your subscription ID
    $resourceGroup = "xxxxxxxxxxxxxxxxxxxxx" # Replace with your resource group name
    $automationAccount = "xxxxxxxxxxxxxxxxx" # Replace with your automation account name
    
    $jobOutputURL = "https://management.azure.com/subscriptions/$subscriptionID/resourceGroups/$resourceGroup/providers/Microsoft.Automation/automationAccounts/$automationAccount/jobs/$($response.JobIds[0])/output?api-version=2019-06-01"
    
    Start-Sleep -Seconds 120
    
    $requestOutput = Invoke-RestMethod -Uri $jobOutputURL -Method Get -Headers $headers
    
    $requestOutput
    

    Let me know if you have any questions.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.