Analysis query to get all members (local and domain) of Windows local groups and the relative status of only local account

I am trying to get an analysis which display the members of some local groups of a computer: we need to list all local ad domain users of each groups and, in case of local user, the relative account status (disabled/enabled)

I started implementing the analysis to get the members of some local groups, as follow:

(item 0 of it & ":" & item 1 of it as string) of (name of it, (if (number of members of it > 0) then (members of it as string) else ("No Members"))) of local groups whose ((name of it contains "Administrators") or (name of it contains "Backup Operators") or (name of it contains "Guest") or (name of it contains "Power Users") or (name of it contains "Replicator") or (name of it contains "Users"))

In this way I get a list as follow:

<group>:<member>

After that I found that there is the BigFix property: "account disable flag of " to get the account status, but I not able to integrate this property in the previous statement in order to display:

<group>:<member>:<account disable status (false/true)>

How can I modify it?

Thanks

1 Like

The problem is that ā€œaccount disabled flagā€ inspector is on type ā€œuserā€, where the data you are getting is ā€œlocal group memberā€, so you essentially need to create a string comparison to find matches between the two inspectors (also, note that the ā€œlocal group name memberā€ will be of format ā€œComputer\userā€, where the name of the user will be ā€œuserā€):

exists ("local group member as string", users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)

Once you ensure that they match, then you keep building on it:

(account disabled flag of item 1 of it as string) of ("local group member as string", users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)

Give this a try:

(item 0 of it & ":" & item 0 of item 1 of it as string & ":" & item 1 of item 1 of it as string) of (name of it, (if (number of members of it > 0) then ((it, (if (exists (it, users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) then ((account disabled flag of item 1 of it as string) of (it, users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) else ("Not Local Account"))) of (it as string) of members of it) else ("No Members", "N/A"))) of local groups whose ((name of it contains "Administrators") or (name of it contains "Backup Operators") or (name of it contains "Guest") or (name of it contains "Power Users") or (name of it contains "Replicator") or (name of it contains "Users"))
2 Likes

You can get the results of groups with no members easily with: (name of it & ":No Members:N/A") of local groups whose(not exists members of it)

Q: (name of it & ":No Members:N/A") of local groups whose(not exists members of it)
A: Access Control Assistance Operators:No Members:N/A
A: Backup Operators:No Members:N/A
A: Cryptographic Operators:No Members:N/A
A: Distributed COM Users:No Members:N/A
A: Event Log Readers:No Members:N/A
A: Hyper-V Administrators:No Members:N/A
A: IIS_IUSRS:No Members:N/A
A: Network Configuration Operators:No Members:N/A
A: Performance Log Users:No Members:N/A
A: Performance Monitor Users:No Members:N/A
A: Power Users:No Members:N/A
A: Remote Management Users:No Members:N/A
A: Replicator:No Members:N/A
A: System Managed Accounts Group:No Members:N/A
T: 10.337 ms
I: plural string

Then to get those with members: (item 0 of it & ":" & item 1 of it & ":" & (account disabled flag of item 2 of it as string | "Not Local Account") ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups

Q: (item 0 of it & ":" & item 1 of it & ":" & (account disabled flag of item 2 of it as string | "Not Local Account") ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups
A: Administrators:_HOST_\Administrator:True

Put it all together:

( (item 0 of it & ":" & item 1 of it & ":" & (account disabled flag of item 2 of it as string | "Not Local Account") ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups ) ; ( (name of it & ":No Members:N/A") of local groups whose(not exists members of it) )

Sometimes it is much easier to have 2 separate logic paths for the different cases than have a single logic path handle the complexity of both.


You can actually measure the performance of these statements for a given system by looking at the execution time without outputting the results themselves by adding number of in front just to hide the results while looking for the approximate execution time:

Q: number of (name of it & ":No Members:N/A") of local groups whose(not exists members of it)
A: 14
T: 9.673 ms
I: singular integer

Q: number of (item 0 of it & ":" & item 1 of it & ":" & (account disabled flag of item 2 of it as string | "Not Local Account") ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups
A: 10
T: 61.234 ms
I: singular integer

Q: number of ( ( (item 0 of it & ":" & item 1 of it & ":" & (account disabled flag of item 2 of it as string | "Not Local Account") ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups ) ; ( (name of it & ":No Members:N/A") of local groups whose(not exists members of it) ) )
A: 24
T: 76.405 ms
I: singular integer

Q: number of (item 0 of it & ":" & item 0 of item 1 of it as string & ":" & item 1 of item 1 of it as string) of (name of it, (if (number of members of it > 0) then ((it, (if (exists (it, users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) then ((account disabled flag of item 1 of it as string) of (it, users) whose ((if (item 0 of it contains "\") then (following text of first "\" of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) else ("Not Local Account"))) of (it as string) of members of it) else ("No Members", "N/A"))) of local groups whose ((name of it contains "Administrators") or (name of it contains "Backup Operators") or (name of it contains "Guest") or (name of it contains "Power Users") or (name of it contains "Replicator") or (name of it contains "Users"))
A: 20
T: 89.279 ms
I: singular integer
1 Like

Thanks to you for the effective help.

We have implemented the final analysis inserting at the beginning the DNS computer name and adding at the end the SID account.

q: (DNS NAME as string & ":" & item 0 of it & ":" & item 0 of item 1 of it as string & ":" & item 1 of item 1 of it as string & ":" & (if (item 0 of item 1 of it as string does not contain "No Members") then (component string of sid of security account ( item 0 of item 1 of it as string)) else "N/A")) of (name of it, (if (number of members of it > 0) then ((it, (if (exists (it, users) whose ((if (item 0 of it contains (COMPUTER NAME as string & "\")) then (following text of first (COMPUTER NAME as string & "\") of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) then ((account disabled flag of item 1 of it as string) of (it, users) whose ((if (item 0 of it contains (COMPUTER NAME as string & "\")) then (following text of first (COMPUTER NAME as string & "\") of item 0 of it) else (item 0 of it)) as lowercase = name of item 1 of it as lowercase)) else ("Not Local Account"))) of (it as string) of members of it) else ("No Members", "N/A"))) of local groups whose ((name of it contains "Administrators") or (name of it contains "Backup Operators") or (name of it contains "Guest") or (name of it contains "Power Users") or (name of it contains "Replicator") or (name of it contains "Users"))
A: COMPNAME.ADNAME.GROUP:Administrators:COMPNAME\Administrator:False:S-1-5-21-4285662607-1493931913-3199868264-500
A: COMPNAME.ADNAME.GROUP:Administrators:SISLAB\Domain Admins:Not Local Account:S-1-5-21-2555079218-486330215-1171134054-512
A: COMPNAME.ADNAME.GROUP:Administrators:KROLAB\guAmministratoriServer:Not Local Account:S-1-5-21-3358638981-845373695-1819800672-1632
A: COMPNAME.ADNAME.GROUP:Administrators:KROLAB\guOperatoriServer:Not Local Account:S-1-5-21-3358638981-845373695-1819800672-1629
A: COMPNAME.ADNAME.GROUP:Administrators:SISLAB\sa_TIIEM-Svil:Not Local Account:S-1-5-21-2555079218-486330215-1171134054-1604
A: COMPNAME.ADNAME.GROUP:Administrators:SEDLAB\ggAmministratoriIEM:Not Local Account:S-1-5-21-2949037896-3013779244-722423975-21094
A: COMPNAME.ADNAME.GROUP:Administrators:SEDLAB\ggGestoriIEM:Not Local Account:S-1-5-21-2949037896-3013779244-722423975-21095
A: COMPNAME.ADNAME.GROUP:Administrators:SEDLAB\adm_gs00630:Not Local Account:S-1-5-21-2949037896-3013779244-722423975-23111
A: COMPNAME.ADNAME.GROUP:Backup Operators:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Distributed COM Users:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Guests:COMPNAME\Guest:True:S-1-5-21-4285662607-1493931913-3199868264-501
A: COMPNAME.ADNAME.GROUP:Performance Log Users:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Performance Monitor Users:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Power Users:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Remote Desktop Users:SEDIRLAB\GS00630:Not Local Account:S-1-5-21-2949037896-3013779244-722423975-1179
A: COMPNAME.ADNAME.GROUP:Replicator:No Members:N/A:N/A
A: COMPNAME.ADNAME.GROUP:Users:NT AUTHORITY\INTERACTIVE:Not Local Account:S-1-5-4
A: COMPNAME.ADNAME.GROUP:Users:NT AUTHORITY\Authenticated Users:Not Local Account:S-1-5-11
A: COMPNAME.ADNAME.GROUP:Users:SISLAB\Domain Users:Not Local Account:S-1-5-21-2555079218-486330215-1171134054-513
T: 107.070 ms

I find this relevance very hard to parse. Do you want the SID of the account or the SID of the group at the end? (Iā€™m assuming the SID of the user)

Iā€™d say this is the most efficient and flexible way to achieve that:

( ( concatenations ":" of (dns name;item 0 of it;item 1 of it;(account disabled flag of item 2 of it as string | "Not Local Account"); (component string of sid of item 2 of it | "NoSID") ) ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups )

I think it actually makes sense to have a separate property for an empty group vs one with members, but you can combine it into one if needed.

( ( concatenations ":" of (dns name;item 0 of it;item 1 of it;(account disabled flag of item 2 of it as string | "Not Local Account"); (component string of sid of item 2 of it | "NoSID") ) ) of (names of it, (it as string) of members of it, users) whose( ( "\" & name of item 2 of it) is contained by item 1 of it) of local groups )

The above doesnā€™t show the members that are domain groups or domain users.
Are we missing anything?

Yes, your whose() filter is limiting the results to only display the users who are members of the group. In the case of a Domain Group who is a member of the local group, the Domain Group is not a ā€˜userā€™ so does not match your whose(l filter