Assigning PIM Azure RBAC permissions using Terraform and ARM template

Currently, Terraform does not support eligible assignments of permissions in Azure RBAC, and only active assignments using the azurerm_role_assignment resource. Continue reading if you want to be able to assign your eligible assignments using ARM or Terraform (Terraform willl use the ARM template).

Continue reading “Assigning PIM Azure RBAC permissions using Terraform and ARM template”

Getting the Azure AD Connect version using API

Finally the Azure AD Connect version is available through the Azure Portal:

But I am more interested in getting this using an API, as I am checking things towards customer tenants. Looking at the API calls behind the Azure Portal, we can find that it is using some endpoints from

Step 1 – Getting the required access token

You can use the well known 1950a258-227b-4e31-a9cf-717495945fc2 app id with ROPC to get an access token as follows, only username and password required:

$secrets = @{
    username = ""
    password = "MyPassword"

# Create uri and body - AAD graph (deprecated)
$uri = "{0}/oauth2/token" -f $secrets.tenant
$body = "resource={1}&password={0}" -f [System.Net.WebUtility]::UrlEncode($secrets.password), $secrets.username

# Get access token and build header
$token = $null
try {
    $token = Invoke-RestMethod $uri -Body $body -ContentType "application/x-www-form-urlencoded" -ErrorAction SilentlyContinue
} catch {
    Write-Error "Exception when getting AAD access token" -Exception $_

if($token.access_token) {
    $Global:HeadersForAzure = @{Authorization = "Bearer $($token.access_token)"}
} else {
    Write-Error "Unable to retrieve access token for"

Step 2 – Getting the latest actual version from Github

This step is not really crucial, but you can easily fetch the latest version from the Azure AD Connect version history, in order to compare to your tenant:

# Get latest version from Github
$VersionHistory = Invoke-RestMethod ""
$_LatestVersion = $VersionHistory -split "`n" | 
    Where-Object {$_ -match "^## [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"} |
    ForEach-Object {$_ -replace "## "} |
    Sort-Object | 
    Select-Object -Last 1

if($_LatestVersion -notmatch "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$") {
    New-PolicyResult -Policy $Policy -Status "Failed" -StatusDetail "Unable to determine latest version of Azure AD Connect"

$LatestVersion = [Version] $_LatestVersion

Step 3 – Working with the API

Now we are ready to work with the API. Remember, this is an undocumented API, and it is prone to change without notification from Microsoft:

# Get AAD Connect Health service
$PremiumCheck = Invoke-RestMethod -Uri '' -Headers $Global:HeadersForAzure

if(!$PremiumCheck.Value) {
    throw "Unable to get Azure AD Connect configuration from"

# Check Azure AD Connect status being healthy
if($PremiumCheck.value[0].health -ne "Healthy") {
    throw "Azure AD Connect service not healthy"

# Get all servers providing the Azure AD Connect service
$ServiceMembers = Invoke-RestMethod -Uri "$($PremiumCheck.value[0].serviceName)/servicemembers?api-version=2014-01-01" -Headers $Global:HeadersForAzure

# Process servers, checking version, health and version
$ServiceMembers.value | ForEach-Object {
    if(([Version] $_.osVersion) -lt ([Version] "10.0.14393.0")) {
        throw "Server $($_.machineName) running too old operating system Windows build $($_.osVersion)"

    if($_.Status -ne "Healthy") {
        throw "Server $($_.machineName) is not healthy, according to Azure AD Connect Health"

    $ServiceConfiguration = Invoke-RestMethod -Uri "$($PremiumCheck.value[0].serviceName)/servicemembers/$($_.serviceMemberId)/serviceconfiguration?api-version=2014-01-01" -Headers $Global:HeadersForAzure

    if(([Version] $ServiceConfiguration.version) -lt $LatestVersion) {
        throw "Server $($_.machineName) is running version $($ServiceConfiguration.version) of Azure AD Connect, which is not the latest ($LatestVersion)"

This API might be different in a few weeks, which means the example will stop working, but that’s life 🙂

Automating certificate rollover for Azure AD applications using Azure Functions and KeyVault

There are several documentation pages on on managing application registration certificate rollover, including several github repos from Microsoft, all of which are either using a silly approach with high privileged user account (Global Admin, Application Admin, etc) or does not delve into details on how to solve the issue with least privilege and in a proper automated fashion when using KeyVault.

In this post I will try to document a few of the things I have experienced while implementing this using the addKey Graph endpoint.

Continue reading “Automating certificate rollover for Azure AD applications using Azure Functions and KeyVault”

Nudging users to adopt Microsoft Authenticator using registration campaigns

As usual when a new Microsoft Graph endpoint is released, I do some digging using Graph Explorer. Not rocket science, but some times I find very interesting stuff, and this time I have found something.

Let’s say you have 1000 users curretly using SMS for Multi-Factor Authentication, and you want to get them to use the Microsoft Authenticator app instead. What do you do? Do you send out emails, checking the current rollout status using the microsoftAuthenticatorAuthenticationMethod endpoint of each user? Sure, today you do, but there is a secret feature available that some time in the future will help you out. Registration campaigns!

Continue reading “Nudging users to adopt Microsoft Authenticator using registration campaigns”

Creating a user and assigning it to an Azure AD role using Microsoft.Graph PS Module

Going forward, the Azure AD PowerShell Module will not be updated, and Microsoft has stated that it is the Microsoft.Graph PowerShell Module that will be used. This makes sense, as this is auto-generated based on the Microsoft Graph Odata, not requiring Microsoft to maintain several things. However, right now, some of the PowerShell verbs are not really following best practices. Anyway, here is how to do some simple things 🙂

Continue reading “Creating a user and assigning it to an Azure AD role using Microsoft.Graph PS Module”

Azure AD CA Authentication Context, a look a tokens

Azure AD Conditional Access has been quite powerful for a long time, but just got way better with the new authentication context feature. Authentication context is essentially a new way to scope conditional access policies, where instead of targeting an application, you target a context, such as “High security operations” or “Operations requiring consenting to terms of use”. Using the authentication context, you can split your applications into several assurance levels, each being targeted by a separate set of CA policies.

Let’s have a look at the tech first, with tokens and stuff.

Continue reading “Azure AD CA Authentication Context, a look a tokens”

Script for determining unused distribution groups in Exchange Online

A common problem when creating just about any resource in Active Directory, Exchange Online, Azure AD, SharePoint, etc. is life cycle. I see so many customers that have no control over their distribution groups. This is a script that you can use to determine which if your distribution groups are in use, and which are not, by looking at the message trace for the last 90 days.

Continue reading “Script for determining unused distribution groups in Exchange Online”

Using Microsoft Graph to get all guests from Azure AD, including those with userType set to “Member”

Shortest blogpost that will ever be on this blog. Here is a url you can use to get all guests from your Azure AD, including those you have set userType to “Member” for, for different reasons:$filter=creationType eq 'Invitation' or userType eq 'Guest' or externalUserState eq 'Accepted' or externalUserState eq 'PendingAcceptance'