DSACL.psm1

$Script:GuidTable = @{
    'Computer'              = [guid]'bf967a86-0de6-11d0-a285-00aa003049e2'
    'Contact'               = [guid]'5cb41ed0-0e4c-11d0-a286-00aa003049e2'
    'Group'                 = [guid]'bf967a9c-0de6-11d0-a285-00aa003049e2'
    'ManagedServiceAccount' = [guid]'ce206244-5827-4a86-ba1c-1c0c386c1b64'
    'User'                  = [guid]'bf967aba-0de6-11d0-a285-00aa003049e2'
    'OrganizationalUnit'    = [guid]'bf967aa5-0de6-11d0-a285-00aa003049e2'
    'All'                   = [guid]'00000000-0000-0000-0000-000000000000'
    'distinguishedName'     = [guid]'bf9679e4-0de6-11d0-a285-00aa003049e2'
    'name'                  = [guid]'bf967a0e-0de6-11d0-a285-00aa003049e2'
    'CN'                    = [guid]'bf96793f-0de6-11d0-a285-00aa003049e2'
    'ResetPassword'         = [guid]'00299570-246d-11d0-a768-00aa006e0529'
    'gPLink'                = [guid]'f30e3bbe-9ff0-11d1-b603-0000f80367c1'
    'Account Restrictions'  = [guid]'4c164200-20c0-11d0-a768-00aa006e0529'
    'Validated write to DNS host name' = [guid]'72e39547-7b18-11d1-adef-00c04fd8d5cd'
    'Validated write to service principal name' = [guid]'f3a64788-5306-11d1-a9c5-0000f80367c1'
}
function Add-DSACLAccessRule {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [System.DirectoryServices.DirectoryEntry]
        $Target,

        [Parameter(Mandatory,ValueFromPipeline)]
        [System.DirectoryServices.ActiveDirectoryAccessRule]
        $ACE
    )
    process {
        try {
            $Target.psbase.ObjectSecurity.AddAccessRule($ACE)
        }
        catch {
            throw
        }
    }
    end {
        try {
            $Target.psbase.CommitChanges()
        }
        catch {
            throw
        }
    }
}

function Get-LDAPObject {
    [CmdletBinding()]
    param (
        # DistinguishedName of LDAP object to bind to
        [Parameter(Mandatory)]
        [string]
        $DistinguishedName,

        # Set domain controller to use
        [Parameter()]
        [string]
        $Server,

        # Set Credentials to use when connecting
        [Parameter()]
        [pscredential]
        $Credential
    )
    try {
        $ArgumentList = $(
            if($PSBoundParameters.ContainsKey('Server')) {
                "LDAP://$Server/$DistinguishedName"
            }
            else {
                "LDAP://$DistinguishedName"
            }
            if($PSBoundParameters.ContainsKey('Credential')) {
                $Credential.UserName
                $Credential.GetNetworkCredential().Password
            }
        )
        $DirectoryEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $ArgumentList
        $null = try {
            # Try to read the object to force an exception if no object was found.
            $DirectoryEntry | Format-List
        }
        catch {
            throw 'Object not found!'
        }
        return $DirectoryEntry
    }
    catch {
        throw
    }
}

function Get-SID {
    [CmdletBinding()]
    param (
        # DistinguishedName of LDAP object to get SID from
        [Parameter(Mandatory)]
        [string]
        $DistinguishedName,

        # Set domain controller to use
        [Parameter()]
        [string]
        $Server,

        # Set Credentials to use when connecting
        [Parameter()]
        [pscredential]
        $Credential
    )

    process {
        $Object = Get-LDAPObject @PSBoundParameters
        New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $Object.ObjectSID.Value, 0
    }

}
<#
.Synopsis
   Create Access Control Entry for Active Directory ACL
.DESCRIPTION
   Create Access Control Entry for Active Directory ACL
.EXAMPLE
   New-ADAccessRule -Identity $SID -ActiveDirectoryRights 'CreateChild', 'DeleteChild' -AccessControlType Allow -ObjectType $TypeGuid -InheritanceType None
   Create access rule that gives the object with SID $SID access to create and delete objects of type $TypeGuid on "this object only"
#>

function New-DSACLAccessRule {
    [CmdletBinding()]
    param (
        # SID of principal that will rule will apply to
        [Parameter(Mandatory = $true, ParameterSetName = '1', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '2', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '3', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '4', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '5', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [System.Security.Principal.SecurityIdentifier]
        $Identity,

        # List of access rights that should be applied
        [Parameter(Mandatory = $true, ParameterSetName = '1', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '2', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '3', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '4', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '5', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipelineByPropertyName = $true)]
        [System.DirectoryServices.ActiveDirectoryRights[]]
        $ActiveDirectoryRights,

        # Sets allow or deny
        [Parameter(Mandatory = $true, ParameterSetName = '1', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '2', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '3', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '4', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '5', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipelineByPropertyName = $true)]
        [System.Security.AccessControl.AccessControlType]
        $AccessControlType,

        # Sets guid where access right should apply
        [Parameter(Mandatory = $true, ParameterSetName = '4', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '5', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipelineByPropertyName = $true)]
        [Guid]
        $ObjectType,

        # Sets if and how this rule should be inherited
        [Parameter(Mandatory = $true, ParameterSetName = '2', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '3', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '5', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipelineByPropertyName = $true)]
        [System.DirectoryServices.ActiveDirectorySecurityInheritance]
        $InheritanceType,

        # Sets guid of object types that should inherit this rule
        [Parameter(Mandatory = $true, ParameterSetName = '3', ValueFromPipelineByPropertyName = $true)]
        [Parameter(Mandatory = $true, ParameterSetName = '6', ValueFromPipelineByPropertyName = $true)]
        [Guid]
        $InheritedObjectType
    )
    process {
        switch ($PSCmdlet.ParameterSetName) {
            '1' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType}
            '2' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType, $InheritanceType}
            '3' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType, $InheritanceType, $InheritedObjectType}
            '4' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType, $ObjectType}
            '5' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType, $ObjectType, $InheritanceType}
            '6' {$ArgumentList = $Identity, $ActiveDirectoryRights, $AccessControlType, $ObjectType, $InheritanceType, $InheritedObjectType}
        }
        New-Object -TypeName System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $ArgumentList
    }
}
<#
.SYNOPSIS
Give Delegate rights to create objects of selected type in target (usually an OU)
 
.EXAMPLE
Add-DSACLCreateChild -TargetDN $UsersOU -DelegateDN $UserAdminGroup -ObjectTypeName User -AccessType Allow
Will give the group with DistinguishedName in $UserAdminGroup access to create user objects in
the OU with DistinguishedName in $UsersOU and all sub-OUs. Add -NoInheritance do disable inheritance.
 
#>

function Add-DSACLCreateChild {
    [CmdletBinding(DefaultParameterSetName='ByTypeName')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipelineByPropertyName)]
        [String]
        $DelegateDN,

        # Object type to give full control over
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [ValidateSet('Computer', 'Contact', 'Group', 'ManagedServiceAccount', 'User','All')]
        [String]
        $ObjectTypeName,

        # ObjectType guid, used for custom object types
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [Guid]
        $ObjectTypeGuid,

        # Allow or Deny
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [System.Security.AccessControl.AccessControlType]
        $AccessType,

        # Sets access right to "This object only"
        [Parameter(ParameterSetName='ByTypeName')]
        [Parameter(ParameterSetName='ByGuid')]
        [Switch]
        $NoInheritance
    )

    process {
        try {
            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'None'
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'All'
            }
            switch ($PSCmdlet.ParameterSetName) {
                'ByTypeName' { $ObjectType = $Script:GuidTable[$ObjectTypeName]}
                'ByGuid'     { $ObjectType = $ObjectTypeGuid }
            }

            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'CreateChild'
                AccessControlType     = $AccessType
                ObjectType            = $ObjectType
                InheritanceType       = $InheritanceType
            }
            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Give Delegate custom rights in target (usually an OU)
 
.DESCRIPTION
Used to delegate any custom rights in Active Directory.
Requires knowledge of creating ActiveDirectoryAccessRules, please use with caution.
 
#>

function Add-DSACLCustom {
    [CmdletBinding(DefaultParameterSetName='Delegate')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [Parameter(Mandatory,ParameterSetName='Self')]
        [String]
        $TargetDN,

        # Give access to "Self" instead of a user or group
        [Parameter(Mandatory,ParameterSetName='Self')]
        [Switch]
        $Self,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [String]
        $DelegateDN,

        # List of access rights that should be applied
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [Parameter(Mandatory,ParameterSetName='Self')]
        [System.DirectoryServices.ActiveDirectoryRights[]]
        $ActiveDirectoryRights,

        # Sets allow or deny
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [Parameter(Mandatory,ParameterSetName='Self')]
        [System.Security.AccessControl.AccessControlType]
        $AccessControlType,

        # Sets guid where access right should apply
        [Parameter(ParameterSetName='Delegate')]
        [Parameter(ParameterSetName='Self')]
        [Guid]
        $ObjectType,

        # Sets if and how this rule should be inherited
        [Parameter(ParameterSetName='Delegate')]
        [Parameter(ParameterSetName='Self')]
        [System.DirectoryServices.ActiveDirectorySecurityInheritance]
        $InheritanceType,

        # Sets guid of object types that should inherit this rule
        [Parameter(ParameterSetName='Delegate')]
        [Parameter(ParameterSetName='Self')]
        [Guid]
        $InheritedObjectType

    )

    process {
        try {
            $Target = Get-LDAPObject -DistinguishedName $TargetDN -ErrorAction Stop
            switch ($PSCmdlet.ParameterSetName) {
                'Delegate' {
                    $DelegateSID = Get-SID -DistinguishedName $DelegateDN
                }
                'Self' { $DelegateSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList 'S-1-5-10' }
            }

            $null = $PSBoundParameters.Remove('TargetDN')
            $null = $PSBoundParameters.Remove('DelegateDN')
            $PSBoundParameters.Add('Identity',$DelegateSID)

            $ACE = New-DSACLAccessRule @PSBoundParameters

            Add-DSACLAccessRule -Target $Target -ACE $ACE
        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Give Delegate rights to delete objects of selected type in target (usually an OU)
 
.EXAMPLE
Add-DSACLDeleteChild -TargetDN $UsersOU -DelegateDN $UserAdminGroup -ObjectTypeName User -AccessType Allow
Will give the group with DistinguishedName in $UserAdminGroup access to delete user objects in
the OU with DistinguishedName in $UsersOU and all sub-OUs. Add -NoInheritance do disable inheritance.
 
#>

function Add-DSACLDeleteChild {
    [CmdletBinding(DefaultParameterSetName='ByTypeName')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipelineByPropertyName)]
        [String]
        $DelegateDN,

        # Object type to give full control over
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [ValidateSet('Computer', 'Contact', 'Group', 'ManagedServiceAccount', 'User','All')]
        [String]
        $ObjectTypeName,

        # ObjectType guid, used for custom object types
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [Guid]
        $ObjectTypeGuid,

        # Allow or Deny
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [System.Security.AccessControl.AccessControlType]
        $AccessType,

        # Sets access right to "This object only"
        [Parameter(ParameterSetName='ByTypeName')]
        [Parameter(ParameterSetName='ByGuid')]
        [Switch]
        $NoInheritance
    )

    process {
        try {
            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'None'
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'All'
            }
            switch ($PSCmdlet.ParameterSetName) {
                'ByTypeName' { $ObjectType = $Script:GuidTable[$ObjectTypeName]}
                'ByGuid'     { $ObjectType = $ObjectTypeGuid }
            }

            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'DeleteChild'
                AccessControlType     = $AccessType
                ObjectType            = $ObjectType
                InheritanceType       = $InheritanceType
            }
            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Give Delegate FullControl rights on objects of selected type in target (usually an OU)
 
.EXAMPLE
Add-DSACLFullControl -TargetDN $UsersOU -DelegateDN $UserAdminGroup -ObjectTypeName User -AccessType Allow
Will give the group with DistinguishedName in $UserAdminGroup FullControl of user objects in
the OU with DistinguishedName in $UsersOU and all sub-OUs. Add -NoInheritance do disable inheritance.
#>

function Add-DSACLFullControl {
    [CmdletBinding(DefaultParameterSetName='ByTypeName')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipelineByPropertyName)]
        [String]
        $DelegateDN,

        # Object type to give full control over
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [ValidateSet('Computer', 'Contact', 'Group', 'ManagedServiceAccount', 'User', 'All')]
        [String]
        $ObjectTypeName,

        # ObjectType guid, used for custom object types
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [Guid]
        $ObjectTypeGuid,

        # Allow or Deny
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [System.Security.AccessControl.AccessControlType]
        $AccessType,

        # Sets access right to "This object only"
        [Parameter(ParameterSetName='ByTypeName')]
        [Parameter(ParameterSetName='ByGuid')]
        [Switch]
        $NoInheritance
    )

    process {
        try {
            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Children'
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Descendents'
            }
            switch ($PSCmdlet.ParameterSetName) {
                'ByTypeName' { $ObjectType = $Script:GuidTable[$ObjectTypeName]}
                'ByGuid'     { $ObjectType = $ObjectTypeGuid }
            }

            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'GenericAll'
                AccessControlType     = $AccessType
                InheritedObjectType   = $ObjectType
                InheritanceType       = $InheritanceType
            }
            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
<#
    .SYNOPSIS
    Give $DelegateDN rights to join computers in target (usually an OU).
 
    .EXAMPLE
    Add-DSACLJoinDomain -TargetDN $ComputersOU -DelegateDN $JoinDomainAccounts -AccessType Allow
    Will give the group with DistinguishedName in $JoinDomainAccounts rights to join computers to
    the domain. Requires a computer account to be created already.
 
    Use switch -AllowCreate to allow to create computer objects in OU and thereby join without a
    pre-existing computer object. -AllowDelete will give rights to move account away from this
    location (requires allow create on destination). Add -NoInheritance do disable inheritance.
#>

function Add-DSACLJoinDomain {
    [CmdletBinding()]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory)]
        [String]
        $DelegateDN,

        # Sets access right to "This object only"
        [Parameter()]
        [Switch]
        $AllowCreate,

        # Sets access right to "This object only"
        [Parameter()]
        [Switch]
        $AllowDelete,

        # Sets access right to "This object only"
        [Parameter()]
        [Switch]
        $NoInheritance
    )

    process {
        try {

            $Target = Get-LDAPObject -DistinguishedName $TargetDN
            $DelegateSID = Get-SID -DistinguishedName $DelegateDN

            $InheritanceParam = @{}
            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Children'
                $InheritanceParam['NoInheritance'] = $true
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Descendents'
            }

            Add-DSACLResetPassword -TargetDN $TargetDN -DelegateDN $DelegateDN -ObjectTypeName Computer -AccessType Allow @InheritanceParam

            $AceParams = @{
                Identity              = $DelegateSID
                ActiveDirectoryRights = 'ExtendedRight'
                AccessControlType     = 'Allow'
                InheritanceType       = $InheritanceType
                InheritedObjectType   = $Script:GuidTable['Computer']
            }

            'Account Restrictions', 'Validated write to DNS host name', 'Validated write to service principal name' | ForEach-Object -Process {
                New-DSACLAccessRule -ObjectType $Script:GuidTable[$_] @AceParams
            } | Add-DSACLAccessRule -Target $Target

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Delegate rights to link GPO on target (usually an OU)
 
.EXAMPLE
Add-DSACLLinkGPO -TargetDN $UsersOU -DelegateDN $GPAdmin -AccessType Allow
Will give the group with DistinguishedName in $GPAdmin rights to link GPOs on
the OU with DistinguishedName in $UsersOU and all sub-OUs. Add -NoInheritance to disable inheritance.
#>

function Add-DSACLLinkGPO {
    [CmdletBinding()]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
        [String]
        $DelegateDN,

        # Allow or Deny
        [Parameter(Mandatory)]
        [System.Security.AccessControl.AccessControlType]
        $AccessType,

        # Sets access right to "This object only"
        [Parameter()]
        [Switch]
        $NoInheritance
    )

    process {
        try {
            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'WriteProperty'
                AccessControlType     = $AccessType
                ObjectType            = $Script:GuidTable['gPLink']
            }

            if ($NoInheritance.IsPresent) {
                $Params['InheritanceType'] = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'None'
            }
            else {
                $Params['InheritanceType'] = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Descendents'
                $Params['InheritanceObjectType'] = $Script:GuidTable['OrganizationalUnit']
            }

            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Give Delegate rights to rename computers in target (usually an OU)
 
.EXAMPLE
Add-DSACLRenameComputer -TargetDN $ComputersOU -DelegateDN $ComputerAdminGroup -AccessType Allow
Will give the group with DistinguishedName in $ComputerAdminGroup rights to rename computers in
the OU with DistinguishedName in $ComputersOU and all sub-OUs. Add -NoInheritance do disable inheritance.
#>

function Add-DSACLRenameComputer {
    [CmdletBinding(DefaultParameterSetName='Delegate')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [Parameter(Mandatory,ParameterSetName='Self')]
        [String]
        $TargetDN,

        # Give access to "Self" instead of a user or group
        [Parameter(Mandatory,ParameterSetName='Self')]
        [Switch]
        $Self,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='Delegate')]
        [String]
        $DelegateDN,

        # Sets access right to "This object only"
        [Parameter(ParameterSetName='Delegate')]
        [Parameter(ParameterSetName='Self')]
        [Switch]
        $NoInheritance
    )

    process {
        try {

            $Target = Get-LDAPObject -DistinguishedName $TargetDN
            switch ($PSCmdlet.ParameterSetName) {
                'Delegate' {
                    $DelegateSID = Get-SID -DistinguishedName $DelegateDN
                }
                'Self' { $DelegateSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList 'S-1-5-10' }
            }

            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Children'
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Descendents'
            }

            $AceParams = @{
                Identity = $DelegateSID
                ActiveDirectoryRights = 'WriteProperty'
                AccessControlType = 'Allow'
                InheritedObjectType   = $Script:GuidTable['Computer']
                InheritanceType       = $InheritanceType
            }

            'distinguishedName', 'name', 'CN' | ForEach-Object -Process {
                New-DSACLAccessRule -ObjectType $Script:GuidTable[$_] @AceParams
            } | Add-DSACLAccessRule -Target $Target

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Give Delegate "Replicating Directory Changes" rights on domain with DistinguishedName in target
 
.EXAMPLE
Add-DSACLReplicatingDirectoryChanges -DelegateDN $AADCServiceAccount
Will give the service account with DistinguishedName in $AADCServiceAccount the right "Replicating Directory Changes".
Add -AllowReplicateSecrets to grant "Replicating Directory Changes All" instead..
 
#>

function Add-DSACLReplicatingDirectoryChanges {
    [CmdletBinding(DefaultParameterSetName='ByTypeName')]
    param (
        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory)]
        [String]
        $DelegateDN,

        # Allow replicating secrets, like passwords (Corresponds to "Replicating Directory Changes All")
        [Parameter()]
        [Switch]
        $AllowReplicateSecrets
    )

    process {
        try {

            $TargetDN = Get-LdapObject -DistinguishedName RootDse | Select-Object -ExpandProperty defaultNamingContext

            if ($AllowReplicateSecrets.IsPresent) {
                # Replicating Directory Changes All
                $ObjectType = '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'
            }
            else {
                # Replicating Directory Changes
                $ObjectType = '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'
            }
            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'ExtendedRight'
                AccessControlType     = 'Allow'
                ObjectType            = $ObjectType
                InheritanceType       = 'None'
            }
            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
<#
.SYNOPSIS
Delegate ResetPassword rights on objects of selected type in target (usually an OU)
 
.EXAMPLE
Add-DSACLResetPassword -TargetDN $UsersOU -DelegateDN $UserAdminGroup -ObjectTypeName User -AccessType Allow
Will give the group with DistinguishedName in $UserAdminGroup ResetPassword rights of user objects in
the OU with DistinguishedName in $UsersOU and all sub-OUs. Add -NoInheritance to disable inheritance.
#>

function Add-DSACLResetPassword {
    [CmdletBinding(DefaultParameterSetName='ByTypeName')]
    param (
        # DistinguishedName of object to modify ACL on. Usually an OU.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [String]
        $TargetDN,

        # DistinguishedName of group or user to give permissions to.
        [Parameter(Mandatory,ParameterSetName='ByTypeName',ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory,ParameterSetName='ByGuid',ValueFromPipelineByPropertyName)]
        [String]
        $DelegateDN,

        # Object type to give full control over
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [ValidateSet('User', 'Computer', 'ManagedServiceAccount')]
        [String]
        $ObjectTypeName,

        # ObjectType guid, used for custom object types
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [Guid]
        $ObjectTypeGuid,

        # Allow or Deny
        [Parameter(Mandatory,ParameterSetName='ByTypeName')]
        [Parameter(Mandatory,ParameterSetName='ByGuid')]
        [System.Security.AccessControl.AccessControlType]
        $AccessType,

        # Sets access right to "This object only"
        [Parameter(ParameterSetName='ByTypeName')]
        [Parameter(ParameterSetName='ByGuid')]
        [Switch]
        $NoInheritance
    )

    process {
        try {
            if ($NoInheritance.IsPresent) {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Children'
            }
            else {
                $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]'Descendents'
            }
            switch ($PSCmdlet.ParameterSetName) {
                'ByTypeName' { $ObjectType = $Script:GuidTable[$ObjectTypeName]}
                'ByGuid'     { $ObjectType = $ObjectTypeGuid }
            }

            $Params = @{
                TargetDN              = $TargetDN
                DelegateDN            = $DelegateDN
                ActiveDirectoryRights = 'ExtendedRight'
                AccessControlType     = $AccessType
                ObjectType            = $Script:GuidTable['ResetPassword']
                InheritanceType       = $InheritanceType
                InheritedObjectType   = $ObjectType
            }
            Add-DSACLCustom @Params

        }
        catch {
            throw
        }
    }
}
Export-ModuleMember -Function 'New-DSACLAccessRule','Add-DSACLCreateChild','Add-DSACLCustom','Add-DSACLDeleteChild','Add-DSACLFullControl','Add-DSACLJoinDomain','Add-DSACLLinkGPO','Add-DSACLRenameComputer','Add-DSACLReplicatingDirectoryChanges','Add-DSACLResetPassword'

# SIG # Begin signature block
# MIIgKwYJKoZIhvcNAQcCoIIgHDCCIBgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUaCvDdiMAaeO6WPBHhl6mEvNQ
# JzWgghtaMIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0B
# AQUFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk
# IElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
# Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg
# +XESpa7cJpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lT
# XDGEKvYPmDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5
# a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g
# 0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1
# roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
# GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G
# A1UdDgQWBBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLL
# gjEtUYunpyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3
# cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmr
# EthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+
# fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5Q
# Z7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu
# 838fYxAe+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw
# 8jCCBSgwggQQoAMCAQICEA+hUYFUQFVW/Nq+92XXcOgwDQYJKoZIhvcNAQELBQAw
# cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ
# d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk
# IElEIENvZGUgU2lnbmluZyBDQTAeFw0xODAyMTgwMDAwMDBaFw0xOTA1MjMxMjAw
# MDBaMGUxCzAJBgNVBAYTAlNFMRIwEAYDVQQIEwlTdG9ja2hvbG0xFDASBgNVBAcT
# C0d1c3RhdnNiZXJnMRUwEwYDVQQKEwxTaW1vbiBXYWhsaW4xFTATBgNVBAMTDFNp
# bW9uIFdhaGxpbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ1eZRbg
# ILXbBouh9HD8KQMmayiqIj08rtHmaXI1eVerZ8/1SlrbinggZgc58grW1JEpiBMK
# V77FpavYO6uJZakeOLOtDisPp3f4H4pvKfdlSijKx5ythkw9BnlMlgjkicRsdSY1
# gr1IGbZ5KFu0u9Ss1SEYcVC/PfSkQE9U3pnY5bH43HrlHMpci5AIenFlkjbvwyem
# GvCcyPKe3FgAzQJQlKDqaaBjMSbQ0fTC3bwYzcjl82xtKyWhI/nuACvPnCrJSKoF
# tCp4KVrQ/9NSxGUMwl+4ruhExnkak2YTXhjKycREk5r2C0DnwhO7LouqywN4zUno
# yHRB43sVoQfpaA0CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nED
# wGD5LfZldQ5YMB0GA1UdDgQWBBR/ldAycNDjdepJosF5sXovEXvXwjAOBgNVHQ8B
# Af8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYv
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmww
# NaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3Mt
# ZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0
# dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcB
# AQR4MHYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggr
# BgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hB
# MkFzc3VyZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI
# hvcNAQELBQADggEBADbXi97ZKkAY9fiXoAonkktvTsd2ZVLgLM66vxeqF2uLC/Y+
# shIDDe82S0UtPK8SUui7Gt09P0SEd4QXQnJg6lUc4i2Og84+dxEQFhZRvfSQUp11
# q48LhGbC2IIPOOiUpHXXaJeJy97fUf+qkhZACw9XF1ZvE6XkCcwlj83FrcBPh1Z5
# GQpOA14tiiUbvI2VSy9PbkVGhJ96u69+glOcOSb7YrHvvzeA/41hOOge+Yq+QukZ
# 6OsTWYfD8++gepgKm4r5BnX+eH7648bjfK0W9xwZ9iixqLtJT7edlGyBcItKtNyI
# 21WuqozQtZ5Tu0KECADaOsj80boAsrdRzeTDfdowggUwMIIEGKADAgECAhAECRgb
# X9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYD
# VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAi
# BgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAw
# MDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp
# Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERp
# Z2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqG
# SIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE
# 9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvsp
# J8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWu
# HEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel0
# 5iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4P
# waLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHN
# MIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUE
# DDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6
# Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMu
# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0f
# BHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz
# dXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29t
# L0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG
# /WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
# UzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYD
# VR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEB
# AD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh
# 9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6R
# Ffu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEM
# j7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutm
# Q9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUu
# kpHqaGxEMrJmoecYpJpkUe8wggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/Bm
# MA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IEFzc3VyZWQgSUQgQ0EtMTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAw
# MDBaMEcxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMc
# RGlnaUNlcnQgVGltZXN0YW1wIFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQAD
# ggEPADCCAQoCggEBAKNkXfx8s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V
# +JLjntVaY1sCSVDZg85vZu7dy4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnM
# Xij0ZLZQt/USs3OWCmejvmGfrvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oO
# jafeTl/iqLYtWQJhiGFyGGi5uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZ
# h6h+z+yMDDZbesF6uHjHyQYuRhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZ
# FQlXmVYwk/PJYczQCMxr7GJCkawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1Ud
# DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI
# MIIBvwYDVR0gBIIBtjCCAbIwggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIB
# FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFW
# HoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBm
# AGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0
# AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAv
# AEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0
# AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAg
# AGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBw
# AG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBu
# AGMAZQAuMAsGCWCGSAGG/WwDFTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcN
# K2cCzTAdBgNVHQ4EFgQUYVpNJLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4
# oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE
# Q0EtMS5jcmwwOKA2oDSGMmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy
# dEFzc3VyZWRJRENBLTEuY3JsMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkq
# hkiG9w0BAQUFAAOCAQEAnSV+GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEX
# zakbvFoWOQCd42yE5FpA+94GAYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gw
# g5QZBWs1kBCge5fH9j/n4hFBpr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x
# 2C/jbRcTBu7kA7YUq/OPQ6dxnSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYo
# FenYk+VVFvC7Cqsc21xIJ2bIo4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VU
# QAOSK2vCUcIKSK+w1G7g9BQKOhvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9
# +QOWA63qAArrPye7uhswDQYJKoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTAT
# BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk
# MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAw
# MDAwMFoXDTIxMTExMDAwMDAwMFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp
# Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY
# RGlnaUNlcnQgQXNzdXJlZCBJRCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
# MIIBCgKCAQEA6IItmfnKwkKVpYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgW
# Wd+etSQVwpi5tHdJ3InECtqvy15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+
# x8cxSIB8HqIPkg5QycaH6zY/2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32j
# x0PdAug7Pe2xQaPtP77blUjE7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSN
# vtLOBq6thG9IhJtPQLnxTPKvmPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0
# XEK4aH631XcKJ1Z8D2KkPzIUYJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/
# BAQDAgGGMDsGA1UdJQQ0MDIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG
# CCsGAQUFBwMEBggrBgEFBQcDCDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9
# bAABBDCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3Nz
# bC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5
# ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABl
# ACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAg
# AG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABh
# AG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwBy
# AGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBp
# AGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABl
# AGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJ
# YIZIAYb9bAMVMBIGA1UdEwEB/wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQG
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKG
# N2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv
# b3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9j
# cmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYD
# VR0OBBYEFBUAEisTmLKZB+0e36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuC
# MS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LP
# UukxR6tWXHvVDQtBs+/sdR90OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJH
# hZRW0eu7NoR3zCSl8wQZVann4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFi
# qKgz5Js5p8T1zh14dpQlc+Qqq8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwC
# Xaj++wc4Tw3GXZG5D2dFzdaD7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7Pkdcntxbu
# D8O9fAqg7iwIVYUiuOsYGk38KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAm
# MYIEOzCCBDcCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0
# IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNl
# cnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQD6FRgVRAVVb82r73
# Zddw6DAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC
# NwIBFTAjBgkqhkiG9w0BCQQxFgQUu4MwXLthPosoSXyhTCDVrLCCGiYwDQYJKoZI
# hvcNAQEBBQAEggEAT6lhhlNCEgpNd7+P0S/kaEunWF3+9NlKS+RvM2X8bKMlwHr1
# 5tWMW/8F5DEk9cAFk6HcbhL5D39LI/r67z+FnTCJoIZEN8XGCsQ5ZKbJI7xBh5/8
# C0+ui2kjAO4RUYclt0IvoK3F1oRrZL4zKMZXhZyMkFFLW5dJ+Z/xSvwSRrKD8Ej+
# Act1gK9KidpjMOHm1Wu/9k1TWNPkGybVqfPKYME6598AJgNymQg8vREkZEipfHlD
# IP8pCiQI3m1Wq6f+rBLFCIcldpWmL9M5KnNo2CrtSD4oMjCfo8e6SwdUZ72XKefO
# jBibLWeCQ1CtUt2+/i3sVx3BtW+iMrDbzHQrOKGCAg8wggILBgkqhkiG9w0BCQYx
# ggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUrDgMCGgUAoF0w
# GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTgwMzMw
# MTg0OTU5WjAjBgkqhkiG9w0BCQQxFgQU6MekEQDLXuOAbFz+vpt5MjxLU2AwDQYJ
# KoZIhvcNAQEBBQAEggEASQuYylGo8XWAvomwd7upb/XOP2RH8nHCGT5bNhKvvq3Z
# bvgwmq/ls9UyzZeKdk0SWEAEcc3h00GkxCZl2g54RNXxHlFu9hTEcOlhy+0ieJnm
# X9lhMZ3lkEQdVLAyYZYIzqt0ULZ4CFJdoD1K6u4kuDceEdDiiUmMeCbNLLGlkWbk
# jCdd7yxsMjgi8feC6jcqCOMkbilgn7EwQirOJSCMfdGUl7bk4HQKES02T6sxKe5l
# SmK7QLke6cAV1ZLm/aVqgSWQ+LTYLSU9cJQl8WEy/oInazs6m2kVewiQhjurQP91
# K1TQbovw2RIRb5INGBLHca3Ch7Cw2/zNOLgG0Dak5A==
# SIG # End signature block