Creating a group of Buttons from Get-ADGroup list

I’m trying to build a widget that will allow a user to input two usernames (New User and Manager) that will pull the Managers groups and then display a group of buttons with those groups. I feel like I’m close but I’ve hit a point where there is no error it just doesn’t load anything after hitting submit.

Current Code:

New-UDCard -Title "Adding Users to Groups" -Content {
    New-UDInput -Title "Enter New User and Manager" -Endpoint {
          param($newusr, $manager)
        $strDomn = "MYDOMAIN.local"
        $objCurrDomn = New-Object System.DirectoryServices.DirectoryEntry             
        $objUsrMngr = New-Object System.Security.Principal.NTAccount($strDomn, $manager)
        $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
        $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
        $grpstr = @()
        foreach($grpname in Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -Property Name){
            $grpstr += $grpname               
        }   
        New-UDCard -Title "Select Groups to Add New User" -Content {
            for($i=0; $i -lt $grpstr.Length;$i++){
                New-UDButton -Text $grpstr[$i]
            }

        }
                
    }
}

It looks as if the nested New-UDCard statement is failing currently without any error. I’ve tried setting it up as a New-UDInputAction and got similar results. I’m stumped at this point, anyone ever run into an issue like this?

@aggiebeckett hey there. I haven’t actually sat down to look at all of the code in its entirety but one thing I did noticed is the Select-Object -Property Name. Did you mean to do that or did you just want the actual string value of the name property? Because if that’s is the case, it should be Select-Object -Expand Name. Just my quick two cents.

@nicoeat614 The code you provided me literally only needed to add one more New-UDInputField and the script ran perfectly. Thank you so much for looking at this and helping me solve it.

Here is the changed code:

New-UDInput -Title "Adding Folder Group Membership - Based on Dept." -Content {
    New-UDInputField -Type textbox -Name 'Manager' -Placeholder "Enter Manager NetID"
    New-UDInputField -Type textbox -Name 'New USer' -Placeholder "Enter New Users NetID"
} -Endpoint {
            param($newusr, $manager)   
             $strDomn = "MYDOMAIN.local"
             $objCurrDomn = [System.DirectoryServices.DirectoryEntry]::new()             
             $objUsrMngr = [System.Security.Principal.NTAccount]::new($strDomn, $manager)
             $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
             $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
              [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name            
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] }
                                         } )
                                    }

Great catch on piping the Get-ADGroup straight into an array. That helped the runtime significantly. Next challenge is to build an onclick for each button that will take the $newusr variable and add them to that security group in AD.

Thanks again! I was definitely stumped on this one for the better part of two days.

1 Like

@aggiebeckett I’m glad that I was able to provide some help. As far as adding the onclick handler for each button that will take the new user variable, this is what I think you might be trying to do. Again, I could be most likely off and I don’t have a test AD environment to try this so no promises lol!

Here’s the code:

New-UDInput -Title "Adding Folder Group Membership - Based on Dept." -Content {
    New-UDInputField -Type textbox -Name 'Manager' -Placeholder "Enter Manager NetID"
    New-UDInputField -Type textbox -Name 'NewUser' -Placeholder "Enter New Users NetID"
} -Endpoint {
            param($newuser, $manager)  
             $strDomn = "MYDOMAIN.local"
             $objCurrDomn = [System.DirectoryServices.DirectoryEntry]::new()             
             $objUsrMngr = [System.Security.Principal.NTAccount]::new($strDomn, $manager)
             $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
             $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name            
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] -OnClick ( New-UDEndpoint -Endpoint {
                             Add-ADGroupMember -Identity $ArgumentList[0] -Members $ArgumentList[1]
                                                        } -ArgumentList @($grpstr[$i], $newuser))
                                                    } 
                                         } )
                                    }

A few things. I believe that the "New User" for the second InputField needs to be changed to "NewUser". The same for $newusr variable to $newuser, according to the custom inputs section in the gitbooks documentation.

Also, speaking from an Active Directory perspective, the client needs to be aware that the text entered for either new user or manager needs to be a samaccountname or a distinguishedname (most common acceptable values for the -Identity and -Members parameters) unless you are planning on doing some filtering on the back end.

1 Like

@nicoeat614 Thank you for pointing out those issues with my inputs. I’ve fixed everything you suggested. But I’m having issues getting the OnClick Endpoints to actually add anyone to the group specified. I noticed after trying it the Add-ADGroupMember way you suggested that my initial array ($grpstr) was only pulling the Name property and that was giving me an error when trying to add the user to the specified group. So I’ve built another array that is pulling the DistinguishedName property now and now the script runs perfectly without error, but it’s still not adding the user to the specified group.

So I tried a different method with DirectoryServices.DirectoryEntry to add but got the same results, unfortunately.

Mind looking over my code and seeing if I’m missing anything obvious. For the life of me I feel like this should be working but it’s not…

New-UDInput -Title "Adding Folder Group Membership - Based on Dept." -Content {
    New-UDInputField -Type textbox -Name 'Manager' -Placeholder "Enter Manager NetID"
    New-UDInputField -Type textbox -Name 'NewUser' -Placeholder "Enter New Users NetID"
} -Endpoint {
            param($newuser, $manager)   
             $strDomn = "MYDOMAIN.local"
             $objCurrDomn = [System.DirectoryServices.DirectoryEntry]::new()
             #Manager             
             $objUsrMngr = [System.Security.Principal.NTAccount]::new($strDomn, $manager)
             $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
             $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             #NewUser
             $objUsr = [System.Security.Principal.NTAccount]::new($strDomn, $newuser)
             $strSIDusr = $objUsr.Translate([System.Security.Principal.SecurityIdentifier])
             $strusr = "CN=" + $strSIDusr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name
             [array]$fgp = Get-ADGroup -filter {name -like "*" -and member -eq $strMngr} | Select-Object -ExpandProperty distinguishedName          
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] -OnClick(
                            New-UDEndpoint -Endpoint {
                                $group = New-Object DirectoryServices.DirectoryEntry("LDAP://$ArgumentList[0]")
                                [void]$group.member.Add("<SID=$strSIDusr>")
                                $group.CommitChanges()
                                $group.Close()
                                #Add-ADGroupMember -Identity $ArgumentList[0] -Members $ArgumentList[1]
                                Show-UDToast -Message "User Added to Group"
                               } -ArgumentList @($fgp[$i], $strSIDusr)     
                        )  
                        }
                }
                )
           }

Thanks in advance man! You have been a big help to me on this one.

@aggiebeckett No problem. I am only trying to throw out ideas you know, I thought it might have worked the first time but I know how AD is man. That’s been my job for almost a decade and their cmdlets can be brutal at times. Can you try changing

[void]$group.member.Add("<SID=$strSIDusr>")

To:

[void]$group.member.Add("<SID=$($ArugmentList[1])") 

and see what happens?

1 Like

@nicoeat614 Thanks for the quick reply! I just tried that and it started throwing an Endpoint Not Found error like below.

image

So I went ahead and updated the $group variable to mirror that same process from the $ArgumentList and it cleared the error. But still no successful group membership update. I’m thinking about doing some testing with an IF ELSE statement to check and see if it’s even running the entire script block in the Button Endpoints or just skipping straight to the User Added to Group Toast Message.

Updated Code with Arrays:

             [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name
             [array]$fgp = Get-ADGroup -filter {name -like "*" -and member -eq $strMngr} | Select-Object -ExpandProperty distinguishedName          
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] -OnClick(
                            New-UDEndpoint -Endpoint {
                                $group = New-Object DirectoryServices.DirectoryEntry("LDAP://$($ArguementList[0])")
                                [void]$group.member.Add("<SID=$($ArgumentList[1])>")
                                $group.CommitChanges()
                                $group.Close()
                                #Add-ADGroupMember -Identity $ArgumentList[0] -Members $ArgumentList[1]
                                Show-UDToast -Message "User Added to Group"
                               } -ArgumentList @($fgp[$i], $strSIDusr)     
                        )  
                        }
                }
                )

There is something weird going on here. What you’re doing should work. Will need some further debugging. I was able to get this to work (at least passing the variables to the endpoint, not creating the AD groups) in my lab with the following structure using the $Session: scope.

New-UDInput -Title "Adding Folder Group Membership - Based on Dept." -Content {
    New-UDInputField -Type textbox -Name 'Manager' -Placeholder "Enter Manager NetID"
    New-UDInputField -Type textbox -Name 'NewUser' -Placeholder "Enter New Users NetID"
} -Endpoint {
            param($newuser, $manager)   
             $strDomn = "MYDOMAIN.local"
             $objCurrDomn = [System.DirectoryServices.DirectoryEntry]::new()
             #Manager             
             $objUsrMngr = [System.Security.Principal.NTAccount]::new($strDomn, $manager)
             $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
             $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             #NewUser
             $objUsr = [System.Security.Principal.NTAccount]::new($strDomn, $newuser)
             $strSIDusr = $objUsr.Translate([System.Security.Principal.SecurityIdentifier])
             $strusr = "CN=" + $strSIDusr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name
             [array]$Session:fgp = Get-ADGroup -filter {name -like "*" -and member -eq $strMngr} | Select-Object -ExpandProperty distinguishedName          
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] -OnClick(
                            New-UDEndpoint -Endpoint {
                                $group = New-Object DirectoryServices.DirectoryEntry("LDAP://$($Session:fgp[ArgumentList[0]])")
                                [void]$group.member.Add("<SID=$($ArgumentList[1])>")
                                $group.CommitChanges()
                                $group.Close()
                                #Add-ADGroupMember -Identity $ArgumentList[0] -Members $ArgumentList[1]
                                Show-UDToast -Message "User Added to Group"
                               } -ArgumentList @($i, $strSIDusr)     
                        )  
                        }
                }
                )
           }

If you ever want to debug an endpoint, add a Wait-Debugger to it.

for($i=0; $i -lt $grpstr.Length;$i++) {
                            New-UDButton -Text $item -OnClick(
                                New-UDEndpoint -Endpoint {
                                    Wait-Debugger

Then run your dashboard and click the button where the Wait-Debugger is hiding. Go back to your PS console and type Get-Runspace.

The runspace that is marked InBreakpoint is the one you want. It’s waiting at the Wait-Debugger call.

PS C:\Users\adamr> get-runspace

 Id Name            ComputerName    Type          State         Availability
 -- ----            ------------    ----          -----         ------------
  1 Runspace1       localhost       Local         Opened        Busy
 12 Runspace12      localhost       Local         Opened        Available
 31 Runspace31      localhost       Local         Opened        InBreakpoint

Then you can debug the runspace with Debug-Runspace.

PS C:\Users\adamr> debug-runspace 31
Debugging Runspace: Runspace31
To end the debugging session type the 'Detach' command at the debugger prompt, or type 'Ctrl+C' otherwise.

At line:4 char:37
+                                     $Session:fgp[$ArgumentList[0]]
+                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can then examine the variables that are available in your runspace.

[DBG]: [Process:19516]: [Runspace31]: PS C:\Users\adamr>> $Session:fgp
Some
Items
[DBG]: [Process:19516]: [Runspace31]: PS C:\Users\adamr>> $ArgumentList[0]
1

Hope that’s helpful!

1 Like

Leave it up to me to break stuff… :joy:

@adam Thank you for the breakdown. I’m going to test the code you provided and do some additional debugging on my end also. Just to clarify as well I’m not trying to create AD Groups but update the membership of current security groups. Don’t want you to debug the wrong result set.

So Interestingly enough after doing some more testing I noticed the $strSIDusr variable was not being cached. So I updated that to a cached variable and it still didn’t work. After running the debugger when declaring the cache variable like:

$Cache:strSIDusr = $objUsr.Translate([System.Security.Principal.SecurityIdentifier])

The variable was still not being passed on my end. And upon restarting IIS the script overall threw a Translate error like below:

image

But… When I changed that to:

$strSIDusr = $objUsr.Translate([System.Security.Principal.SecurityIdentifier]) $Cache:strSIDusr = $strSIDusr

The variable array passed nicely to the Button Endpoint. And after updating the ArgumentList to the proper variables the Buttons populate properly and when I click the new user is added to the associated group like intended!!!

Updated Code:

New-UDInput -Title "Adding Folder Group Membership - Based on Dept." -Content {
    New-UDInputField -Type textbox -Name 'Manager' -Placeholder "Enter Manager NetID"
    New-UDInputField -Type textbox -Name 'NewUser' -Placeholder "Enter New Users NetID"
} -Endpoint {
            param($newuser, $manager)   
             $strDomn = "MYDOMAIN.local"
             $objCurrDomn = [System.DirectoryServices.DirectoryEntry]::new()
             #Manager             
             $objUsrMngr = [System.Security.Principal.NTAccount]::new($strDomn, $manager)
             $strSIDMngr = $objUsrMngr.Translate([System.Security.Principal.SecurityIdentifier])
             $strMngr = "CN=" + $strSIDMngr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             #NewUser
             $objUsr = [System.Security.Principal.NTAccount]::new($strDomn, $newuser)
             $strSIDusr = $objUsr.Translate([System.Security.Principal.SecurityIdentifier])
             $Cache:strSIDusr = $strSIDusr
             $strusr = "CN=" + $strSIDusr.Value + ",CN=ForeignSecurityPrincipals," + $objCurrDomn.distinguishedName
             [array]$grpstr =  Get-ADGroup -Filter {member -eq $strMngr} | Select-Object -ExpandProperty Name
             [array]$Session:fgp = Get-ADGroup -filter {name -like "*" -and member -eq $strMngr} | Select-Object -ExpandProperty distinguishedName          
             New-UDInputAction -Content @(
                New-UDCard -Title "Select Groups to Add New User" -Content {
                    for($i=0; $i -lt $grpstr.Length;$i++) {
                        New-UDButton -Text $grpstr[$i] -OnClick(
                            New-UDEndpoint -Endpoint {
                                $group = New-Object DirectoryServices.DirectoryEntry("LDAP://$($Session:fgp[$ArgumentList[0]])")
                                [void]$group.member.Add("<SID=$($ArgumentList[1])>")
                                $group.CommitChanges()
                                $group.Close()
                                #Add-ADGroupMember -Identity $Session:fgp[$ArgumentList[0]] -Members $ArgumentList[1]
                                Show-UDToast -Message "User Added to Group"
                           } -ArgumentList @($i,$Cache:strSIDusr)     
                        )  
                        }
                }
             )
            }

Big Thanks to both of you @adam and @nicoeat614 I appreicate the help. I feel I would have been stuck on this for alot longer without your input.

Edit: Be aware! If anyone looks to use the group add method I used in my Endpoints that it completely skips any and all authentication methods. This works for my case because only my technical teams will be using these tools. This could get you in trouble with your boss if used improperly it is not secure.

2 Likes