Azure Automation - Device Cleanup

Azure Automation - Device Cleanup
This article has been superseded! I will be updating this post to show how we can migrate to the new method. Please use this article instead:
Azure Automation - Device Cleanup v2 (

Please use this method moving foward 👇

Azure Automation - Device Cleanup v2
Almost a year ago, I shared how we can use Azure Automation to clean up devices in Azure AD. Unfortunately, Graph API only supported Disable as an option at the time (when using Application permissions), but apparently that changed some time around February 1! Another thing I was unhappy about

Archived Version - Do not use :)

I'm a huge fan of Azure Automation. If you're an #AzureAD / #M365 Admin and haven't used it before, then this thread is for you.

You will need an Azure subscription, but the first 500 minutes/month are free!

Here's an example of how to automate Azure AD device cleanup :)  First, we're going to log into the Azure portal:

Search for Automation and click on Automation Accounts

Then we'll click Create, pick the sub and resource group (or create one), give it a descriptive name, select a location, and hit Review + Create

If you haven't heard, the MSOnline and AzureAD PowerShell modules are going away at the end of the year. So instead, we are going to use the new Graph SDK PowerShell modules.

So let's go under Modules, click Add a Module, browse the gallery, and add Microsoft.Graph.Authentication.

Now, the Graph SDK PowerShell modules are a bit... different.

There are modules for every scope rather than one large module like we used to have. So we just did the one required for Authentication, and we also need to add the Microsoft.Graph.Identity.DirectoryManagement module.

Now, we need to create a Run as account since Automation's Managed Identities only work for Azure resources (AFAIK - please correct me!).

Next up, we need to grant Graph API permissions to managed devices to the Service Principal that was just created by our Automation Account.

So let's head over to App registrations and search for the name of our Automation Account. Select the account, then go to API permissions, and click Add a permission.

In the Request API permissions dialog, click Microsoft Graph, then select Application permissions.

In the filter, we'll search for Device.ReadWrite.All. Expand Device, check the box for Device.ReadWrite.All, then click Add permission. Now click Grant admin consent for the Service Principal to be authorized for your tenant and confirm.

The final step is to create our Runbook.

Go back to your Automation account, click Runbooks under Process Automation, and then click Create a runbook. Give it a name, select PowerShell for type, and the runtime needs to match modules (5.1 if following the images so far).

Here's the code to paste in:

You can test code in the Test pane (add -WhatIf), but first... Apparently Graph is different than AzureADPreview, so we will need one additional step - adding the Service Principal to the Cloud Device Administrator role.

Whoops, don't forget to Publish!

Now go to Azure AD - Roles and Administrators, earch for Cloud Device Administrator, click Add assignments, then search for the Service Principal for your Automation Account, and add it.

You should now be able to run with proper permissions!

If we go back to our Automation Account and look at the Runbook we just created, we can manually run this script by clicking Start. This will take us to the job where we can see output.

We can also see the history under Jobs for our Automation Account.

But let's schedule this!

Open your runbook, then click the Link to Schedule button.

We want to link a schedule to our runbook, then add a schedule, and then configure it how we want :)

Here's an example of running daily at midnight.

And that's really all there is to it!

You are now automating disabling of devices that haven't talked to AAD in 90 days :D