Automatically deploy Windows drivers on Patch Tuesday

Today is a blog post about deploying drivers to our Windows devices using Microsoft Intune and Logic Apps. For some time, we have had the Windows Driver update management feature available in Microsoft Intune. This provides tooling to control when and which drivers are deployed to our Windows devices. We can build deployment rings for drivers like we already could to deploy Windows (Feature) Updates. We can approve the drivers that need to be deployed to our devices or decline drivers that we don’t want to deploy. If a driver causes issues, we can also pause the driver so it stops deploying to our devices.

Before a driver is deployed to our devices, the driver first needs to be approved. For recommended drivers, we have the option to automatically approve the drivers or to manually approve the drivers.

When different deployment rings are used, most likely the recommended drivers are automatically approved. Otherwise, all drivers need to be approved manually every once in a while. That was a time-consuming job, as previously only one driver could be approved at the same time. We didn’t have a bulk action to approve multiple drivers at once. But Microsoft made the bulk actions available in the Windows Drivers section!

We are now able to approve (or decline) multiple drivers in one action.

Automatically approve drivers, or?

Approving drivers automatically or manually both have their pros and cons. When using deployment rings and automatic approval, everything is deployed automatically, an IT admin doesn’t need to push the deployment button. And because of the rings, we can test the drivers in our environment in a small group before deploying them to the end-users.

Sounds great, right!?

The downside of this approach is that the drivers can be offered to a Windows device on any day of the month. The user does (does he?) know when the monthly Windows update is offered, but is also bothered with driver and firmware updates on other days instead of only around Patch Tuesday. And that is an issue in some environments.

I was following a conversation on X (Twitter) on the driver update topic and the need for drivers to only become available on Patch Tuesday when David (a Microsoft PM) answered the below;

Ok, that sounds good! So, if we approve all recommended drivers the day before Patch Tuesday (using the bulk action we now have), the drivers should be offered on the same day as the monthly Windows Update is offered.

But who is going to approve all those drivers every Patch Tuesday? We have bulk actions available, but still. Don’t we forget to approve the drivers every month? Can’t we automate this task!?

Of course, we should be able to do that. At least, I give it a shot with Logic Apps.

The solution in short

Information regarding Driver updates for Windows is available via Microsoft Graph. We can query this information using HTTP actions in an Azure Logic Apps flow, which we can run on an occurrence (every Patch Tuesday for example).

We first query MS Graph for all the recommended drivers of the driver policy that is set to manual approval. In this query, we filter on recommended drivers that need to be reviewed. Every returned driver is then approved and the deployment date is set.

Sounds pretty simple!

The complete flow can also be downloaded as a template from my GitHub repository for easy deployment.


To create this solution, we only have just one requirement. To query Microsoft Graph and to change the status of the driver to approved we need to have permission to perform this job. There are different options to authenticate to MS Graph and assign permissions, but I prefer an Azure Managed Identity.
The required Graph (Application) permission we need is:

Setup the Logic App flow

If this requirement of a Managed Identity is in place, we can start building our Logic Apps flow.

Sign in to the Azure portal and open the Logic App service. I created a blank Logic App of type Consumption.

When the flow is created, click on the name of the flow at the top of the screen, open the Identity section, and on the tab User assigned add your Managed Identity.

Open the Overview tab, which shows a few templates, and choose Recurrence.

Change the Interval to 1 and Frequency to Week.
Click Add new parameter and select On these days.
Select Tuesday as the day on which the flow should run.
I want to run this flow at the start of the day, so I also configured the Time zone and At these hours.

With the above settings, the flow would run every Tuesday, something we don’t want.

We can make sure the flow only runs on the second Tuesday of the month (Patch Tuesday) by adding a Trigger condition to the recurrence trigger. Click on the three dots in the right corner and click Settings. Enter below trigger condition:

I found the logic for this condition in this blog post, so I’m not going to explain it further in my post.

In the Windows Update ring for IT admins, I have configured deferral days to 0 and driver updates are automatically approved. For all other users, the deferral is configured to 2 days. To have the drivers offered to end-users on the same day as the Cumulative Update is offered (referring to David’s tweet), I should be good to approve the drivers on Patch Tuesday. But during my tests, the drivers became available pretty soon after the flow had run. Depending on your Windows Update ring implementation, you should change the Recurrence settings to your need, but we can also set the deployment date to one or more days after the flow run (that’s handled in the HTTP POST executeAction later in this post).
So, test this out to get the best user experience. I only tested this in my lab environment, so just with a handful of devices.

Next, we add an Initialize variable action. In this action, we set the Windows Drivers Update Profile ID.
This is the ID of the driver update profile in which the approval is set to manually. I use this variable so I don’t have to specify the ID later in the HTTP actions, but I can just select this variable.

The profile ID can be found in the address bar of your browser when the Driver update policy is opened.

We can also find the IP by running the below Graph query using the Graph Explorer;

We need to provide a Name and as Type we select String in the initialize variable action.
In the value box, we add the previously found profile ID.

Next, we add anHTTP action. With this action, we query the driver inventory of the driver update profile. If we did that without a filter, we would get back all the drivers that are inventoried under this profile. But we only want to have the recommended drivers, that need to be reviewed (are not approved or declined). Therefore, we’ll add a filter to the URL.

Select GET as Method.
Enter below URI:[ID]/driverInventories?$filter=(category%20eq%20%27recommended%27)%20and%20(approvalStatus%20eq%20%27needsReview%27)

We need to replace [ID] with the driver update profile id. As we have already set that as a variable, we can just select the ID from the Dynamic content list.

Next, choose Add Parameter and select Authentication.
As Authentication type select Managed identity.
Select your Managed identity from the list.
And add as Audience.

This is our HTTP action.

Next, we need to add a Parse JSON action, which is a Data operations action. We parse the output of the HTTP action, to be able to use the values later on in the flow.
As Content, we select Body from the Dynamic content list that is from our HTTP action.

We don’t have to write the schema ourselves, we can generate it by adding a sample payload. We can get this example payload, by running the current flow and grabbing the output from the HTTP action. We can also grab the body when we run the same query via Graph Explorer.

We can paste that response information from the HTTP action or Graph Explorer into the example payload box.

And our schema is created.

Next, we add an HTTP action again. With this action we are going to execute an action, in our case, we approve the drivers.

As Method select POST.
As URI enter:[ID]/executeAction

Choose Add Parameter and select Authentication.
As Authentication type select Managed identity.
Select your Managed identity from the list.
And add as Audience.

Again, we need to replace [ID] with the driver update profile id, which is found in the dynamic content list.

In the body, we are going to specify the actionName that we want to take (approve). We will specify the driverID (not to confuse it with the driver policy ID). And we specify a deploymentDate.

We do this all by adding this schema to the Body field;

    "actionName": "approve",
    "driverIds": ,
    "deploymentDate": ""

The driver ID we need to add is a variable, retrieved in the previous action and, thus can be add as dynamic content. Just select the id from the Parse JSON action and add it between the double quotes on the driverIds rule.

You will see that the HTTP action is automatically added to a For each action. This is done because we could retrieve multiple driver ids and we need to process all of them separately. To get this done, we use an For each action which loops through every driver id.

We cannot just enter a date and time as the deployment date, as the deployment date differs every time the flow runs. To add the date and time of the moment on which the flow runs, we can add this expression to the body;
formatDateTime(utcNow(), ‘yyyy-MM-ddTHH:mm:ssZ’)

The above expression adds the current date, but if there is a need not to add the date of Patch Tuesday but one day later we can use this expression;

Or two days later:

This is the flow we created;

By scheduling this flow, we automatically approve the drivers on Patch Tuesday.
As written you need to change the flow (recurrence and deployment date) to your needs and test what the best configuration works best in your environment.

Be the first to comment

Leave a Reply

Your email address will not be published.