private/Add-OUStructureFromTemplate.ps1

Function Add-OUStructureFromTemplate {
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param
    (
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)]
        [String]$Name,

        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1)]
        [String]$Description,

        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=2)]
        [String]$Path,

        [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$true, Position=3)]
        [System.Collections.Hashtable]$Template,

        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, Position=4)]
        [String]$ParentOrg,

        [Switch]$ResetRoleMembership
        
    )

    BEGIN {
        $shouldProcess = @{
            Confirm = [bool]($ConfirmPreference -eq "low")
            Whatif = [bool]($WhatIfPreference.IsPresent)
            verbose = [bool]($VerbosePreference -ne "SilentlyContinue")
        }
        #$ShouldProcess.verbose = $True
    }
    PROCESS {       
        if ($PsItem.Name) { $Name = $_.Name}
        if ($PsItem.Description) {$Description = $_.Description}
        if ($PsItem.Path) {$Path = $_.Path}
        if ($PsItem.Template) {$Template = $_.Template}
        if ($PsItem.ParentOrg) {$ParentOrg = $_.ParentOrg}
        $DefaultRights = $Template.DefaultRights
        $DefaultRoles = $Template.DefaultRoles
        $resetRoleParam = @{
            resetMembership = [bool]($ResetRoleMembership)
        }
       

        $structureString = "`r`n{0} OUs {0}{0}{0} Descriptions {0}{0}{0}" -f "#####"
        $structureString += "`r`n {0,-24} : {1}" -f $name,$description
        $structureString += $Template.OUs | ForEach-Object {"`r`n --> {0,-20} : {1}" -f $_.name,($_.description[0..95] -join "")}
        $ChildPath = "OU=$name,$path"
        if (-not $shouldProcess.verbose) {Write-Host ("Creating OU Structure: '{0}'`r`n under: '{1}'`r`n{2}" -f $name,$path,$structureString)}
        if ($PSCmdlet.ShouldProcess(("`r`nCreating OU Structure: '{0}'`r`n under: '{1}'`r`n{2}" -f $name,$path,$structureString))) {
            $OUBase = CreateOrSetOU -Name $name -Description $Description -Path $path @shouldProcess
            $ChildPath = $OUBase.DistinguishedName
            $ChildOUs = $Template.OUs | foreach-object {
                $_.Path = $ChildPath
                write-verbose ("--- Template ChildOU: {0} at {1}" -f $_.name, $_.path)
                [pscustomObject]$_
            }
            
            $ChildOUs | CreateOrSetOU @ShouldProcess | out-null
        }
        Write-Host "Finished Structure Creation`r`n"
        if ($ParentOrg) {
        # Write-verbose "There is a component"
            $GroupMidName = "$parentOrg-$Name"
            $RightsPath = "OU={0}s,{1}" -f $RightsName, $ChildPath
            $RolesPath = "OU={0}s,{1}" -f $RolesName, $ChildPath
            $ParentPrincipalPrefix = "$parentOrg"
        } else {
        # write-verbose "No Component"
            $GroupMidName = $name
            $RightsPath = "OU={0}s,{1}" -f $RightsName, $ChildPath
            $RolesPath = "OU={0}s,{1}" -f $RolesName, $ChildPath
            $ParentPrincipalPrefix = "Global"
        }
        # write-verbose "Rights: $rightsPath; Roles: $RolesPath"
        if ($defaultRights) {Write-host ("{0,-48} @ {1}" -f "About to create default rights", $RightsPath)}
        $rightsDef = foreach ($Group in $DefaultRights) {
            $def = [pscustomobject]@{
                Name = "$RightsName-$GroupMidName-$($Group.nameSuffix)"
                Description = $Group.Description
                path = $RightsPath
                GroupScope = "DomainLocal"
                Info = $Group.Description
                Members = @()
                memberOf = @()
            }
            if ($Group.AddParents -ne $false -and $ParentPrincipalPrefix -ne $name) {
                try {
                    $parentRightName = (get-adgroup $("{0}-{1}-{2}" -f $RightsName, $ParentPrincipalPrefix, $Group.nameSuffix)).name
                    write-Verbose "Adding the parent Org group $parentRightName as a member to $($def.name)"   
                    $def.members = $parentRightName
                } catch {
                    Write-verbose "Parent org group doesn't exist, skipping"
                }
            }

            Write-Host ("--->{0,-30}" -f $def.name, $def.path)
            $def
        }

        
        $rightsDef | CreateOrSetGroup @ShouldProcess | out-null
        
        if ($defaultRoles) {Write-host ("`r`n{0,-48} @ {1}" -f "About to create Roles:", $RolesPath) }
        $rolesDef = foreach ($Group in $DefaultRoles) {
            $def = [psCustomObject]@{
                Name = "$RolesName-$GroupMidName-$($Group.nameSuffix)"
                Description = $Group.Description
                path = $RolesPath
                GroupScope = "Global"
                Info = $Group.Description
                MemberOf = @()
            }
            if ($Group.AddParents -eq $true -and $name -ne "Global") {
                $parentGroupName = "{0}-{1}-{2}" -f $RolesName, $ParentPrincipalPrefix, $Group.nameSuffix
                write-Verbose "Add parent group as member: $parentGroupName"
                $def.members = $ParentGroupName
            }
            Write-Host ("--->{0,-30}" -f $def.name, $def.path)
            $def.memberOf = foreach ($right in $Group.rights) {
                $rightName = "$RightsName-$GroupMidName-$right"
                $RightName
            }
            if ($group.auxiliaryGroups) {
                $def.memberof += $Group.auxiliaryGroups
            }
            if ($true -eq $Group.Protected) {
                $def.memberOf += "Protected Users"
            }
            foreach ($g in $def.memberOf) {
                if ($null -ne $g) {
                    write-Host (" |-->{0}" -f $g)
                }
            }
            $def
        }
        $rolesDef | CreateOrSetGroup @shouldProcess @resetRoleParam | out-null

        # Build ParameterList
        $ACLList = foreach ($delegation in $Template.OUDelegations) {
            $params = @{
                ADPath = $null
                Principal = $null
            }


            if ($delegation.PrincipalSuffix -and -not $delegation.Principal) {
                $params.Principal = "{0}-{1}-{2}" -f $RightsName, $GroupMidName, $delegation.PrincipalSuffix
                write-Verbose "Deriving Principal: $($params.Principal)"
            } else {
                $params.Principal = $delegation.principal
            }
            if ($delegation.ADRight) {
                $params.ADRight = $Delegation.ADRight
            }
            if ($delegation.ExtendedRight) {
                $params.ExtendedRight = $Delegation.ExtendedRight
            }
            if ($delegation.targetObject) {
                $params.targetObject = $Delegation.targetObject
            }
            if ($delegation.appliesTo) {
                $params.appliesTo = $Delegation.appliesTo
            } 
            if ($delegation.InheritanceType) {
                $params.InheritanceType = $Delegation.InheritanceType
            } 


            if ($Delegation.ADPathQuery) {
                $query = $delegation.ADPathQuery
                $params.ADPath = $(get-adobject @query).DistinguishedName
                @{
                    Path = "Children of $($query.searchbase)"
                    ACL = $params
                }
            } else{
                if ($delegation.ADPathLeafOU -and -not $delegation.ADPath) {
                    $params.ADPath = join-string -inputObject @($delegation.ADPathLeafOU, $ChildPath) -Separator ","
                    write-Verbose "Deriving ADPath: $($params.ADPath)"
                } elseif ($delegation.ADPath) {
                    $params.ADPath = $delegation.ADPath
                } else {
                    $Params.ADPath = $ChildPath
                }
                @{
                    Path = $Params.ADPath
                    ACL = $params
                }
            }
        }
        if ($ACLList) {Write-Host "`r`nApplying AD Delegations"}
        $textIndent = "|-->"
        $ACLList | group-object path | foreach-object {
            Write-Host ("--->{0,-40}" -f $_.name)
            $_.group.acl | foreach-object { 
                Write-host ("{0,6}{1,-48} on: {2,-36} IOT: {3,-36} {4}" -f $textIndent,$_.Principal,($_.ExtendedRight + $_.TargetObject), $_.AppliesTo, $_.ADRight)
                Add-OUPermission @_
            }
            write-host ""
        }
    }
}