Getting started with Graph and Azure Automation

Whilst I have many scripts which run in Azure runbooks (some are designed to do so), I’ve never actually covered how to setup your first automation account to use with Graph so now is the time to sort it!


You’ll need an Azure subscription, pay-as-you-go is fine as nothing in this will acrue costs.

Within the subscription you will need permissions to create resources, including potentially an app registration as we will cover the different connection methods.

Creating an automation account

Within your Azure tenant, search for and select Automation accounts:

Click Create

Select your subscription and resource group. If you haven’t yet created a resource group, simply click Create new and Azure will handle the rest.

You will also need a name for your automation account and a region. Unless you have specific private networking requirements, or require tags in your environment, click Review + Create

If everything looks correct, click Create

After a minute or two your deployment will be complete:

Click Go to resource so we can add our Graph modules. We will add the scripts once we have everything else in place

Adding modules

Out of the box, your runbook account will include all Azure az. modules, but as we are using Graph, we need to manually add them.

Under Shared Resources, click Modules

Click Add Module

Select Browse from gallery and click on the blue text

Your script should hopefully tell you which modules to add and you need to follow this process for each one. In this case we are adding Microsoft.Graph.Authentication as this is a requirement for all of my scripts:

Click on the module and press Select

It will pre-populate the name so the final choice here is to select the PowerShell version. This needs to match the version used in your script. You can have the same module in the automation account multiple times for different PS versions

Now click Import

If we refresh our module list, you can see the module is importing

After a few minutes is will be available

Now we can look at the different ways to connect.

App reg

We will start with the more commonly used option and if you need multi-tenant connections, often the best option. We will use both secret and certificate here

This uses an app registration created in Entra with permissions assigned.

In the portal, search for and select Entra ID

Click on App Registrations

Click New Registration

Give you app reg a name and select if you need it to be multi-tenant. Ignore the redirect URI for now. Then click Register

On the overview, make a note of the client ID as we will need that to authenticate later

Now we can set the redirect URI, click authentication

Click Add a platform

If your app doesn’t require any special URIs, select Mobile and Desktop applications

Check the three boxes and click Configure

Next, it’s going to need some permissions, click API Permissions

Click Add a permission

This is a graph guide, so select that:

We can now select permissions, Delegated permissions run as the logged in user so for an automation, unless we are passing credentials (which is a bad idea), we need Application

Now select your permissions, for Intune looked under DeviceManagement for the main ones and watch for Read vs ReadWrite depending on what you need to do.

Now we configure our authentication, click on Certificates and Secrets

Client ID and secret

Starting with the more widely used, client ID and secret

Click New client secret

Give your secret a name and an expiry, up to 24 months. Make a note of the expiry date as your secret will stop working after that

After clicking Add, copy the Value and store it somewhere secure, once you leave the page, it cannot be revealed again


We will use the Version 2 module of the microsoft.graph.authentication here.

To connect using an app reg (script can be found here)

Using our client ID and secret, we retrieve an access token:

            $body = @{
                grant_type    = "client_credentials";
                client_id     = <<<APPIDHERE>>>;
                client_secret = <<<APPSECRETHERE>>>;
                scope         = "";
            $response = Invoke-RestMethod -Method Post -Uri<<<TENANTID>>>/oauth2/v2.0/token -Body $body
            $accessToken = $response.access_token

We then connect with the token which in V2 needs to be converted to a SecureString:

$accesstokenfinal = ConvertTo-SecureString -String $accessToken -AsPlainText -Force

Certificate in Azure vault

If you would rather not use an app secret as it’s stored in plain text, an alternative is a certificate stored in a key-vault which we can retrieve within the script.

Within the Azure portal, search for and select Key Vaults

Click Create

Select your subscription and give the key vault a name. This name has to be exclusive across Azure so you might need some trial and error. As with before, you can create a resource group if required.

By default is will use Azure RBAC, if you need different configuration, click Next. Otherwise click Review + Create

Click Create and wait for the deployment to complete and click Go to resource

Click Certificates

In this example, we will generate a certificate, but you can also import an existing one

Click Generate/Import (make sure your permissions are enough here too)

Fill in your details as required and click Create

Once created, click on your certificate

Then click on the latest version (this will update as it renews)

Download it in CER format

Back in your Entra App Reg, click Certificates and Secrets, this time select Certificate

Click Upload certificate

Select the certificate just downloaded and click Add


We now connect to Graph using the cert and the Runbook managed identity

This script can be found here

First we connect to Azure with the managed identiy

Disable-AzContextAutosave -Scope Process | Out-Null

# Connect using a Managed Service Identity
try {
        $AzureContext = (Connect-AzAccount -Identity).context
        Write-Output "There is no system-assigned user identity. Aborting."; 

Now we need the thumbprint for the certificate in the vault

$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
    -DefaultProfile $AzureContext

        $CertificateSecret = Get-AzKeyVaultSecret -VaultName <<<VAULTNAME>>> -Name <<<CERTNAME>>> -AsPlainText
        $CertificateBytes = [System.Convert]::FromBase64String($CertificateSecret)
        $CertificateObject = New-Object System.Security.Cryptography.x509Certificates.x509Certificate2Collection
        $ProtectedCertificateBytes = $CertificateObject.Export([System.Security.Cryptography.x509Certificates.x509ContentType]::Pkcs12,"")
        Import-PfxCertificate -FilePath "c:\temp\Certificate.pfx" Cert:\CurrentUser\My

        $thumbprint2 = Get-Item "Cert:\CurrentUser\My\$($CertificateObject.thumbprint)"
$thumbprint = $thumbprint2.Thumbprint

Finally, connect to Graph using the thumbprint

Connect-MgGraph -TenantId <<<TENANTID>>> -ClientId <<<APPID>>> -CertificateThumbprint $thumbprint

Managed identity

If you are in a single-tenant scenario, managed identity connection is the safest as everything is handled within Azure and there are no expiries to worry about. During the runbook creation, it created a System Managed Identity within Entra which we can then use to connect.

Within your Runbook, click on Identity

Add any Azure role assignments as required for your script (probably Intune admin and/or User admin)

That’s it, you can now connect:


connect-mggraph -identity

Adding your script

After sorting our permissions and connections, we can add our script.

Within the Automation account, click Runbooks

Click Create runbook

Add a name and select the Powershell version we used when adding the modules, then click Review + Create

You are now taken to a screen where you simply add your script.

Note: The script output pane will not display anything sent in a write-host so change to write-output if you want to see what’s happening

When added, click Save and then Publish

We have now added a script which we can run manually, but the beauty of runbooks is not having to do so.


The first option is a webhook where you can trigger a runbook via a URL passing through any parameters (for example, app reg details, or any parameters required in the script)

Click Webhooks

Add a webhook

Click create new webhook

Add a name and expiry and copy down the URL, you need this and it can’t be retrieved and click OK. Expiry can be up to 9 years

If your script has parameters or needs a hybrid worker (more on that below), press Modify run settings

Now to trigger your webhook, simply send a web request to the URL created. If sending parameters, add those to an array

An example in PHP:

    //Add to array
$data = array(
    array("tenant" => "<<<TENANT ID>>>"),
    array("clientid" => "<<<APP ID>>>"),
    array("clientsecret" => "<<<APP SECRET>>>")
$header = array("message" => "WEBHOOK DEPLOYED");
//Encode it
$body = json_encode($data);

//Setup CURL
$ch = curl_init();
$url = "<<<URLHERE>>>";
curl_setopt($ch, CURLOPT_URL, $runbookurl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);

Scheduled jobs

The other option is to run the runbooks on a schedule

Click Schedules

Click Add a schedule

Click Schedule

If you don’t have a schedule created, click Add a schedule at the top

Set your requirements and click Create

If your script has parameters, click Modify run settings

When completed, click OK

Hybrid Workers

Azure runbooks work on a Windows ARM machine with limited resources available. If you need more, such as a full Windows x64, you can use a hybrid worker. For this create a virtual machine and link it to the runbook under Hybrid worker groups

Just remember your VM will need standard maintenance as with any other VM

Hopefully this has been useful!

Leave a Comment