1

I'm having trouble finding good documentation that explains exactly how the AzureAD accounts are handled in local groups and I'm getting mixed results which makes it hard for me to write a reliable API that gives accurate results for determining group memberships for different types of computer.

This article gives a good overview of possible paths when using the WinNT provider but I'm finding this is not extensive. When a computer is joined to a domain, everything is pretty straightforward. However, when a computer is not joined to domain, I can observe that objects usually have a path that corresponds to the workgroup name and computer name. As an example, the built-in Administrators group usually would have an ADsPath:

WinNT://<workgroup name>/<computer name>/Administrators

So it's usually something like:

WinNT://WORKGROUP/MyComputer/Administrators

If there is an account that is joined to Azure Active Directory, even though the computer itself is not joined to the Azure Active Directory, the account still can appear in various places. For example, if John Doe set up his home computer using johndoe@contoso.com, and the contoso.com is hosted on Azure Active Directory, then John's account will be shown as AzureAD\JohnDoe.

However, that account is not actually known to the local computer. Looking under the computer management, you won't find that user listed under the local users. Assuming that the AzureAD\JohnDoe was the one that was used to set up, it will be found as a member under the local computer's Administrators group.

Enumerating the members of the Administrators group, we can determine that the ADS path of that account is WinNT://AzureAD/JohnDoe. However, that ADS path does not actually work. Attempt to locate the object with that path will return an error, usually this:

Run-time error '-2147024843 (80070035)':

Automation error
The network path was not found. 

However, we can determine the SID of that user and instead use the SID similar to this format:

WinNT://S-1-12-1-123456789-1234567890-1234567890-1223456778

This will return a valid object. However, the class is different; it's now a Domain, not a User as we got when we enumerated the members of a built-in group.

As a consequence, if one creates a new local group and try to add the user interactively, this will fail because the location is set to the computer's name. Using AzureAD\JohnDoe will fail. However, if one adds member to the new local group programmatically, one can use the SID ADs path to then successfully add the same AzureAD account to that group.

When you open again the members of the group via the computer management, it will now show AzureAD\JohnDoe in the UI. This is also a User, rather than a Domain. The ADsPath also is WinNT://AzureAD/JohnDoe, which is still invalid.

As a consequence, it is not possible to use the built-in IsMember method of the ADS group to determine whether an AzureAD account is a member of that local group or not. I determined that it is possible to compare the SID which seems to work and is more reliable. However, the downside is that this approach is very slow and enumerating the group membership, even with short-circuiting when a match is found, is very slow.

I am hoping there is a better method to determine the group membership even for an Azure account on a computer. The API was already working well for handling both the checking for local groups on a workgroup and for domain groups on a domain-joined computer. Azure accounts, however is a new wrench in the machinery.

As far as I know, this is something to do with ADS provider, and thus the specifics on how the data is obtained in which languages doesn't matter so it'd be the same answer whether one uses command prompt, WMI, powershell, or win32 APIs.

this
  • 111
  • 2
  • One can also add a member to a local group using powershell using the form (it doesns't get you much, but you at least do not have to use the SID): `Add-LocalGroupMember -Group Administrators -Member AzureAd\johndoe@contoso.com` – Semicolon Jul 04 '22 at 14:32
  • There are several available workarounds that you can find in this GitHub Issue: https://github.com/PowerShell/PowerShell/issues/2996. While it is in the PowerShell repo, its not strictly a powershell issue. You may find one method there that is more appealing to you than others. – Semicolon Jul 04 '22 at 14:34

0 Answers0