If somebody would have to build the users and groups of the whole galaxy into a single AzureAD, group memberships would play a big role. For an alien it would then be easy to understand who is member of what part of the galaxy. Lets take a little – not too serious – example:
How Aliens look into the Galaxy via a REST-API
Left hand is the Alien, using the MS Graph REST-API and has at least read-access to the Azure AD (by some Application with the Global-Reader role assigned).
Righ-hand-side is the Galaxy with its president Zaphod. Solaris (our system) has a lot of members, for example we take Venus, a person on the Venus planet. And finally there is Earth with one person we picked out called Arthur.
How this structure is build into the Galaxies AzureAD.
First we have the „Galaxy“ group with Zaphod and the „Solaris“ group as member.
Next we have the Solaris group with Venus and Earth as members.
And pretty much the same way Earth, and Arthur.
And now lets play Alien and query the galaxy!
Our Alien uses PowerShell, and frankly i sometimes feel like an alien using PowerShell, as many admins still click around in the GUI ;-).
But first leks create an Access Token and an authorization header.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# All GUIDS ARE CHANGED, so please replace with your own $TenantId = 'a55555c7-9fb3-4031-a720-cd9f9c430c57' $Appid = 'c90b651c-a28d-4997-9c5d-6e3b4d6c98b7' $ClientKey = '---areallysecretkey---' #Login Token request für Graph $url = "https://login.microsoftonline.com/$tenantId/oauth2/token" $resource = "https://graph.microsoft.com/" $restbody = @{ grant_type = 'client_credentials' client_id = $AppID client_secret = $ClientKey resource = $resource } Invoke-RestMethod -Method POST -Uri $url -Body $restbody -outvariable Token|out-null # Security header $baseUrl = 'https://graph.microsoft.com/v1.0' $header = @{ 'Authorization' = "$($Token.token_type) $($Token.access_token)" 'Content-type' = "application/json" } |
Ok, now we have a header with a proper token and access to the Graph API. Now lets define the object-IDss for our galaxy-objects (you get them from the Azure Portal ==> Groups ==> Object ID, same for users.
1 2 3 4 5 6 7 8 9 |
# Group object id´s $Galaxy = '765aac03-02fa-4790-9e7e-e0d26bf13b6b' $Solaris = 'b20ca90e-43eb-41e0-9423-c8b5a2d89665' $Earth = 'aa346574-a8eb-4d8c-9cd1-8664690e438e' # User object id´s $Zaphod = 'b45994ba-01c1-40fd-955e-2aa1a7bcab1e' $Venus = '7e60cff7-b1e0-4fgf-8f3b-b1db377d471b' $Arthur = '54cf869e-bd76-43d1-aa42-6acdfc0c46f6' |
Is Arthur from Earth ?
Now comes the fun part. We use the „checkMemberGroups“ path from the MS Graph API to find out if Arthur is from earth (maybe something really interesting for Vogons …;-))
1 2 3 4 5 6 7 8 9 |
# Prepare the REST-API call $url = $baseUrl + '/users' + "/$Arthur" + '/checkMemberGroups' ## Create Array with groups to check membership against $groupIds = @($Earth) $gidBody = @{groupIds = $groupids}|ConvertTo-Json ## and now call the API $checkmembergroups = Invoke-RestMethod -Method POST -headers $header -body $gidBody -Uri $url |
If Arthur is a member, the API returns the groups object-id, which we can then compare and make a simple output via If/else.
1 2 3 4 5 6 7 |
foreach ($groupid in $groupIDs) { if ($checkMemberGroups.value -eq $groupid) { "is member of $groupid" } else { "not found in $groupid" } } |
For Arthur this emits „is member of …“
Is Venus from Earth ?
Guys and girls, especially all which are in a long-term relationship, we all know the answer …
1 2 3 4 5 6 7 8 9 |
# Replace $Arthur with $Venus $url = $baseUrl + '/users' + "/$Venus" + '/checkMemberGroups' ## Create Array with groups to check membership against $groupIds = @($Earth) $gidBody = @{groupIds = $groupids}|ConvertTo-Json ## and now call the API $checkmembergroups = Invoke-RestMethod -Method POST -headers $header -body $gidBody -Uri $url |
… not found … so true 🙁
Is Arthur part of the Galaxy ?
Yep, thats the really interesting question and the reason why we do nested groups. Arthur is part of Earth, Solaris and the Galaxy as a whole.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$url = $baseUrl + '/users' + "/$Arthur" + '/checkMemberGroups' ## Create Array with groups to check membership against $groupIds = @($Galaxy) $gidBody = @{groupIds = $groupids}|ConvertTo-Json ## and now call the API $checkmembergroups = Invoke-RestMethod -Method POST -headers $header -body $gidBody -Uri $url foreach ($groupid in $groupIDs) { if ($checkMemberGroups.value -eq $groupid) { "is member of $groupid" } else { "not found in $groupid" } } |
And – without question -he is !
Ask for multiple group memberships
To analyze where the group memberships breaks, the REST-API allows us to ship muliple group-ID´s and as for membership. Lets try this for venus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# $venus $url = $baseUrl + '/users' + "/$venus" + '/checkMemberGroups' ## Multiple groups in groupIds $groupIds = @($Galaxy,$Solaris,$Earth) $gidBody = @{groupIds = $groupids}|ConvertTo-Json ## and now call the API $checkmembergroups = Invoke-RestMethod -Method POST -headers $header -body $gidBody -Uri $url foreach ($groupid in $groupIDs) { if ($checkMemberGroups.value -eq $groupid) { "is member of $groupid" } else { "not found in $groupid" } } # result: is member of 025aac03-01fa-4790-9e7e-e0d26bf13b6b is member of b20ca80e-43eb-41e0-9423-c8b5a2d89693 not found in aa346574-a8eb-4d8c-9cd1-8664690e668e |
Summary
Nested groups are great and the MS-Graph API allows us to query group membership easily. Hope that helps you in some way!
Roman
Photo by Jeremy Thomas on Unsplash for the headure picture!