Azure Active Directory guest users really simplify the process to collaborate with external users. Although keeping a good governance on guest accounts can become quite a challenge. The two biggest challenges I often observe are: “Who invited that guest user?” and “Does this guest user still need access to our infrastructure?”. Inspired by a recent post of Thomas Kurth regarding Azure AD Guest Account - Governance and Cleanup I also developed a solution which comes quite close to an “Azure AD Access review” like user experience.
Notable features # The ‘Manager’ attribute of your guest users get’s automatically populated with the identity of the inviter All Azure AD app registration information is stored in Azure Key Vault Almost zero touch deployment with ARM templates You can integrate existing guest users into this solution by populating the manager attribute in Azure AD You can configure the approval frequency for guest accounts Approval frequency respects last approval date for each guest account Architecture # The solution leverages function of:
Azure Logic App
Microsoft is working on a new set of PowerShell modules grouped under the umbrella of Microsoft.Graph that will (hopefully) cover all the Microsoft Graph resources available. I’ve already used some of them for my Conditional Access Documentation Script and thought they have some notable features worth sharing.
Advantages and changes # The Microsoft Graph modules use the new Microsoft Authentication Library (MSAL) instead of the old Azure AD Authentication Library (ADAL). The MSAL library in the modules implements a token cache which persists the access and refresh tokens.
MSAL caches a token after it has been acquired. Application code should try to get a token silently (from the cache), first, before acquiring a token by other means. - Microsoft docs
The token cache persists system reboots and re-opening PowerShell sessions. The module allows you to obtain tokens either for authentication via client credentials (certificate only) or device code flow.
Furthermore, the new modules support a really broad spectrum of available entities on the Graph API. From an EM+S perspective this means for example: groups, users, identity protection, conditional access, and some of the Intune app management commands are also starting to appear.
Just be aware that the modules are currently published as pre-release. If you encounter any issues share them with the development team on GitHub and submit issues or even better contribute directly to the project.
For some recent Microsoft Graph scripts I wanted to translate some Azure AD Object ID / GUID entries to their respective display name. The array with the GUID’s contained already some readable text. Of course I only wanted to translate the GUID entries with according Graph API requests. Otherwise the Graph requests would fail. Google offered only some fancy regex functions and helpers but I had that .NET function in my mind which looks much nicer compared to whatever regex pattern that I don’t understand.
"applications": { "includeApplications": [ "797f4846-ba00-4fd7-ba43-dac1f8f63013", "Office365" ] } So I needed a way to test a string for a valid GUID and only invoking the Graph calls for GUID values.
Matching a GUID with a regex # I found the following regex on this site:
"d815c3bc-9c49-4633-9d16-29808242d063" -match '(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$' Matching a GUID with the .NET method # Instead of the complex regex we can invoke this nice .NET member method which returns true or false based on the input:
[guid]::TryParse("d815c3bc-9c49-4633-9d16-29808242d063", $([ref][guid]::Empty)) I guess that’s much more convenient.
Helper Function # Here’s a helper function which can be used in PowerShell scripts:
Documenting things sucks. If it involves a lot of klick(edi klack klack) in portals and copying information around even more. But there’s hope. And it’s called automation. For the Intune part Thomas Kurt did already an awesome job with his IntuneDocumentation. Now the Modern Workplace Concierge is ready to help you with documenting your Conditional Access configuration. I promise you: we will get through this within under 15 minutes! Afterwards you can make an impression on your fellow Enterprise Mobility teammates.
What’s inside? # A Conditional Access policy is returned by the Microsoft Graph API in the following JSON representation:
{ "id": "714b5737-5f13-415e-bf96-d659f3a5928e", "displayName": "PROD - Admin protection - Azure management: Require MFA", "createdDateTime": null, "modifiedDateTime": null, "state": "enabled", "grantControls": { "operator": "OR", "builtInControls": [ "mfa" ], "customAuthenticationFactors": [], "termsOfUse": [] }, "conditions": { "signInRiskLevels": [], "clientAppTypes": [], "platforms": null, "locations": null, "deviceStates": null, "applications": { "includeApplications": [ "797f4846-ba00-4fd7-ba43-dac1f8f63013" ], "excludeApplications": [], "includeUserActions": [] }, "users": { "includeUsers": [ "All" ], "excludeUsers": [], "includeGroups": [], "excludeGroups": [ "04988d96-ad01-4569-9aee-a199a1cb4f8e" ], "includeRoles": [], "excludeRoles": [] } }, "sessionControls": null } That’s not really human readable. Especially the object id’s (32 character UUIDs) make it difficult to guess to which users or apps a policy is assigned. But an API has definitely other goals than showing pretty formatted reports.
If you manage multiple Intune tenants with your Azure AD account (invited as guest in the foreign tenant) we need a way to specify the tenant id we want to connect. Otherwise you will land in your home-tenant every time. This posts shows you how to accomplish that with the Intune PowerShell SDK.
If we have a look at the default Graph settings in a PowerShell session with the Intune PowerShell SDK you will notice that all authentication requests will land on the /common endpoint.
Get-MSGraphEnvironment AuthUrl : https://login.microsoftonline.com/common ResourceId : https://graph.microsoft.com/ GraphBaseAddress : https://graph.microsoft.com AppId : d1ddf0e4-d672-4dae-b554-9d5bdfd93547 RedirectLink : urn:ietf:wg:oauth:2.0:oob SchemaVersion : v1.0 To connect to a specific tenant we need to update the AuthUrl to contain the tenant id or any registered domain name of the target tenant before connecting:
Update-MSGraphEnvironment -AuthUrl "https://login.microsoftonline.com/nicolonsky.ch" Afterewards you can connect to Microsoft Graph as usual:
Connect-MSGraph ``` Happy Microsoft Graph-ing with multiple tenants.
This post has the intention to give you an overview and starting point to automate things with the Microsoft Graph API and PowerShell. While having the focus on Intune and EM+S but the basics are also valid for other Microsoft services.
The world is changing and so are you? # When talking about automation most people only think about some PowerShell code and scheduled tasks running on whatever box in an environment. But technology regarding Microsoft services and it’s automation possibilities have definitely evolved quickly. Automation can now be done with basically any scripting or programming language because Microsoft offers us the Microsoft Graph API. Although API (application program interface) sounds more like a developer term engineers should better get used to consuming API’s. As more and more services can be consumed as SaaS API’s are mostly offered for further data processing and automation.
Microsoft Graph API # Microsoft describes it’s own Graph API as “Microsoft Graph is the gateway to data and intelligence in Microsoft 365”. Most of the API’s out there are built according the RESTful definition. A RESTful, also called REST API should implement the following operations (HTTP methods) to work with data:
As you might have noticed I have been doing quite a lot of automation stuff with Microsoft Graph for Intune and Azure AD. My preferred way to run PowerShell scripts which need to run on a regular basis is to use Azure automation. Unfortunately the official “Intune-PowerShell-SDK” does not support authentication with a client certificate. Therefore I updated the module and will show you how to use it with Azure automation.
Why I don’t like client secrets # Azure automation brings us service principals (run as accounts) which simplify the access to Azure resources by providing an Azure AD app registration and certificates to authenticate against Azure AD. This provides more security and prevents the risk from having client secrets stored as plain text in scripts. Going with a client secret when having a nice certificate based authentication solution in place feels like making a step-backwards for me. This was the main reason why I decided to “upgrade” the Intune-PowerShell-SDK to support certificate based authentication.
Why I love the Intune-PowerShell-SDK # This PowerShell SDK provides nice Cmdlets to do any kind of automation with Microsoft Graph, not only limited to Intune because it offers a helper cmdlets like:
After you have uploaded a PowerShell script to the Intune portal you won’t be able to view the script or its content. Therefore things become complicated when an Intune tenant is managed by multiple admins and someone wants to update or review a script. In addition to the unknown script content things can go from bad to worse if you can’t find the script anymore. Fortunately we can recollect our PowerShell scripts directly from the Microsoft Graph API.
Taking advantage of the Intune-PowerShell-SDK # Install the Intune-PowerShell-SDK Consent MS Graph App registration if not done yet (uses default Microsoft Intune PowerShell App with ID: d1ddf0e4-d672-4dae-b554-9d5bdfd93547 ) Execute the snippet below Retrieve device configuration - PowerShell scripts # Final words # This was more a minimalistic self-serving post instead of a good explained one but it hopefully helps you if in need to export your PowerShell scripts in Intune without reinventing the wheel.
A colleague recently asked me how to access the Microsoft Graph API using PowerShell without specifying his user account or credentials. So here’s a little post about the required configuration to authenticate against the OAuth 2.0 endpoint of Azure AD with an app registration. This is especially useful for automation services like Azure automation.
At the end of this post you’ll find a PowerShell template.
Gather application information # Create a new client secret for your app and note down the following values:
Client Secret Application ID (client ID) Directory ID (tenant ID) Azure AD App registration ## PowerShell code Request authentication token # In order to use the Graph API we need an authentication token. The information we gathered before is now sent to the Azure AD OAuth 2.0 endpoint.
https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token In the request supply a body with the following content:
$body=@{ client_id="8f9f420d-606c-4e13-889e-837072dbfb42" client_secret="BlaBlaExampleSecret" #Generated secret scope="https://graph.microsoft.com/.default" grant_type="client_credentials" } The scope and grant_type are required attributes. A full example looks like:
$body=@{ client_id="8f9f420d-606c-4e13-889e-837072dbfb42" client_secret="BlaBlaExampleSecret" scope="https://graph.microsoft.com/.default" grant_type="client_credentials" } $tenantId="7955e1b3-cbad-49eb-9a84-e14aed7f3400" Invoke-WebRequest -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -Method Post If everything works we receive an access token object as HTML 200/ok response: