Interacting with Runbooks
Run runbooks and query their status using RealmJoins API
Overview
RealmJoin allows you to use Azure Automation Runbooks to automate day to day operations in your environment. See Runbooks for more information.
RealmJoin's API allows you to start runbooks from your application, to query the successful execution of previously triggered runs. See RealmJoin's Swagger description to see, which operations are currently supported.
The following sections lay out how to use RealmJoin's API to start and track runbook jobs. It is assumed that you already have connected an Azure Automation account to RealmJoin Portal. Also, make sure to authenticate every request against RealmJoin's API using an appropriate http Authorization header.
How does Azure Automation handle runbooks?
Azure Automation has a batch processing approach regarding runbooks. When you trigger the execution of a runbook, a job is created for this runbook and queued for execution.
So in general, a runbook will not start immediately. Also multiple job's for the same runbook can exist at the same time in different states of execution.
Every job has a set of parameters (inputs) that are passed on to the runbook script. This can e.g. be two variables like $username
and $newEmailAddress
if the runbook is supposed to add an eMail-Alias to a user's mailbox.
Every job has a status that represents its current state of execution, see Microsoft Docs. We will focus on Queued
, Running
, Completed
and Failed
in this document. Be aware this is a simplification for the purpose of easier understanding.
Starting a Runbook Job
RealmJoin API offers two endpoints to trigger runbooks.
run
will execute a runbook in a synchronous fashion and only return/finish when the runbook is actually completed or failed. This endpoint directly returns the success state and output of the associated runbook job.
start
will take the same parameters as run
but works in a an asynchronous fashion. It will return as soon as a runbook job is queued. It will return the jobID
to enable easy tracking of the new job.
Runbook naming
Runbooks are adressed by their name in Azure Automation. In short:
Is it synced from RealmJoin's GitHub repo? Add
rjgit-
as prefixEither
org_
,device_
,group_
,user_
as scope (exactly one of those)A category, like
general_
orsecurity_
The name of the runbook, separated by
_
likeadd-xyz-exception
The result in this case would be: rjgit-org_security_add-xyz-exception
See Naming Conventions for more details.
Example
Let us assume the following situation:
You have your RealmJoin API credentials and encoded them to
dC0xMjM0MTIzNDpteVMzY3JldCE=
(Base64)You want to start the runbook
rjgit-user_security_revoke-or-restore-access
to block sign in for a specific userThe parameters for the runbook (PowerShell) are:
$UserName = "someone@contoso.com"
$Revoke = $true
We will use the run
endpoint to immediately know if the job was successful.
Let us build the request:
Headers:
Request / URI:
Body (in JSON-Notation):
The request will take a while, as it waits for the job to execute. Please make sure you adapt your http clients timeout accordingly. Otherwise try using the start
endpoint, which will immediately return.
The response will contain the jobID
, the status
(Failed
or Completed
) and all output streams of the runbook.
Response:
Http Status: 200
(OK)
Body (in JSON-Notation):
The output streams are separated into different channels (streamTypes
): Output
, Verbose
, Error
. This allows to filter for errors or reduce output only to relevant information by only showing Output
.
You can get these streams after a runbook is finished using the /api/external/runbook/jobs/{jobID}/output/streams
endpoint. (see below)
Querying a Job's status and output
If a job has already beed created, you can use RealmJoin API to query its state and output.
Querying Job Status
Use /api/external/runbook/jobs/{jobID}/status
to query for the current status.
See Authentication on how to create an Authorization header, the following is only an example.
Assume the jobID
to be 1234545e-7a24-436a-90c9-6056b512345
Request
Headers:
Request / URI:
This request has no body.
Response
Http Status 200 (OK)
Body (Plaintext)
Other possible states include New
, Failed
, Running
. See possible Runbook states.
Reading Job Output
Use /api/external/runbook/jobs/{jobID}/output/text
to get a simple plaintext representation of the output of a runbook. This will not include the Verbose
and Error
stream. See reading streams to read other streams. Exceptions are handled separately.
See Authentication on how to create an Authorization header, the following is only an example.
Assume the jobID
to be 1234545e-7a24-436a-90c9-6056b512345
Request
Headers:
Request / URI:
This request has no body.
Response
Http Status 200 (OK)
Body (Plaintext)
Reading Specific Streams
Use /api/external/runbook/jobs/{jobID}/output/streams
to get a comprehensive json representation of the output of a runbook. This way you can access the Output
, Verbose
and Error
stream. Exceptions are handled separately.
See Authentication on how to create an Authorization header, the following is only an example.
Assume the jobID
to be 1234545e-7a24-436a-90c9-6056b512345
Request (all streams)
Headers:
Request / URI:
This request has no body.
Response
Http Status 200 (OK)
Body (JSON, array of messages)
See below to read interrupting error messages and exceptions
To just receive a single stream, for example Verbose, you can add a filter to the request by adding ?streamTypes=Verbose
. You can also filter for Output
and Error
.
Request (filter for a single stream)
Headers:
Request / URI:
This request has no body.
Response
Http Status 200 (OK)
Body (JSON, array of messages)
Reading Exceptions
Use /api/external/runbook/jobs/{jobID}/exception/text
to get a simple plaintext representation of a runbook's exception message (if present). This will not include the Output
, Verbose
and Error
streams. See reading streams to read other streams.
Exceptions are written, when interrupting errors happen in the execution of the PowerShell script associated with the runbook. This endpoint will only read the plaintext message and does not include technical details, like at which line of code the script stopped.
In out example, an interrupting error was caused by throw "Exception"
.
See Authentication on how to create an Authorization header, the following is only an example.
Assume the jobID
to be 1234545e-7a24-436a-90c9-6056b512345
Request
Headers:
Request / URI:
This request has no body.
Response
Http Status 200 (OK)
Body (Plaintext)
Last updated