Microsoft Endpoint Manager Intune, Power Automate, and Microsoft Graph

One of my passions is working with customers and I’m fortunate to be able to speak with customers every day. Another passion of mine is automating tasks. A piece of customer feedback I receive is how to automate certain processes using the data within Intune, Microsoft 365, and 3rd party services.  Currently organizations may automate programatically by using the Microsoft Graph, however if you’re not familiar with using PowerShell or a developer it may be difficult to create a solution in the timeframe you need it by. Fortunately, there are Intune Graph samples available and if you’re intersted in viewing and utilizing the samples please visit: https://github.com/microsoftgraph/powershell-intune-samples.

Additionally, and the goal of this post, Microsoft Power Automate provides a robust set of templates and connectors to automate processes across Microsoft 365 and many other solutions.

For this post, using Microsoft Graph and Power Automate, I have automated end user email notifications after an end user has enrolled a device. The Power Automate (aka Flow) runs every hour and will send a mail to the end user who enrolled the device within the hour (or timeframe of your choice) of the last time the Power Automate process ran. From a security and user awareness perspective, an organization may want to notify users after a device enrollment completes, and if it wasn’t the user who actually enrolled the device, they could report it to their security and MDM teams.

Let’s get started

Requirements

  • Azure Active directory
  • Intune
  • Power Automate
  • SharePoint Online
  • Postman

Azure Active Directory

Register an application in Azure and creating a Power Automate connector for Microsoft Graph

We need to do several things to register an app in Azure AD and create a Power Automate connector, however registering an app in Azure AD and granting it permissions is several steps as is creating a Power Automate connector (because I use Postman to create the auth flow and query to Graph then save it out and import it to Power Automate as a custom connector). So to keep this focused on the automation piece, I found an individual online who published the following video who has a great walk through of how to do this in the first 30 minutes: https://www.bing.com/videos/search?q=graph+api+microsoft+flow&docid=608006419082446884&mid=DDFFFEB586D6DA665B5DDDFFFEB586D6DA665B5D&view=detail&FORM=VIRE

I recommend going through the steps in the video above and supplementing the perms and Graph call with the following:

To access Graph in Power Automate we to register a new application in Azure Active Directory so we can use it to make Graph calls to Intune. Once the application is registered we need to provide it the following application permissions to access Intune device objects:

Note: I have more perms granted than needed for this particular process, however the three above should be enough:

We also need to create a client secret and save it for later use in Postman:

Postman and Graph Explorer

If you don’t have Postman you can download it from: https://www.postman.com/downloads/

Use Graph explorer to come up with the query you’d like to use by visiting: https://developer.microsoft.com/en-us/graph/graph-explorer For this post I’m pulling all the managed devices from Intune: https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/

For reference, here is the authorization for the Flow connector collection I created in Postman.

You’ll save the collection out and import as a custom connector in Power Automate. Refer to the video above and it walks you through all this minus the uniqness of my query and app.


SharePoint Online

We need a method to look up when the last time the Flow ran and to do this I store one list item in a SharePoint list. The item I store is just the date, however what I really care about is the created time the list item was created because I call that in the Flow and compare it to when the devices were last enrolled. For example, if the Flow ran on 2020-04-03T20:22:15Z, the date is stored in SharePoint and for any device registered after that time, an email will be sent to the end user. It’s a simple process, however it works well.

The following is my SharePoint Online list where I store a formatted date in the Title fiel, however it really doesn’t matter what is stored in the Title field as the Flow looks for the “created” date for the single item. After the flow completes, I have a process in Flow that deletes the record and adds a new one so the next time it runs it has new date to reference.


Power Automate

At this point you should have an app registered with Azure AD, a connector created in Power Automate, and a SharePoint list to reference.  Now we can move on to the next step.

Let’s create the Power Automate process now:

In Power Automate select Create, name it, and as the trigger select “Manually trigger a flow”. We need a trigger, and for testing I recommend creating the Power Automate process with a manual trigger. When you’re ready to go live, delete the trigger and replace it with the Recurrence trigger, more on this later.

Here’s the Flow in it’s entirety, however I break it down in the next few steps:

First step in the Flow, beyond the manual trigger, is pulling the item from the SharePoint list.  Do to this, add a new action and search for SharePoint the select “Get items”. I’m not doing anything special in Get items as I’m just looking for that one item in the list so there is no need to limit or filter items:

Next add another action, select “Custom” and select the connector you created earlier:

Now we need to parse the JSON that was returned from the custom action above. Do this by adding an action and search for Parse JSON, then add it. As you can see in the image below I have a perfectly formatted JSON output, however this needs to be generated. To do this select “Generate from sample” and go to either Graph explorer or Postman and copy all the JSON query output and paste into the sample payload.  Once you select done in the sample payload prompt, it will format properly and show something identical to what I have in the image below (provided you’re making the same Graph call).  You can also remove attributes from the JSON if you don’t want to show them in the dynamic content.

Next I want to select only devices that have a UPN because we can’t send email if there is no UPN to sent it to.  If the device record has a UPN and was created after the timestamp we stored in SharePoint, the user will receive a mail (sample mail shown later on in this post). To do this add an action and search for “Select” and add it. In the “From” field add the value from the Parse JSON step above, and in the Map section, select the txt icon on the far right then choose userPrincipleName from the dynamic list:

This next step is a cascade of actions so pay close attention please:

  • Add an “Apply to each” action and select the Parse JSON value (just like you did in the Select step above).
  • Now add an embeded “Apply to each” action and add the value from the SharePoint step above.

  • Add an embedded “Condition” action (this is where we compare dates), and in the first box find and select “created” from the SharePoint items and select “is less than” and in the far right box select “enrolledDateTime”:

What I’m doing is comparing the single item created date pulled from SharePoint to the enrollment dates pulled from Intune:

SharePoint item created date

Device enrollment dates

  • In the “If Yes” box, add an action, then search and add “Send an email (V2)”. Then select from the dynamic items to craft a mail. We don’t need anything for “If no”.

The next three steps in the Flow are fairly self-explanatory so I expanded them for reference:

What’s occurring  in the “Apply to each 2” is a SharePoint value is selected from the SharePoint Get items step, then I delete the item. Next step is up to you, all I’m doing is converting the current date/time then adding it to the Title field of a new SharePoint list item, however you can do what you want in the middle step, just make sure the last step creates a single SharePoint list item as the created date needs to be referenced in a previous step in this Flow.

Testing the Flow

Once the steps above are complete, run a test to create an item in SharePoint, then register a device and make sure it shows up in Intune under device, then run another test.  So you’ll run two tests, one to generate the SharePoint item, and other after the device is registered with Intune.

The following is the email Power Automate sends to the end user who enrolled the device:

When you’re ready to move this process into production, delete the manual trigger in the first step and replace it with the Recurrence trigger and run it on the interval that is best for your organization:

That’s it, we fully automated a process by using Power Automate to pull all enrolled device objects from Microsoft Intune, selecting only devices that have a UPN associated, and sending an email to end users who have enrolled their devices since the last time the Flow ran.

Intune, Azure AD, and Zscaler Private Access

Securing the perimeter has become increasingly difficult with more and more services moving to the cloud and users needing, no, expecting, access from their personal devices. The days of relying on the walls of a network to “trust” access are fading fast, and some would say they’re long gone. This is why organizations are using Microsoft technologies to build out zero trust networks where they rely on device and user claims to evaluate access to resource both on and off network. As I’ve written about in the past, security comes in layers, and zero trust encompasses many layers of security behind the scenes.

Over the past few years, Microsoft has worked with many security and management vendors to integrate with Microsoft Intune and other solutions in EMS such as Azure Active Directory.

The following list is just an example of the many technology partnerships Microsoft has in place today.

To keep up to date with Microsoft security partners please visit: https://www.microsoft.com/en-us/enterprise-mobility-security/microsoft-intune?rtc=1

For this month’s post I’ll focus on Intune, Azure Active Directory, as well as a Microsoft security partner, Zscaler, particularly Zscaler Private Access and its integration with Azure AD and Intune.

What is Zscaler Private Access?

According to Christopher Hines, Head of Product Marketing at Zscaler:

“The Zscaler Private Access (ZPA) service provides users with seamless and secure access to private applications without placing them on the network and without exposing apps to the internet. Allowing enterprises to embrace a software-defined perimeter that supports all private apps and environments.”

More details about Zscaler may be found by visiting: : https://help.zscaler.com/zpa/getting-started/what-zscaler-private-access

Before we get started, I want to give special thanks to the following individuals I collaborated with for this post:

    • Tyler Castaldo – Microsoft Program Manager – Intune
    • David Creedy – Senior Product Manager – Web Security
    • Christopher Hines – Head of Product Marketing – ZPA and Zscaler App

Let’s get started

Zscaler SSO Setup

First, we need to set up Zscaler with Azure so we can provide SSO as users access the app. Once the user accesses the the Zscaler App on their device, they’ll be passed through to Azure AD for sign-on.

Setting up Zscaler Private Access (ZPA) requires a few steps so I won’t go through them, however the steps are well documented here: https://docs.microsoft.com/en-us/azure/active-directory/saas-apps/zscalerprivateaccess-tutorial

In addition, Zscaler has also created their own documentation that may be referenced as well:

Adding Zscaler App to Intune for deployment

For this post I focus on iOS and Android. However, Zscaler is also supported on macOS and Windows 10 (more details at the bottom of this post).

After SSO is set up with Zscaler and Azure AD, we now need to add the Zscaler App to Intune for deployment.

Navigate to portal.azure.com or devicemanagement.microsoft.com and select “Client apps -> Apps”

Select “Add” then App Type and from the dropdown select iOS. Search for Zscaler and select “Zscaler App” as shown below. Add the app and assign it to a group for deployment.

For Android, repeat the steps above, however for the “App type” select “Android“. Use Managed Google Play in the console to search for Zscaler, then add and assign the app to a group for deployment.

Note: if you haven’t set up Managed Google Play with Intune yet, you will find details steps on how to do so by visiting: https://docs.microsoft.com/en-us/intune/connect-intune-android-enterprise

When performing a search for “Zscaler” under apps in Intune you should see both assigned apps.

Configuring the Zscaler App using a VPN policy for iOS and app config for Android

Configuring Zscaler Private Access for iOS in Intune is straightforward as Intune has the settings available directly in the Intune adming portal UI as shown below.

Note: the “Organization’s cloud name” is case sensitive and FQDN and key/value pairs are optional, for more details please visit: https://docs.microsoft.com/en-us/intune/vpn-settings-ios#base-vpn-settings.

Select how the VPN will be launched:

Configure additional settings your organization requires to provide access to applications bridged by Zscaler:

For Android, we need to create an app configuration policy and assign it to the Zscaler App we added earlier.

https://docs.microsoft.com/en-us/intune/app-configuration-policies-use-android

Create an app configuration policy by navigating to “Client apps -> App configuration policies”

Select “Add”, provide the policy a name and from the “Device enrollment type” drop-down select “Android”.

Under “Associated app” select the Zscaler App added earlier.

Under “Configuration settings” select “Use configuration designer” from the drop-down and select all the options provided. Select ok to begin configuring the values.

Configure the values based on how your Zscaler environment is configured. In my case, my Zscaler environment is set up in Azure so I utilized the cloud name for the service in Azure as well as the domain my users log into. For username, I selected variable and chose “Partial UPN”.

Once all the settings are configured select “Ok” to complete the setup.

Note: you’ll notice the “deviceToken” value is set to “DummyValue”. This value isn’t needed when Azure AD is used as the identity provider (IdP), however it is needed in the profile, so just add it and type in whatever you like for the value. Also, please note the “Organization’s cloud name” is case sensitive.

After you’re finished with the app config policy, be sure to assign it to the same group you assigned the Zscaler App to.

Client experience

On first launch, the Zscaler App on iOS and/or Android it will redirect to sign-on using Azure AD, however subsequent launches of the Zscaler App will sign-in automatically.

Azure AD Conditional Access

To prevent access to an application Zscaler Private Access is securing access for, we need to create an Azure AD conditional access policy. The Azure AD Conditional Access policy will ensure the device and/or user meets compliance policies (e.g. Intune) before allowing access.

Navigate the Azure Active Directory in the Azure portal and select “Conditional Access”

Provide a name for the policy and under Cloud app add “Zscaler Private Access” and add the Zscaler cloud app used to access resources, i.e. the organization cloud name that points to the app we added earlier. The cloud app I utilize is called Zscaler ZSCloud as shown below.

Select the device platforms to target the Azure AD CA policy, since I’m focusing on iOS and Android in this post, I select iOS and Android from the devices platforms list.

Now grant access if the device is marked as compliant by Intune, enable the policy and save.

Note: additional conditions and access controls may be checked if needed.

If the device is compliant with Intune compliance policies, Zscaler will connect the user to the application. If the device isn’t compliant, Azure AD Conditional Access will block access to the application Zscaler provides access until the compliance issue is remediated.

Note: currently there is an issue with Conditional Access and Android Enterprise where the device is treated as not enrolled.  Zscaler is working through this and we’ll provide an update as soon as the issue is resolved.

Let’s see this in action

I’m testing with my Android device enrolled with Intune under Android Enterprise Device Owner as a fully managed device. The Zscaler Private Access (ZPA) App and ZPA App configuration is automatically deployed.

Intune_Zscaler.gif

Conclusion

In summary we learned how to set up Zscaler with Azure and provide SSO using Azure Active Directory. We also learned how to set up Zscaler Private Access App configuration and app deployment with Microsoft Intune. Finally, we learned how to set up an Azure Active Directory Conditional Access policy to further secure application access with Zscaler based on Intune device compliance.

I hope this post helps you and your organization further secure corporate applications, devices, users, and resources using Microsoft Intune, Azure Active Directory, and Zscaler Private Access. If you’re a Zscaler customer today, go out and give these steps a try.

Appendix

Information on setting up Zscaler for Windows and MacOS

Outlook app configuration – contact field export control

Organizations utilizing the Outlook app on iOS and Android may desire granular control of app behavior such as only allowing certain contact fields to be sync’d with the native contacts app on iOS. Fortunately, Outlook settings are available to further control the Outlook app on iOS and Android.

I’ve worked with organizations who have strict data protection and GDPR requirements and utilizing Intune we were able to protect data from leaking from users’ corporate email to unmanaged apps and storage while allowing limited contact attributes sync’d to the local contacts app so caller ID will show for callers residing in contacts. Some of the restrictions are enforced by the platform (i.e. iOS/Android) while other restrictions are controlled at the app and device layer by Intune.

To learn more about app config with Outlook please visit: https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/outlook-for-ios-and-android/outlook-for-ios-and-android-configuration-with-microsoft-intune#configure-contact-field-sync-to-native-contacts-for-outlook-for-ios-and-android

As you walk through the settings make note of the “Device Enrollment Type” for each configuration setting, e.g. “Managed devices”, “Managed apps”. The device enrollment type corresponds to the Intune “Device enrollment type” setting when adding a configuration policy (see screenshot below). It’s important to understand the differences as there are different settings for different types of profiles and if settings are used for an unsupported profile type, they simply will not deploy to the app. In addition to the contacts settings, there are also account configuration, wearable, and iOS notification settings that can be configured as well.

Let get started

The following example demonstrates syncing only certain contact fields to the local contacts app so the end user will see the caller ID for a contacts for phone numbers when calls are received.

Navigate to the Intune admin portal and select “Client Apps > App configuration policies > Add”

Give the configuration policy a name and select “Managed apps” as the Device enrollment type as I’m pushing this policy via an App Protection Policy.

Select “Associated app” and select Outlook for the platform(s) you’re interested in configuring Outlook for. For “Managed Apps” I recommend using a single policy for iOS and Android to maintain consistency across platforms.

Add configuration settings to configure the app configuration settings for contacts in Outlook as shown below. These are key/value pairs and are documented here: https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/outlook-for-ios-and-android/outlook-for-ios-and-android-configuration-with-microsoft-intune#configure-contact-field-sync-to-native-contacts-for-outlook-for-ios-and-android

I’m only allowing first name, last name, and mobile phone number. If other phone fields are required such as home, office, other, you may want to allow those as well. Note: these fields match up to the existing fields in Outlook contacts and the native contacts app.

Assign the policy to a group of users:

Syncing contacts to the native contacts app

For contacts to show up in the native contacts app, users need to manually select “Save Contacts” in Outlook settings to sync contacts to their device.

Note: if you don’t see “Save Contacts” an Intune App Protection Policy may be blocking contacts sync. To check APP settings install and open the Edge browser and type in: about:intunehelp in the search box and view Intune app status for Outlook. If block contact sync is enabled, it will be set to “1” disabled will be set to “0”. Also, the “Save Contacts” setting cannot be set by policy at this time.

As shown below, only the fields specified in the Outlook configuration policy show up when the contact is accessed from the native contacts app. All other fields are blanked out. Even if I add the additional data to the fields, such as a phone number, the field will show up populated in the native contacts app then disappear when the policy refreshes (the update to the field will retain in Outlook though).

If you continue to see the fields that are blocked, try waiting a few minutes and disabling and re-enabling contact sync in Outlook.

Finally, when the email profile is removed from Outlook so are the sync’d contacts from the native contacts app.

Additional info

For MDM enrolled iOS devices, if contacts do not sync with the native contacts app after going through the steps above, because of certain Apple restrictions, you may need to toggle these settings to “Not configured”. There is a support post on this topic that is worth reading with additional tips: https://blogs.technet.microsoft.com/intunesupport/2018/04/17/support-tip-ios-11-3-and-native-contacts-app/