Report changes in Microsoft Intune

Report changes in Microsoft Intune

In this blog post I will describe how you easily can help yourself and your management to know if someone changed configurations or apps in your Microsoft Intune environment.
Many of my customers do have more than one administrator. With a modern way of working “Hybrid work” we sit at different locations, and it is not always that we remember to share what we configured or changed in the system.
The case could also be, that you want to be in control and that no one can do changes without you being aware of it. – Still curious how to do this? Then read along!

I will showcase to you the different ways to achieve this. We will look at Logic Apps and Power Automate and the cost of utilizing the different methods.

Microsoft Intune changes using Logic App

Change report

Prerequisites

  • Intune diagnostic configured (AuditLogs)
  • Azure Subscription
  • Log Analytics

Creating your Logic App flow

Start by going to portal.azure.com
Search for Logic apps

Logic App flow

Click Add

Logic App flow

Add relevant information

  1. Choose subscription and create a new Resource Group
  2. Logic App name needs to be unique. A good tip is to add a corporate identifier, but keep it simple.
  3. Choose your region
  4. I choose Standard and you can see more on the pricing here
  5. Review + Create

TIP:
If you use standard you will have a bunch of benefits, but at the same time the price will rise. As a sum up I will show you how much it will cost you using this method. You can also read more here

Logic App flow

If you only need to run a small amount of flows then I’d suggest that you use comsumption based instead. It is much cheaper, and I will show you the difference in the summary.

INFO!
Be aware that if you choose the consumption plan, the next couple of pictures will not be the ones you see. – I think you will find your way through anyway, as it is pretty logical.

Logic App flow

Create

Logic App flow

Click into the new Logic app choose Workflows and click add

Logic App flow

Call it whatever you like as long as it makes sense.

Logic App flow

Choose Designer

Logic App flow

Add Recurrence and set it to a schedule that fit your needs.

Logic App flow

Add Run query and visualize results add parameters where you have configured your Log Analytics Workspace

Kudos to Oliver for providing a great example of KQL

Logic App flow
Logic App flow
IntuneAuditLogs
| where OperationName == "Patch DeviceConfiguration"
    or OperationName == "Patch DeviceManagementConfigurationPolicy"
    or OperationName == "Patch DeviceManagementIntent"
    or OperationName == "Patch DeviceCompliancePolicy"
    or OperationName == "Update GroupPolicyConfiguration"
    or OperationName == "Create DeviceConfiguration"
    or OperationName == "Create DeviceManagementConfigurationPolicy"
    or OperationName == "Create DeviceManagementIntent"
    or OperationName == "Create DeviceCompliancePolicy"
    or OperationName == "Create GroupPolicyConfiguration"
    or OperationName == "Delete DeviceConfiguration"
    or OperationName == "Delete DeviceManagementConfigurationPolicy"
    or OperationName == "Delete DeviceManagementIntent"
    or OperationName == "Delete GroupPolicyConfiguration"
    or OperationName == "Delete DeviceCompliancePolicy"
    or OperationName == "Patch MobileApp"
    or OperationName == "Create MobileApp"
    or OperationName == "Delete MobileApp"
    or OperationName == "Create WindowsFeatureUpdateProfile"
    or OperationName == "Patch WindowsFeatureUpdateProfile"
    or OperationName == "Delete WindowsFeatureUpdateProfile"
    or OperationName == "Create WindowsQualityUpdateProfile"
    or OperationName == "Patch WindowsQualityUpdateProfile"
    or OperationName == "Delete WindowsQualityUpdateProfile"
| extend PropertiesJson = parse_json(Properties)
| where TimeGenerated > now() - 24hours
| extend ActorJson = parse_json(PropertiesJson.Actor)
| extend Policy = replace_regex(tostring(todynamic(Properties).TargetDisplayNames), @'["\[\]]', "")
| extend ChangedBy = todynamic(Properties).Actor.UPN
| project
    TimeGenerated=TimeGenerated,
    Policy,
    ChangedBy,
    Operation=OperationName
| order by TimeGenerated

Again add Run query and visualize results add parameters where you have configured your Log Analytics Workspace. (all settings should be the same as the other object we just configured.)

Kudos to Ugur for providing a great example of KQL

Logic App flow
IntuneAuditLogs
| where OperationName == "Patch DeviceConfiguration"
    or OperationName == "Patch DeviceManagementConfigurationPolicy"
    or OperationName == "Patch DeviceManagementIntent"
    or OperationName == "Patch DeviceCompliancePolicy"
    or OperationName == "Update GroupPolicyConfiguration"
    or OperationName == "Create DeviceConfiguration"
    or OperationName == "Create DeviceManagementConfigurationPolicy"
    or OperationName == "Create DeviceManagementIntent"
    or OperationName == "Create DeviceCompliancePolicy"
    or OperationName == "Create GroupPolicyConfiguration"
    or OperationName == "Delete DeviceConfiguration"
    or OperationName == "Delete DeviceManagementConfigurationPolicy"
    or OperationName == "Delete DeviceManagementIntent"
    or OperationName == "Delete GroupPolicyConfiguration"
    or OperationName == "Delete DeviceCompliancePolicy"
    or OperationName == "Patch MobileApp"
    or OperationName == "Create MobileApp"
    or OperationName == "Delete MobileApp"
    or OperationName == "Create WindowsFeatureUpdateProfile"
    or OperationName == "Patch WindowsFeatureUpdateProfile"
    or OperationName == "Delete WindowsFeatureUpdateProfile"
    or OperationName == "Create WindowsQualityUpdateProfile"
    or OperationName == "Patch WindowsQualityUpdateProfile"
    or OperationName == "Delete WindowsQualityUpdateProfile"
| where TimeGenerated > now() - 24hours
| extend ChangedBy = todynamic(Properties).Actor.UPN
| extend Apps = todynamic(Properties).Actor.ApplicationName
| extend Device = todynamic(Properties).TargetObjectIds
//| extend Policy = todynamic(Properties).TargetDisplayNames
| extend Policy = replace_regex(tostring(todynamic(Properties).TargetDisplayNames), @'["\[\]]', "")
| mv-expand todynamic(Properties).Targets[0].ModifiedProperties
| extend Configuration = todynamic(Properties_Targets_0_ModifiedProperties).Name
| extend ['New Value'] = todynamic(Properties_Targets_0_ModifiedProperties).New
| extend ['Old Value'] = todynamic(Properties_Targets_0_ModifiedProperties).Old
| project TimeGenerated, Policy, Configuration, ['New Value'], ['Old Value'], ChangedBy
| order by TimeGenerated

Add new step and setup Send an email (V2)

Logic App flow

TIP:
You can tell the difference on run query and visualize results as when multiple are added, they are numbered. The purple have number 2 where the first (the green) has no number.
You can also rename them if you like, that will make it easier to identify what value you are putting into your body

Logic App flow

Click Save

Logic App flow

To test your flow right away you can trigger it manually by going to Overview

Logic App flow

This is cool. We get an email every day with the changes in it, where we can easily track changes and have no surprises.

Logic app cost per month

A forecast for Logic apps where we use the “Standard” with 1 trigger per day is about 1200dkk pr month.

Logic app cost per month

A forecast for Logic apps where we use the “Consumtion based” with 1 trigger per day is about 2dkk pr month.

Logic app cost per month

Microsoft Intune changes using Power Automate

Prerequisites

Creating your Power Automate flow

Start by going to Power Automate
Click Create and click Scheduled cloud flow

Power Automate flow

Give it a proper name

Power Automate flow

Click New Step

Power Automate flow

Search for Azure monitor logs

Power Automate flow

We need the one called Run query and visualize results

TIP:
This one requires the Premium license. All other connectors we will be using does not.

Power Automate flow

Add all the needed informations.
These should be the ones where your log analytics is stored

Power Automate flow
IntuneAuditLogs
| where OperationName == "Patch DeviceConfiguration"
or OperationName == "Patch DeviceManagementConfigurationPolicy"
or OperationName == "Patch DeviceManagementIntent"
or OperationName == "Patch DeviceCompliancePolicy"
or OperationName == "Update GroupPolicyConfiguration"
or OperationName == "Create DeviceConfiguration"
or OperationName == "Create DeviceManagementConfigurationPolicy"
or OperationName == "Create DeviceManagementIntent"
or OperationName == "Create DeviceCompliancePolicy"
or OperationName == "Create GroupPolicyConfiguration"
or OperationName == "Delete DeviceConfiguration"
or OperationName == "Delete DeviceManagementConfigurationPolicy"
or OperationName == "Delete DeviceManagementIntent"
or OperationName == "Delete GroupPolicyConfiguration"
or OperationName == "Delete DeviceCompliancePolicy"
or OperationName == "Patch MobileApp"
or OperationName == "Create MobileApp"
or OperationName == "Delete MobileApp"
or OperationName == "Create WindowsFeatureUpdateProfile"
or OperationName == "Patch WindowsFeatureUpdateProfile"
or OperationName == "Delete WindowsFeatureUpdateProfile"
or OperationName == "Create WindowsQualityUpdateProfile"
or OperationName == "Patch WindowsQualityUpdateProfile"
or OperationName == "Delete WindowsQualityUpdateProfile"
| extend PropertiesJson = parse_json(Properties)
| where TimeGenerated > now() - 24hours
| extend ActorJson = parse_json(PropertiesJson.Actor)
| extend Policy = replace_regex(tostring(todynamic(Properties).TargetDisplayNames), @'["\[\]]', "")
| extend ChangedBy = todynamic(Properties).Actor.UPN
| project
TimeGenerated=TimeGenerated,
Policy,
ChangedBy,
Operation=OperationName
| order by TimeGenerated

In order to convert the output we need to use Initialize variable

Power Automate flow

Add your own name to it and make sure you use Type: string

Power Automate flow

Then you search for Set Variable and in the dropdown you choose what you specified above.
In Value you add the attachment Content from the Run query and visualize results from above

Power Automate flow

Create yet another Run query and visualize results

Power Automate flow
IntuneAuditLogs
| where OperationName == "Patch DeviceConfiguration"
    or OperationName == "Patch DeviceManagementConfigurationPolicy"
    or OperationName == "Patch DeviceManagementIntent"
    or OperationName == "Patch DeviceCompliancePolicy"
    or OperationName == "Update GroupPolicyConfiguration"
    or OperationName == "Create DeviceConfiguration"
    or OperationName == "Create DeviceManagementConfigurationPolicy"
    or OperationName == "Create DeviceManagementIntent"
    or OperationName == "Create DeviceCompliancePolicy"
    or OperationName == "Create GroupPolicyConfiguration"
    or OperationName == "Delete DeviceConfiguration"
    or OperationName == "Delete DeviceManagementConfigurationPolicy"
    or OperationName == "Delete DeviceManagementIntent"
    or OperationName == "Delete GroupPolicyConfiguration"
    or OperationName == "Delete DeviceCompliancePolicy"
    or OperationName == "Patch MobileApp"
    or OperationName == "Create MobileApp"
    or OperationName == "Delete MobileApp"
    or OperationName == "Create WindowsFeatureUpdateProfile"
    or OperationName == "Patch WindowsFeatureUpdateProfile"
    or OperationName == "Delete WindowsFeatureUpdateProfile"
    or OperationName == "Create WindowsQualityUpdateProfile"
    or OperationName == "Patch WindowsQualityUpdateProfile"
    or OperationName == "Delete WindowsQualityUpdateProfile"
| where TimeGenerated > now() - 24hours
| extend ChangedBy = todynamic(Properties).Actor.UPN
| extend Apps = todynamic(Properties).Actor.ApplicationName
| extend Device = todynamic(Properties).TargetObjectIds
//| extend Policy = todynamic(Properties).TargetDisplayNames
| extend Policy = replace_regex(tostring(todynamic(Properties).TargetDisplayNames), @'["\[\]]', "")
| mv-expand todynamic(Properties).Targets[0].ModifiedProperties
| extend Configuration = todynamic(Properties_Targets_0_ModifiedProperties).Name
| extend ['New Value'] = todynamic(Properties_Targets_0_ModifiedProperties).New
| extend ['Old Value'] = todynamic(Properties_Targets_0_ModifiedProperties).Old
| project TimeGenerated, Policy, Configuration, ['New Value'], ['Old Value'], ChangedBy
| order by TimeGenerated

and again we need to change our output using variables

Power Automate flow
Last flow we will need is the Send an email (v2). Behind the scenes it will create an connection to Office365
Power Automate flow

Add information so it looks like you want it to be

Power Automate flow

Save your flow

Power Automate flow
And to test it you can click Test in the right upper corner
Power Automate flow

Run Flow

Power Automate flow

And you should see something similar to mine

Power Automate flow

And shortly after a mail going into your mailbox

Change report

Power Automate cost per month

A forecast for Power Automate with 1 trigger per day is about 370dkk pr month. (unfortunately don’t have any graphics for that.)

Summary

There are several ways to automate flows when it comes to Azure and I’ve shown you 2 ways to accomplish a task that can help your daily operations.
It depends on your use which solution will be the cheapest, but if you only need a simple flow with few triggers a month, then I would strongly recommend using consumption based logic app flows.

I hope this blog post was helping you to decide where to add you flow and give you some inspiration to automate stuff using low code.
For more inspiration please have a look at my MVP colleague Peter Klapwijk as he has made a lot of great stuff in this area.

Table of Contents

Share this post
Search blog posts
Authors
Modern Workplace consultant and a Microsoft MVP in Enterprise Mobility.
Modern Workplace consultant and a Microsoft MVP in Windows and Devices for IT.

Infrastructure architect with focus on Modern Workplace and Microsoft 365 security.

Passionate IT professional with 20+ experience in IT architecture, consulting, and design. 

Cloud & security specialist with focus on Microsoft backend products and cloud technologies.

Infrastructure architect with focus on design, implementation, migration and consolidation.

Infrastructure consultant with focus on cloud solutions in Office365 and Azure.

follow us in feedly
Categories

Follow on SoMe