Wednesday, May 8, 2019

AD groups - setting group owner and delegating permission with powershell

Given that permissions delegation is only a simple checkbox in the AD users and computers tool under the manager's name, it would be nice if set-adgroup had a similar functionality. There are several steps involved in delegating rights, and if the owner is being changed, typically the old owner's rights should be removed. With this script below, it should accomplish this at least on a single domain environment. If the owner and group are in multiple domains, it can get a bit more complicated and some adjustments would be needed. This script takes either get-adgroup pipeline input, or a single group name that would work as an "identity" value in get-adgroup.

[CmdletBinding()]

param(

               [parameter(helpmessage="samaccountname of group owner",mandatory=$true)]$owner,

                              #defaults to current user's domain if not specified

               [parameter(helpmessage="netbios domain name")]$domain=$env:userdomain,  

               [parameter(parametersetname='pipe', valuefrompipeline=$true)]

        [Microsoft.ActiveDirectory.Management.ADGroup]$group,

               [parameter(parametersetname='normal',valuefrompipeline=$false, helpmessage="AD group name")]$identity,

                              #for cross domain? needs testing and what if the group and owner are in different domains?

               [parameter(helpmessage="domain controller to do object lookups")]$server

)

 

begin{

               import-module activedirectory

               if ($server -eq $null) { $server = (get-addomaincontroller -Discover -Writable).hostname}

}

process {

               #allow for both a single group name to be passed as $identity, or take pipeline get-adgroup output

               if ($pscmdlet.parametersetname -eq 'normal') {

                              try {

                                             [array]$group = get-adgroup $identity -property managedby -ea stop -server $server

                              } catch {

                                             throw "Unable to find AD group"

                              }

               }

              

               #cast the group as an array for the foreach loop

               if (!($group -is [array])) { $group = [array]$group}

              

               #hardcode guid for the write members permission

               $guid =[guid]'bf9679c0-0de6-11d0-a285-00aa003049e2'

              

               #get the group owner's sid - this could be replaced with get-aduser

               $user = New-Object System.Security.Principal.NTAccount("$domain\$owner")

               $sid =$user.translate([System.Security.Principal.SecurityIdentifier])

               $ctrl =[System.Security.AccessControl.AccessControlType]::Allow

               $rights =[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty

               $intype =[System.DirectoryServices.ActiveDirectorySecurityInheritance]::None

               try {

                              try {

                                             $aduserobj = get-aduser $owner -server $server

                              } catch {

                                             #if no user was found try looking for a group owner

                                             $aduserobj = get-aduser $owner -server $server

                              }

               } catch {

                              throw "Unable to find owner's account"

               }

 

 

               foreach ($groupobj in $group) {

              

                              $acl = Get-Acl ad:"$($groupobj.distinguishedname)"

                             

                             

                              #if the group was passed without the managedby property, look it up again

                              if (($groupobj |gm |where {$_.name -eq "managedby"}) -eq $null) {

                                             #if there was a previous manager listed that doesn't match the one being passed to this script

                                             # remove any existing rights for that user

                                             $groupobj = get-adgroup $groupobj.distinguishedname -property managedby -server $server

                              }

 

                              if ($groupobj.managedby -ne $null) {

                                             try {
                                                $previousownersid = (get-aduser $groupobj.managedby -property sid -server $server).sid } catch { $previousownersid = (get-adgroup $groupobj.managedby -property sid -server $server).sid

                                             if ($previousownersid.value -ne $sid.value) {

                #$prevownerID = new-object system.security.principal.securityidentifier($previousownersid)

                           $previousownerID = $previousownersid.Translate([System.security.principal.ntaccount]).Value

                                                            $acl.access | where {$_.identityreference -eq $previousownerID} | % {

                                                                           $acl.RemoveAccessRule($_)

                                                            }

                                             }

                              }

                                            

                             

                              #set the ManagedBy property to the new owner

                              set-adgroup $groupobj -managedby $aduserobj -server $server

                             

                              #add new owner's right to manage members

                              $rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($sid,$rights,$ctrl,$guid)

                              $acl.AddAccessRule($rule)

                              Set-Acl -acl $acl -path ad:"$($groupobj.distinguishedname)"

               }

}

No comments:

Post a Comment