All posts by JosL

Managed Sites.Selected permissions

Of course you did not give your service principal or managed identity Sites.ReadWrite.All right? Right?

Ok, well, if you did, I can imagine, since there is no GUI for it and having to look up site ID’s, MI/SPN’s GUID’s and then executing Graph queries is quite the hassle!

So I added a small feature to SPNRoleMgr that makes this a 100% GUI workflow directly in your browser (no installs, no dependencies!).

/tools was built mainly for myself, but you are more than welcome to use it to make your life easier (and please get rid of sites.readwrite.all!)

Replacing MemberOf in Entra after it is deprecated

Microsoft is phasing out the memberOf option in Entra Dynamic Groups, in November.

https://learn.microsoft.com/en-us/entra/identity/users/groups-dynamic-rule-member-of

This was in preview, but thousands upon thousands of tenants are of course using this in production. Microsoft thus may delay, but in either case, this called for a replacement. A good plan and Claude to the rescue!

A simple azure runbook you can plug and play into your environment, readme and code are here:

https://github.com/jflieben/assortedFunctionsV2/tree/main/EntraMemberOfSync

It basically completely replaces this functionality in Entra 🙂

Example of output of the runbook:

Bypassing the IMDS cache

The IMDS service allows retrieving tokens for e.g. the Graph API, assuming your managed identity has permissions for it.

But what if you forgot to assign permissions? If you already requested a token, you’ll have to wait an hour because IMDS caches its responses, and there is no documented way to bypass the IMDS cache.

By digging into some old MS modules, I accidentally discovered an undocumented parameter you can add to our IMDS call, which immediately mints a new token. Imagine my surprise, no idea why this isn’t documented as it is useful in all kinds of rollout or escalation scenario’s!

Anyway, to bypass the cache, add bypass_cache=true to your GET params! Example:

http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=$($resource)&bypass_cache=true

DriftMaester 1.3.0

With Maester 2.2, we now finally have Sharepoint support and tests! And of course much more, but that’s what stood out most to me. (legacy active directory just makes me feel dirty).

So, DriftMaester also needs to handle these new permissions and has the new pnp module dependency! Time to update 🙂

DriftMaester auto updates, but it doesn’t have permissions to increase its own permissions. So, for whoever wants to leverage the new tests, run this quick oneliner in Azure Shell!

iex ((Invoke-WebRequest -UseBasicParsing 'https://raw.githubusercontent.com/jflieben/DriftMaester/main/Update-DriftMaesterPermissions.ps1').Content)

You can also run the full GUI again as it is a fully idempotent install (overwrite without delete):

iex ((Invoke-WebRequest -UseBasicParsing 'https://raw.githubusercontent.com/jflieben/DriftMaester/main/Install-DriftMaester.ps1').Content)

The full changelog of 1.2.0 to 1.3.0 is:

  • SharePoint Online support: the installer grants the managed identity the SharePoint Sites.FullControl.All application role, and the invoke runbook connects PnP.PowerShell to the tenant admin endpoint with that managed identity so the Maester SharePoint Online tests run unattended.
  • Reports now lead with the number of passed tests instead of the score percentage as this is more valueable when new tests are added
  • Fixed the ORCA tests failing with “Cannot find type [PolicyInfo]”. Maester is now imported at script scope in the invoke runbook, because its manifest loads the ORCA class definitions through ScriptsToProcess, which only defines them in the scope that called Import-Module.
  • The installer now reuses the Azure sign-in for Microsoft Graph by passing an Az-issued Graph token to Connect-MgGraph, so the admin signs in once instead of twice.
  • Centralized permissions and added a permissions reconciliation script (Update-DriftMaesterPermissions.ps1) that automatically adds new permissions and can be executed lightweight in Azure Shell

M365AutoRevocate

Offboarding has always been an interesting case, and one I rarely see customers do 100% right. The will is there, often focused on keeping access to data or reclaiming licenses.

But execution is a whole different world. Automation for onboarding often exists, offboarding rarely, and if it exists, it is usually still triggered manually, and more often than not only for managed accounts (admins, guests, service accounts etc are totally forgotten), and then what is actually done upon offboarding?

Microsoft Graph has an option to subscribe to changes, specifically for user objects. This means we can listen to deactivation, idle (x days inactive) or deletion events and act accordingly. E.g. unshare onedrive, notify a manager of flows and powerapps or teams the user still owns, reclaim licenses, disable upon inactve, etc etc.

So I co-wrote a little PowerShell solution, of course perfectly based on best practises around MI auth, least privileges and assume breach.

It lets you configure WHAT (loads of things, expandable) to do WHEN (inactive, delete, deactivate), and runs at almost no cost in your own azure subscription, as usual, open source and a oneliner to install: https://github.com/jflieben/M365AutoRevocate