Public/New-Tier0GpoRestriction.ps1

function New-Tier0GpoRestriction {

    <#
        .SYNOPSIS
            Creates and configures security baseline GPOs for tiered administration model.

        .DESCRIPTION
            This function creates and configures Group Policy Objects (GPOs) for implementing
            a tiered administrative model in Active Directory. It establishes security baselines
            for different administration tiers:
            - Domain baseline
            - Domain Controllers baseline
            - Admin/Tier0 baseline
            - Infrastructure (Tier 0, 1, 2) baselines
            - Privileged Access Workstation (PAW) baselines

            The function configures user rights assignments in these GPOs according to security
            best practices for a tiered administrative model, including logon restrictions,
            privilege assignments, and specific permissions for administrative accounts.

        .PARAMETER ConfigXMLFile
            [System.IO.FileInfo] Full path to the XML configuration file.
            Contains all naming conventions, OU structure, and security settings.
            Must be a valid XML file with required schema elements.
            Default: C:\PsScripts\Config.xml

        .PARAMETER DMScripts
            [String] Path to all the scripts and files needed by this function.
            Must contain a subfolder named 'SecTmpl' with security templates.
            Default: C:\PsScripts\

        .EXAMPLE
            New-Tier0GpoRestriction -ConfigXMLFile C:\Scripts\Config.xml -DMScripts C:\Scripts

            Creates and configures all baseline GPOs using the specified configuration file and scripts path.

        .EXAMPLE
            New-Tier0GpoRestriction -ConfigXMLFile C:\Scripts\Config.xml -WhatIf

            Shows what would happen if the command runs without making any changes.

        .INPUTS
            System.IO.FileInfo, System.String

        .OUTPUTS
            System.String

        .NOTES
            Used Functions:
                Name ║ Module/Namespace
                ═══════════════════════════════════════════╬══════════════════════════════
                Import-MyModule ║ EguibarIT
                Get-FunctionDisplay ║ EguibarIT
                Get-AdObjectType ║ EguibarIT
                Set-GpoPrivilegeRight ║ EguibarIT
                Set-GpoFileSecurity ║ EguibarIT
                Set-GpoRegistryKey ║ EguibarIT
                Write-Verbose ║ Microsoft.PowerShell.Utility
                Write-Debug ║ Microsoft.PowerShell.Utility
                Test-Path ║ Microsoft.PowerShell.Management
                Get-Content ║ Microsoft.PowerShell.Management
                Get-ADUser ║ ActiveDirectory
                Get-ADGroup ║ ActiveDirectory

        .NOTES
            Version: 1.1
            DateModified: 30/Apr/2025
            LastModifiedBy: Vicente Rodriguez Eguibar
                            vicente@eguibar.com
                            Eguibar IT
                            http://www.eguibarit.com

        .LINK
            https://github.com/vreguibar/EguibarIT

        .COMPONENT
            EguibarIT

        .ROLE
            Security

        .FUNCTIONALITY
            Group Policy, Tiered Administration, Security Baseline
    #>


    [CmdletBinding(
        SupportsShouldProcess = $true,
        ConfirmImpact = 'High'
    )]
    [OutputType([void])]

    param (

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True,
            ValueFromRemainingArguments = $false,
            HelpMessage = 'Full path to the configuration.xml file',
            Position = 0)]
        [ValidateScript({
                if (-Not ($_ | Test-Path -PathType Leaf) ) {
                    throw ('File not found: {0}' -f $_)
                }
                if ($_.Extension -ne '.xml') {
                    throw ('File must be XML: {0}' -f $_)
                }
                try {
                    [xml]$xml = Get-Content -Path $_ -ErrorAction Stop
                    # Verify required XML elements are present
                    if ($null -eq $xml.n.Admin -or
                        $null -eq $xml.n.Admin.Users -or
                        $null -eq $xml.n.Admin.GPOs -or
                        $null -eq $xml.n.Admin.GG -or
                        $null -eq $xml.n.Admin.OUs -or
                        $null -eq $xml.n.NC) {
                        throw 'XML file is missing required elements (Admin, Users, OUs, GG, GPOs or NC section)'
                    }
                    return $true
                } catch {
                    throw ('Invalid XML file: {0}' -f $_.Exception.Message)
                }
            })]
        [PSDefaultValue(Help = 'Default Value is "C:\PsScripts\Config.xml"',
            Value = 'C:\PsScripts\Config.xml'
        )]
        [Alias('Config', 'XML', 'ConfigXml')]
        [System.IO.FileInfo]
        $ConfigXMLFile,

        [Parameter(Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromRemainingArguments = $false,
            HelpMessage = 'Path to all the scripts and files needed by this function',
            Position = 1)]
        [PSDefaultValue(
            Help = 'Default Value is "C:\PsScripts\"',
            Value = 'C:\PsScripts\'
        )]
        [Alias('ScriptPath')]
        [string]
        $DMScripts = 'C:\PsScripts\',

        [Parameter(Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelineByPropertyName = $false,
            ValueFromRemainingArguments = $false,
            HelpMessage = 'Start transcript logging to DMScripts path with function name',
            Position = 2)]
        [Alias('Transcript', 'Log')]
        [switch]
        $EnableTranscript

    )

    Begin {
        Set-StrictMode -Version Latest

        If (-not $PSBoundParameters.ContainsKey('ConfigXMLFile')) {
            $PSBoundParameters['ConfigXMLFile'] = 'C:\PsScripts\Config.xml'
        } #end If

        If (-not $PSBoundParameters.ContainsKey('DMScripts')) {
            $PSBoundParameters['DMScripts'] = 'C:\PsScripts\'
        } #end If

        # If EnableTranscript is specified, start a transcript
        if ($EnableTranscript) {
            # Ensure DMScripts directory exists
            if (-not (Test-Path -Path $DMScripts -PathType Container)) {
                try {
                    New-Item -Path $DMScripts -ItemType Directory -Force | Out-Null
                    Write-Verbose -Message ('Created transcript directory: {0}' -f $DMScripts)
                } catch {
                    Write-Warning -Message ('Failed to create transcript directory: {0}' -f $_.Exception.Message)
                } #end try-catch
            } #end if

            # Create transcript filename using function name and current date/time
            $TranscriptFile = Join-Path -Path $DMScripts -ChildPath ('New-Tier0GpoRestriction_{0}.LOG' -f (Get-Date -Format 'yyyyMMdd_HHmmss'))

            try {
                Start-Transcript -Path $TranscriptFile -Force -ErrorAction Stop
                Write-Verbose -Message ('Transcript started: {0}' -f $TranscriptFile)
            } catch {
                Write-Warning -Message ('Failed to start transcript: {0}' -f $_.Exception.Message)
            } #end try-catch
        } #end if

        # Initialize logging
        if ($null -ne $Variables -and
            $null -ne $Variables.Header) {

            $txt = ($Variables.Header -f
                (Get-Date).ToString('dd/MMM/yyyy'),
                $MyInvocation.Mycommand,
                (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False)
            )
            Write-Verbose -Message $txt
        } #end If

        ##############################
        # Module imports

        Import-MyModule -Name 'ActiveDirectory' -Verbose:$false
        Import-MyModule -Name 'EguibarIT' -Verbose:$false
        Import-MyModule -Name 'EguibarIT.DelegationPS' -Verbose:$false

        ##############################
        # Variables Definition

        # Parameters variable for splatting CMDlets
        [hashtable]$Splat = [hashtable]::New([StringComparer]::OrdinalIgnoreCase)

        # Progress reporting variables
        [int]$ProgressCounter = 0
        [int]$ProgressTotal = 7  # Total number of main operations

        # Progress splatting for consistent progress reporting
        [hashtable]$ProgressSplat = @{
            Activity        = 'Configuring GPO Restrictions'
            Status          = ''
            PercentComplete = 0
            Id              = 1
        }

        # Collection for groups that need logon rights
        [System.Collections.Generic.List[object]]$NetworkLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$DenyNetworkLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$InteractiveLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$DenyInteractiveLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$RemoteInteractiveLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$DenyRemoteInteractiveLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$BatchLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$DenyBatchLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$ServiceLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$DenyServiceLogon = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$Backup = [System.Collections.Generic.List[object]]::New()
        [System.Collections.Generic.List[object]]$ArrayList = [System.Collections.Generic.List[object]]::New()

        # Load the XML configuration file
        try {
            [xml]$ConfXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile'])
            Write-Verbose -Message ('Successfully loaded configuration file: {0}' -f $PSBoundParameters['ConfigXMLFile'])
        } catch {
            Write-Error -Message ('Error reading XML file: {0}' -f $_.Exception.Message)
            throw
        } #end Try-Catch


        # Load naming conventions from XML
        [hashtable]$NC = @{
            'sl'    = $confXML.n.NC.LocalDomainGroupPreffix
            'sg'    = $confXML.n.NC.GlobalGroupPreffix
            'su'    = $confXML.n.NC.UniversalGroupPreffix
            'Delim' = $confXML.n.NC.Delimiter
            'T0'    = $confXML.n.NC.AdminAccSufix0
            'T1'    = $confXML.n.NC.AdminAccSufix1
            'T2'    = $confXML.n.NC.AdminAccSufix2
        }


        #region Users
        $AdminName = Get-SafeVariable -Name 'AdminName' -CreateIfNotExist {
            try {
                Get-ADUser -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-500' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Administrator name: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $NewAdminName = Get-SafeVariable -Name 'NewAdminExists' -CreateIfNotExist {
            $newAdminName = $confXML.n.Admin.users.NEWAdmin.Name
            if (-not [string]::IsNullOrEmpty($newAdminName)) {
                Get-AdObjectType -Identity $newAdminName
            } else {
                $null
            }
        }
        #endregion Users

        #region Well-Known groups Variables
        $Administrators = Get-SafeVariable -Name 'Administrators' -CreateIfNotExist {
            try {
                Get-ADGroup -Identity 'S-1-5-32-544'
            } catch {
                Write-Debug -Message ('Failed to retrieve Administrators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $DomainAdmins = Get-SafeVariable -Name 'DomainAdmins' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-512' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Domain Admins group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $EnterpriseAdmins = Get-SafeVariable -Name 'EnterpriseAdmins' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-519' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Enterprise Admins group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $SchemaAdmins = Get-SafeVariable -Name 'SchemaAdmins' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-518' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Schema Admins group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $AccountOperators = Get-SafeVariable -Name 'AccountOperators' -CreateIfNotExist {
            try {
                Get-ADGroup -Identity 'S-1-5-32-548'
            } catch {
                Write-Debug -Message ('Failed to retrieve Account Operators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $BackupOperators = Get-SafeVariable -Name 'BackupOperators' -CreateIfNotExist {
            try {
                Get-ADGroup -Identity 'S-1-5-32-551'
            } catch {
                Write-Debug -Message ('Failed to retrieve Backup Operators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $PrintOperators = Get-SafeVariable -Name 'PrintOperators' -CreateIfNotExist {
            try {
                Get-ADGroup -Identity 'S-1-5-32-550'
            } catch {
                Write-Debug -Message ('Failed to retrieve Print Operators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $ServerOperators = Get-SafeVariable -Name 'ServerOperators' -CreateIfNotExist {
            try {
                Get-ADGroup -Identity 'S-1-5-32-549'
            } catch {
                Write-Debug -Message ('Failed to retrieve Server Operators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $CryptoOperators = Get-SafeVariable -Name 'CryptoOperators' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-32-569' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Cryptographic Operators group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $DomainControllers = Get-SafeVariable -Name 'DomainControllers' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-516' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Domain Controllers group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $RODC = Get-SafeVariable -Name 'RODC' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-521' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Read Only Domain Controllers group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $GPOCreatorsOwner = Get-SafeVariable -Name 'GPOCreatorsOwner' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-520' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Group Policy Creators Owner group: {0}' -f $_.Exception.Message)
                $null
            }
        }

        $LocalAccount = Get-SafeVariable -Name 'LocalAccount' -CreateIfNotExist {
            try {
                Get-ADGroup -Filter * | Where-Object { $_.SID -like 'S-1-5-113' }
            } catch {
                Write-Debug -Message ('Failed to retrieve Local Account group: {0}' -f $_.Exception.Message)
                $null
            }
        }
        #endregion Well-Known groups Variables

        #region Global groups Variables

        $SG_AdAdmins = Get-SafeVariable -Name 'SG_AdAdmins' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.AdAdmins.Name)
            Get-AdObjectType -Identity $groupName
        }

        $SG_Tier0Admins = Get-SafeVariable -Name 'SG_Tier0Admins' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name)
            Get-AdObjectType -Identity $groupName
        }

        $SG_Tier1Admins = Get-SafeVariable -Name 'SG_Tier1Admins' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name)
            Get-AdObjectType -Identity $groupName
        }

        $SG_Tier2Admins = Get-SafeVariable -Name 'SG_Tier2Admins' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name)
            Get-AdObjectType -Identity $groupName
        }

        # Tier Service Account Groups
        # ToDo: the GetSafeVariable is finding the variable, but variable has old DN. Interim fix filling the variable again
        $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name)
        $SG_Tier0ServiceAccount = Get-AdObjectType -Identity $groupName


        # ToDo: the GetSafeVariable is finding the variable, but variable has old DN. Interim fix filling the variable again
        $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name)
        $SG_Tier1ServiceAccount = Get-AdObjectType -Identity $groupName

        # ToDo: the GetSafeVariable is finding the variable, but variable has old DN. Interim fix filling the variable again
        $groupName = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name)
        $SG_Tier2ServiceAccount = Get-AdObjectType -Identity $groupName
        #endregion Global groups Variables

        #region Local groups Variables
        $SL_PAWM = Get-SafeVariable -Name 'SL_PAWM' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PAWM.Name)
            Get-AdObjectType -Identity $groupName
        }

        $SL_PISM = Get-SafeVariable -Name 'SL_PISM' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PISM.Name)
            Get-AdObjectType -Identity $groupName
        }

        $SL_DcManagement = Get-SafeVariable -Name 'SL_DcManagement' -CreateIfNotExist {
            $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.DcManagement.Name)
            Get-AdObjectType -Identity $groupName
        }
        #endregion Local groups Variables

    } #end Begin

    Process {
        if ($PSCmdlet.ShouldProcess('Active Directory', 'Configure Domain Baseline GPO Restrictions')) {
            try {
                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring Domain Baseline GPO Restrictions'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                Write-Verbose -Message 'Configuring Domain Baseline GPO Restrictions'

                # Access this computer from the network
                $NetworkLogon.Clear()
                [void]$NetworkLogon.Add($Administrators)
                [void]$NetworkLogon.Add('Authenticated Users')
                [void]$NetworkLogon.Add('Enterprise Domain Controllers')

                # Deny access to this computer from the network
                $DenyNetworkLogon.Clear()
                [void]$DenyNetworkLogon.Add('ANONYMOUS LOGON')
                [void]$DenyNetworkLogon.Add($LocalAccount)
                [void]$DenyNetworkLogon.Add('Local Account and member of administrators group')

                # Deny Logon Locally
                $DenyInteractiveLogon.Clear()
                [void]$DenyInteractiveLogon.Add('Guests')
                if ($null -ne $SG_Tier0ServiceAccount) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier0ServiceAccount)
                }
                if ($null -ne $SG_Tier1ServiceAccount) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier1ServiceAccount)
                }
                if ($null -ne $SG_Tier2ServiceAccount) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier2ServiceAccount)
                }

                # Deny logon through RDS/TerminalServices
                $DenyRemoteInteractiveLogon.Clear()
                [void]$DenyRemoteInteractiveLogon.Add($LocalAccount)
                [void]$DenyRemoteInteractiveLogon.Add('Guests')
                [void]$DenyRemoteInteractiveLogon.Add($AccountOperators)
                [void]$DenyRemoteInteractiveLogon.Add($BackupOperators)
                [void]$DenyRemoteInteractiveLogon.Add($PrintOperators)
                [void]$DenyRemoteInteractiveLogon.Add($ServerOperators)
                [void]$DenyRemoteInteractiveLogon.Add($DomainControllers)
                [void]$DenyRemoteInteractiveLogon.Add($RODC)
                if ($null -ne $SG_Tier0ServiceAccount) {
                    [void]$DenyRemoteInteractiveLogon.Add($SG_Tier0ServiceAccount)
                }
                if ($null -ne $SG_Tier1ServiceAccount) {
                    [void]$DenyRemoteInteractiveLogon.Add($SG_Tier1ServiceAccount)
                }
                if ($null -ne $SG_Tier2ServiceAccount) {
                    [void]$DenyRemoteInteractiveLogon.Add($SG_Tier2ServiceAccount)
                }
                # Logon as a Service
                # Deny Logon as a Batch job / Deny Logon as a Service
                $DenyBatchLogon.Clear()
                [void]$DenyBatchLogon.Add($SchemaAdmins)
                [void]$DenyBatchLogon.Add($EnterpriseAdmins)
                [void]$DenyBatchLogon.Add($DomainAdmins)
                [void]$DenyBatchLogon.Add($Administrators)
                [void]$DenyBatchLogon.Add($AccountOperators)
                [void]$DenyBatchLogon.Add($BackupOperators)
                [void]$DenyBatchLogon.Add($PrintOperators)
                [void]$DenyBatchLogon.Add($ServerOperators)
                [void]$DenyBatchLogon.Add($DomainControllers)
                [void]$DenyBatchLogon.Add($RODC)
                [void]$DenyBatchLogon.Add($GPOCreatorsOwner)
                [void]$DenyBatchLogon.Add($CryptoOperators)
                [void]$DenyBatchLogon.Add('Guests')
                if ($null -ne $SG_Tier0Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier0Admins)
                }
                if ($null -ne $SG_Tier1Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier1Admins)
                }
                if ($null -ne $SG_Tier2Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier2Admins)
                }
                if ($null -ne $AdminName) {
                    [void]$DenyBatchLogon.Add($AdminName)
                }
                if ($null -ne $NewAdminName) {
                    [void]$DenyBatchLogon.Add($NewAdminName)
                }

                # Logon as a Service
                $ServiceLogon.Clear()
                [void]$ServiceLogon.Add('Network Service')
                [void]$ServiceLogon.Add('All Services')

                <#
                # NOT Modified for this GPO

                $InteractiveLogon = [System.Collections.Generic.List[object]]::New()
                $RemoteInteractiveLogon = [System.Collections.Generic.List[object]]::New()
                $DenyBatchLogon = [System.Collections.Generic.List[object]]::New()
                $DenyServiceLogon = [System.Collections.Generic.List[object]]::New()
                $MachineAccount = [System.Collections.Generic.List[object]]::New()
                $IncreaseQuota = [System.Collections.Generic.List[object]]::New()
                $Backup = [System.Collections.Generic.List[object]]::New()
                $ChangeNotify = [System.Collections.Generic.List[object]]::New()
                $SystemTime = [System.Collections.Generic.List[object]]::New()
                $TimeZone = [System.Collections.Generic.List[object]]::New()
                $CreatePagefile = [System.Collections.Generic.List[object]]::New()
                $CreateGlobal = [System.Collections.Generic.List[object]]::New()
                $CreateSymbolicLink = [System.Collections.Generic.List[object]]::New()
                $EnableDelegation = [System.Collections.Generic.List[object]]::New()
                $RemoteShutdown = [System.Collections.Generic.List[object]]::New()
                $Audit = [System.Collections.Generic.List[object]]::New()
                $Impersonate = [System.Collections.Generic.List[object]]::New()
                $IncreaseWorkingSet = [System.Collections.Generic.List[object]]::New()
                $IncreaseBasePriority = [System.Collections.Generic.List[object]]::New()
                $LoadDriver = [System.Collections.Generic.List[object]]::New()
                $AuditSecurity = [System.Collections.Generic.List[object]]::New()
                $Relabel = [System.Collections.Generic.List[object]]::New()
                $SystemEnvironment = [System.Collections.Generic.List[object]]::New()
                $DelegateSessionUserImpersonate = [System.Collections.Generic.List[object]]::New()
                $ManageVolume = [System.Collections.Generic.List[object]]::New()
                $ProfileSingleProcess = [System.Collections.Generic.List[object]]::New()
                $SystemProfile = [System.Collections.Generic.List[object]]::New()
                $Undock = [System.Collections.Generic.List[object]]::New()
                $AssignPrimaryToken = [System.Collections.Generic.List[object]]::New()
                $Restore = [System.Collections.Generic.List[object]]::New()
                $Shutdown = [System.Collections.Generic.List[object]]::New()
                $SyncAgent = [System.Collections.Generic.List[object]]::New()
                $TakeOwnership = [System.Collections.Generic.List[object]]::New()
            #>


                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify                = 'C-Baseline'
                    NetworkLogon               = $NetworkLogon
                    DenyNetworkLogon           = $DenyNetworkLogon
                    DenyInteractiveLogon       = $DenyInteractiveLogon
                    DenyRemoteInteractiveLogon = $DenyRemoteInteractiveLogon
                    DenyBatchLogon             = $DenyBatchLogon
                    ServiceLogon               = $ServiceLogon
                    Confirm                    = $false
                    Verbose                    = $true
                    Debug                      = $true
                }
                Set-GpoPrivilegeRight @Splat
                Write-Verbose -Message 'Domain Baseline GPO configured successfully'

            } catch {

                Write-Error -Message ('Error configuring Domain Baseline GPO: {0}' -f $_.Exception.Message)

            } #end Try-Catch
        } #end If ShouldProcess

        if ($PSCmdlet.ShouldProcess('Active Directory', 'Configure DomainControllers Baseline GPO Restrictions')) {
            try {
                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring Domain Controllers Baseline GPO restrictions'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                Write-Verbose -Message 'Configuring Domain Controllers Baseline GPO restrictions'

                # Access this computer from the network
                $NetworkLogon.Clear()
                [void]$NetworkLogon.Add($Administrators)
                [void]$NetworkLogon.Add('Authenticated Users')
                [void]$NetworkLogon.Add('Enterprise Domain Controllers')

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices
                $InteractiveLogon.Clear()
                [void]$InteractiveLogon.Add($SchemaAdmins)
                [void]$InteractiveLogon.Add($EnterpriseAdmins)
                [void]$InteractiveLogon.Add($DomainAdmins)
                [void]$InteractiveLogon.Add($Administrators)
                if ($null -ne $AdminName) {
                    [void]$InteractiveLogon.Add($AdminName)
                }
                if ($null -ne $NewAdminName) {
                    [void]$InteractiveLogon.Add($NewAdminName)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$InteractiveLogon.Add($SG_Tier0Admins)
                }
                $RemoteInteractiveLogon.Clear()
                $RemoteInteractiveLogon = $InteractiveLogon


                # Deny Logon Locally / Deny Logon through RDP/TerminalServices
                $DenyInteractiveLogon.Clear()
                [void]$DenyInteractiveLogon.Add($AccountOperators)
                [void]$DenyInteractiveLogon.Add($BackupOperators)
                [void]$DenyInteractiveLogon.Add($PrintOperators)
                [void]$DenyInteractiveLogon.Add('Guests')
                if ($null -ne $SG_Tier1Admins) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier1Admins)
                }
                if ($null -ne $SG_Tier2Admins) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier2Admins)
                }
                if ($null -ne $SG_Tier1ServiceAccount) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier1ServiceAccount)
                }
                if ($null -ne $SG_Tier2ServiceAccount) {
                    [void]$DenyInteractiveLogon.Add($SG_Tier2ServiceAccount)
                }
                $DenyRemoteInteractiveLogon.Clear()
                $DenyRemoteInteractiveLogon = $DenyInteractiveLogon


                # Deny Logon as a Batch job / Deny Logon as a Service
                $DenyBatchLogon.Clear()
                [void]$DenyBatchLogon.Add($SchemaAdmins)
                [void]$DenyBatchLogon.Add($EnterpriseAdmins)
                [void]$DenyBatchLogon.Add($DomainAdmins)
                [void]$DenyBatchLogon.Add($Administrators)
                [void]$DenyBatchLogon.Add($AccountOperators)
                [void]$DenyBatchLogon.Add($BackupOperators)
                [void]$DenyBatchLogon.Add($PrintOperators)
                [void]$DenyBatchLogon.Add($ServerOperators)
                [void]$DenyBatchLogon.Add($GPOCreatorsOwner)
                [void]$DenyBatchLogon.Add($CryptoOperators)
                [void]$DenyBatchLogon.Add('Guests')
                if ($null -ne $AdminName) {
                    [void]$DenyBatchLogon.Add($AdminName)
                }
                if ($null -ne $NewAdminName) {
                    [void]$DenyBatchLogon.Add($NewAdminName)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier0Admins)
                }
                if ($null -ne $SG_Tier1Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier1Admins)
                }
                if ($null -ne $SG_Tier2Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier2Admins)
                }
                if ($null -ne $SG_Tier1ServiceAccount) {
                    [void]$DenyBatchLogon.Add($SG_Tier1ServiceAccount)
                }
                if ($null -ne $SG_Tier2ServiceAccount) {
                    [void]$DenyBatchLogon.Add($SG_Tier2ServiceAccount)
                }
                $DenyServiceLogon.Clear()
                $DenyServiceLogon = $DenyBatchLogon


                # Back up files and directories / Bypass traverse checking / Create Global Objects / Create symbolic links
                # Change System Time / Change Time Zone / Force shutdown from a remote system
                # Create Page File / Enable computer and user accounts to be trusted for delegation
                # Impersonate a client after authentication / Load and unload device drivers
                # Increase scheduling priority / Manage auditing and security log
                # Modify firmware environment values / Perform volume maintenance tasks
                # Profile single process / Profile system performance / Restore files and directories
                # Shut down the system / Take ownership of files or other objects
                $Backup.Clear()
                [void]$Backup.Add($Administrators)
                if ($null -ne $SG_Tier0Admins) {
                    [void]$Backup.Add($SG_Tier0Admins)
                }
                if ($null -ne $SG_AdAdmins) {
                    [void]$Backup.Add($SG_AdAdmins)
                }

                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify                = 'C-{0}-Baseline' -f $confXML.n.Admin.GPOs.DCBaseline.Name
                    NetworkLogon               = $NetworkLogon
                    InteractiveLogon           = $InteractiveLogon
                    RemoteInteractiveLogon     = $RemoteInteractiveLogon
                    DenyRemoteInteractiveLogon = $DenyRemoteInteractiveLogon
                    DenyInteractiveLogon       = $DenyInteractiveLogon
                    BatchLogon                 = @($SG_Tier0ServiceAccount, 'Performance Log Users')
                    ServiceLogon               = @($SG_Tier0ServiceAccount, 'Network Service')
                    DenyServiceLogon           = $DenyServiceLogon
                    DenyBatchLogon             = $DenyBatchLogon
                    Backup                     = $Backup
                    ChangeNotify               = @(
                        $Administrators,
                        $SG_Tier0Admins,
                        $SG_AdAdmins,
                        'LOCAL SERVICE',
                        'NETWORK SERVICE'
                    )
                    CreateGlobal               = @(
                        $Administrators,
                        $SG_Tier0Admins,
                        $SG_AdAdmins,
                        'LOCAL SERVICE',
                        'NETWORK SERVICE'
                    )
                    Systemtime                 = @($Administrators, $SG_Tier0Admins, $SG_AdAdmins, 'LOCAL SERVICE')
                    TimeZone                   = $Backup
                    CreatePagefile             = $Backup
                    CreateSymbolicLink         = $Backup
                    EnableDelegation           = $Backup
                    RemoteShutDown             = $Backup
                    Impersonate                = @(
                        $Administrators,
                        $SG_Tier0Admins,
                        $SG_AdAdmins,
                        'LOCAL SERVICE',
                        'NETWORK SERVICE',
                        'SERVICE'
                    )
                    IncreaseBasePriority       = $Backup
                    LoadDriver                 = $Backup
                    AuditSecurity              = $Backup
                    SystemEnvironment          = $Backup
                    ManageVolume               = $Backup
                    ProfileSingleProcess       = $Backup
                    SystemProfile              = $Backup
                    AssignPrimaryToken         = @('LOCAL SERVICE', 'NETWORK SERVICE')
                    Restore                    = $Backup
                    Shutdown                   = $Backup
                    TakeOwnership              = $Backup
                    Confirm                    = $false
                    Verbose                    = $true
                    Debug                      = $true
                }
                Set-GpoPrivilegeRight @Splat


                # Additional configuration for File permissions and Registry permissions
                # these settings are intended to "delegate" software maintenance tasks to Dc_Management group
                Write-Verbose -Message 'Configuring additional File and Registry permissions'

                # File Security
                $Splat = @{
                    GpoToModify = 'C-{0}-Baseline' -f $confXML.n.Admin.GPOs.DCBaseline.Name
                    Group       = $SL_DcManagement
                }
                Set-GpoFileSecurity @Splat

                # Registry Keys
                $Splat = @{
                    GpoToModify = 'C-{0}-Baseline' -f $confXML.n.Admin.GPOs.DCBaseline.Name
                    Group       = $SL_DcManagement
                }
                Set-GpoRegistryKey @Splat

                Write-Verbose -Message 'Domain Controllers Baseline GPO configured successfully'

            } catch {

                Write-Error -Message ('Error configuring Domain Controllers Baseline GPO: {0}' -f $_.Exception.Message)

            } #end Try-Catch
        } #end If ShouldProcess

        if ($PSCmdlet.ShouldProcess('Active Directory', 'Configure Admin/Tier0 Baseline GPO Restrictions')) {
            try {
                Write-Verbose -Message 'Configuring Admin/Tier0 Baseline GPO restrictions'

                #region Admin Area = Baseline

                # Logon as a Batch job / Logon as a Service
                $BatchLogon.Clear()
                [void]$BatchLogon.Add('Network Service')
                [void]$BatchLogon.Add('All Services')
                if ($null -ne $SG_Tier0ServiceAccount) {
                    [void]$BatchLogon.Add($SG_Tier0ServiceAccount)
                }
                $ServiceLogon.Clear()
                $ServiceLogon = $BatchLogon

                # Deny Logon as a Batch job / Deny Logon as a Service
                $DenyBatchLogon.Clear()
                [void]$DenyBatchLogon.Add($SchemaAdmins)
                [void]$DenyBatchLogon.Add($EnterpriseAdmins)
                [void]$DenyBatchLogon.Add($DomainAdmins)
                [void]$DenyBatchLogon.Add($Administrators)
                [void]$DenyBatchLogon.Add($AccountOperators)
                [void]$DenyBatchLogon.Add($BackupOperators)
                [void]$DenyBatchLogon.Add($PrintOperators)
                [void]$DenyBatchLogon.Add($ServerOperators)
                [void]$DenyBatchLogon.Add($RODC)
                [void]$DenyBatchLogon.Add($GPOCreatorsOwner)
                [void]$DenyBatchLogon.Add($CryptoOperators)
                [void]$DenyBatchLogon.Add('Guests')
                if ($null -ne $AdminName) {
                    [void]$DenyBatchLogon.Add($AdminName)
                }
                if ($null -ne $NewAdminName) {
                    [void]$DenyBatchLogon.Add($NewAdminName)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier0Admins)
                }
                if ($null -ne $SG_Tier1Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier1Admins)
                }
                if ($null -ne $SG_Tier2Admins) {
                    [void]$DenyBatchLogon.Add($SG_Tier2Admins)
                }
                if ($null -ne $SG_Tier1ServiceAccount) {
                    [void]$DenyBatchLogon.Add($SG_Tier1ServiceAccount)
                }
                if ($null -ne $SG_Tier2ServiceAccount) {
                    [void]$DenyBatchLogon.Add($SG_Tier2ServiceAccount)
                }
                $DenyServiceLogon.Clear()
                $DenyServiceLogon = $DenyBatchLogon


                $ArrayList.Clear()
                [void]$ArrayList.Add($Administrators)
                if ($null -ne $SG_Tier0Admins) {
                    [void]$ArrayList.Add($SG_Tier0Admins)
                }
                if ($null -ne $SG_AdAdmins) {
                    [void]$ArrayList.Add($SG_AdAdmins)
                }

                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify          = 'C-{0}-Baseline' -f $confXML.n.Admin.GPOs.Adminbaseline.Name
                    BatchLogon           = $BatchLogon
                    ServiceLogon         = $ServiceLogon
                    DenyBatchLogon       = $DenyBatchLogon
                    DenyServiceLogon     = $DenyServiceLogon
                    MachineAccount       = $ArrayList
                    Backup               = $ArrayList
                    SystemTime           = @($Administrators, $SG_Tier0Admins, $SG_AdAdmins, 'LOCAL SERVICE')
                    TimeZone             = $ArrayList
                    CreatePagefile       = $ArrayList
                    CreateSymbolicLink   = $ArrayList
                    RemoteShutdown       = $ArrayList
                    IncreaseBasePriority = $ArrayList
                    LoadDriver           = $ArrayList
                    AuditSecurity        = $ArrayList
                    SystemEnvironment    = $ArrayList
                    ManageVolume         = $ArrayList
                    ProfileSingleProcess = $ArrayList
                    SystemProfile        = $ArrayList
                    Restore              = $ArrayList
                    Shutdown             = $ArrayList
                    TakeOwnership        = $ArrayList
                    Confirm              = $false
                    Verbose              = $true
                    Debug                = $true
                }
                Write-Verbose -Message 'Applying Admin/Tier0 Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Admin Area = Baseline



                #region HOUSEKEEPING

                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring Housekeeping LOCKDOWN GPO'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                # Access this computer from the network / Allow Logon Locally
                $NetworkLogon.Clear()
                [void]$NetworkLogon.Add($DomainAdmins)
                [void]$NetworkLogon.Add($Administrators)
                if ($null -ne $SG_Tier0Admins) {
                    [void]$NetworkLogon.Add($SG_Tier0Admins)
                }
                $InteractiveLogon.Clear()
                $InteractiveLogon = $NetworkLogon

                # Logon as a Batch job / Logon as a Service
                $BatchLogon.Clear()
                [void]$BatchLogon.Add('Network Service')
                [void]$BatchLogon.Add('All Services')
                if ($null -ne $SG_Tier0ServiceAccount) {
                    [void]$BatchLogon.Add($SG_Tier0ServiceAccount)
                }
                $ServiceLogon.Clear()
                $ServiceLogon = $BatchLogon

                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify      = 'C-Housekeeping-LOCKDOWN'
                    NetworkLogon     = $NetworkLogon
                    InteractiveLogon = $InteractiveLogon
                    BatchLogon       = $BatchLogon
                    ServiceLogon     = $ServiceLogon
                    Confirm          = $false
                    Verbose          = $true
                    Debug            = $true
                }

                Write-Verbose -Message 'Applying Housekeeping Lockdown GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion HOUSEKEEPING



                #region Infrastructure

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices
                $InteractiveLogon.Clear()
                [void]$InteractiveLogon.Add($DomainAdmins)
                [void]$InteractiveLogon.Add($Administrators)
                if ($null -ne $SL_PISM) {
                    [void]$InteractiveLogon.Add($SL_PISM)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$InteractiveLogon.Add($SG_Tier0Admins)
                }
                $RemoteInteractiveLogon.Clear()
                $RemoteInteractiveLogon = $InteractiveLogon


                $ArrayList.Clear()
                [void]$ArrayList.Add($Administrators)
                if ($null -ne $SG_Tier0Admins) {
                    [void]$ArrayList.Add($SG_Tier0Admins)
                }
                if ($null -ne $SL_PISM) {
                    [void]$ArrayList.Add($SG_AdAdmins)
                }


                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0OU.Name
                    InteractiveLogon       = $InteractiveLogon
                    RemoteInteractiveLogon = $RemoteInteractiveLogon
                    MachineAccount         = $ArrayList
                    Backup                 = $ArrayList
                    CreateGlobal           = @($Administrators, $SG_Tier0Admins, $SG_AdAdmins, 'LOCAL SERVICE', 'NETWORK SERVICE')
                    SystemTime             = @($Administrators, $SG_Tier0Admins, $SG_AdAdmins, 'LOCAL SERVICE')
                    TimeZone               = $ArrayList
                    CreatePagefile         = $ArrayList
                    CreateSymbolicLink     = $ArrayList
                    RemoteShutdown         = $ArrayList
                    Impersonate            = @(
                        $Administrators,
                        $SG_Tier0Admins,
                        $SG_AdAdmins,
                        'LOCAL SERVICE',
                        'NETWORK SERVICE',
                        'SERVICE'
                    )
                    IncreaseBasePriority   = $ArrayList
                    LoadDriver             = $ArrayList
                    AuditSecurity          = $ArrayList
                    SystemEnvironment      = $ArrayList
                    ManageVolume           = $ArrayList
                    ProfileSingleProcess   = $ArrayList
                    SystemProfile          = $ArrayList
                    Restore                = $ArrayList
                    Shutdown               = $ArrayList
                    TakeOwnership          = $ArrayList
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Infrastructure Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Infrastructure


                #Region Tier0 Infrastructure

                # Allow Logon Locally / Allow Logon throug RDP/TerminalServices
                $InteractiveLogon.Clear()
                [void]$InteractiveLogon.Add($DomainAdmins)
                [void]$InteractiveLogon.Add($Administrators)
                if ($null -ne $SL_PISM) {
                    [void]$InteractiveLogon.Add($SL_PISM)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$InteractiveLogon.Add($SG_Tier0Admins)
                }
                $RemoteInteractiveLogon.Clear()
                $RemoteInteractiveLogon = $InteractiveLogon


                # Logon as a Batch job / Logon as a Service
                $BatchLogon.Clear()
                [void]$BatchLogon.Add('Network Service')
                [void]$BatchLogon.Add('All Services')
                if ($null -ne $SG_Tier0ServiceAccount) {
                    [void]$BatchLogon.Add($SG_Tier0ServiceAccount)
                }
                $ServiceLogon.Clear()
                $ServiceLogon = $BatchLogon

                # Modify all rights in one shot
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0OU.Name
                    InteractiveLogon       = $InteractiveLogon
                    RemoteInteractiveLogon = $RemoteInteractiveLogon
                    BatchLogon             = $BatchLogon
                    ServiceLogon           = $ServiceLogon
                    RemoteShutdown         = $InteractiveLogon
                    SystemTime             = $InteractiveLogon
                    ChangeNotify           = $InteractiveLogon
                    ManageVolume           = $InteractiveLogon
                    SystemProfile          = $InteractiveLogon
                    Shutdown               = $InteractiveLogon
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Tier0 Infrastructure Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier0 Infrastructure



                #region Tier1 Infrastructure

                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring Tier1 Infrastructure GPO restrictions'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices / Logon as a Batch job / Logon as a Service
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1OU.Name
                    InteractiveLogon       = @($SG_Tier1Admins, $Administrators)
                    RemoteInteractiveLogon = $SG_Tier1Admins
                    BatchLogon             = $SG_Tier1ServiceAccount
                    ServiceLogon           = $SG_Tier1ServiceAccount
                    RemoteShutdown         = $SG_Tier1Admins
                    SystemTime             = $SG_Tier1Admins
                    ChangeNotify           = $SG_Tier1Admins
                    ManageVolume           = $SG_Tier1Admins
                    SystemProfile          = $SG_Tier1Admins
                    Shutdown               = $SG_Tier1Admins
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Tier1 Infrastructure Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier1 Infrastructure



                #region Tier2 Infrastructure

                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring Tier2 Infrastructure GPO restrictions'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices / Logon as a Batch job / Logon as a Service
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT2OU.Name
                    InteractiveLogon       = @($SG_Tier2Admins, $Administrators)
                    RemoteInteractiveLogon = $SG_Tier2Admins
                    BatchLogon             = $SG_Tier2ServiceAccount
                    ServiceLogon           = $SG_Tier2ServiceAccount
                    RemoteShutdown         = $SG_Tier2Admins
                    SystemTime             = $SG_Tier2Admins
                    ChangeNotify           = $SG_Tier2Admins
                    ManageVolume           = $SG_Tier2Admins
                    SystemProfile          = $SG_Tier2Admins
                    Shutdown               = $SG_Tier2Admins
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Tier2 Infrastructure Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier2 Infrastructure




                #region Staging Infrastructure

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices
                $ArrayList.Clear()
                [void]$ArrayList.Add($DomainAdmins)
                [void]$ArrayList.Add($Administrators)
                if ($null -ne $SL_PISM) {
                    [void]$ArrayList.Add($SL_PISM)
                }
                if ($null -ne $SG_Tier0Admins) {
                    [void]$ArrayList.Add($SG_Tier0Admins)
                }
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraStagingOU.name
                    InteractiveLogon       = $ArrayList
                    RemoteInteractiveLogon = $ArrayList
                    RemoteShutdown         = $ArrayList
                    SystemTime             = $ArrayList
                    ChangeNotify           = $ArrayList
                    ManageVolume           = $ArrayList
                    SystemProfile          = $ArrayList
                    Shutdown               = $ArrayList
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Staging Infrastructure Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Staging Infrastructure



                #region Staging PAWs

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices
                $Splat = @{
                    GpoToModify            = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawStagingOU.Name
                    InteractiveLogon       = @($SL_PAWM, $Administrators)
                    RemoteInteractiveLogon = $SL_PAWM
                    RemoteShutdown         = $SL_PAWM
                    SystemTime             = $SL_PAWM
                    ChangeNotify           = $SL_PAWM
                    ManageVolume           = $SL_PAWM
                    SystemProfile          = $SL_PAWM
                    Shutdown               = $SL_PAWM
                    Confirm                = $false
                    Verbose                = $true
                    Debug                  = $true
                }

                Write-Verbose -Message 'Applying Staging PAWs Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Staging PAWs




                #region Tier0 PAWs

                # Update progress
                $ProgressCounter++
                $ProgressSplat['Status'] = 'Configuring PAW (Privileged Access Workstation) restrictions'
                $ProgressSplat['PercentComplete'] = ($ProgressCounter / $ProgressTotal) * 100
                Write-Progress @ProgressSplat

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices / Logon as a Batch job / Logon as a Service
                $Splat = @{
                    GpoToModify                = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT0OU.Name
                    InteractiveLogon           = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    RemoteInteractiveLogon     = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    BatchLogon                 = $SG_Tier0ServiceAccount
                    ServiceLogon               = $SG_Tier0ServiceAccount
                    DenyInteractiveLogon       = @($SG_Tier1Admins, $SG_Tier2Admins)
                    DenyRemoteInteractiveLogon = @($SG_Tier1Admins, $SG_Tier2Admins)
                    DenyBatchLogon             = @($SG_Tier1ServiceAccount, $SG_Tier2ServiceAccount)
                    DenyServiceLogon           = @($SG_Tier1ServiceAccount, $SG_Tier2ServiceAccount)
                    RemoteShutdown             = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    SystemTime                 = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    ChangeNotify               = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    ManageVolume               = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    SystemProfile              = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    Shutdown                   = @($SL_PAWM, $Administrators, $SG_Tier0Admins, $AdminName, $NewAdminName)
                    Confirm                    = $false
                    Verbose                    = $true
                    Debug                      = $true
                }

                Write-Verbose -Message 'Applying Tier0 PAWs Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier0 PAWs



                #region Tier1 PAWs

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices / Logon as a Batch job / Logon as a Service
                # Deny Allow Logon Locally / Deny Allow Logon through RDP/TerminalServices
                # Deny Logon as a Batch job / Deny Logon as a Service
                $Splat = @{
                    GpoToModify                = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT1OU.Name
                    InteractiveLogon           = @($SG_Tier1Admins, $Administrators)
                    RemoteInteractiveLogon     = $SG_Tier1Admins
                    BatchLogon                 = $SG_Tier1ServiceAccount
                    ServiceLogon               = $SG_Tier1ServiceAccount
                    DenyInteractiveLogon       = @($SG_Tier0Admins, $SG_Tier2Admins)
                    DenyRemoteInteractiveLogon = @($SG_Tier0Admins, $SG_Tier2Admins)
                    DenyBatchLogon             = @($SG_Tier0ServiceAccount, $SG_Tier2ServiceAccount)
                    DenyServiceLogon           = @($SG_Tier0ServiceAccount, $SG_Tier2ServiceAccount)
                    RemoteShutdown             = $SG_Tier1Admins
                    SystemTime                 = $SG_Tier1Admins
                    ChangeNotify               = $SG_Tier1Admins
                    ManageVolume               = $SG_Tier1Admins
                    SystemProfile              = $SG_Tier1Admins
                    Shutdown                   = $SG_Tier1Admins
                    Confirm                    = $false
                    Verbose                    = $true
                    Debug                      = $true
                }

                Write-Verbose -Message 'Applying Tier1 PAWs Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier1 PAWs



                #region Tier2 PAWs

                # Allow Logon Locally / Allow Logon through RDP/TerminalServices / Logon as a Batch job / Logon as a Service
                # Deny Allow Logon Locally / Deny Allow Logon through RDP/TerminalServices
                # Deny Logon as a Batch job / Deny Logon as a Service
                $Splat = @{
                    GpoToModify                = 'C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT2OU.Name
                    InteractiveLogon           = @($SG_Tier2Admins, $Administrators)
                    RemoteInteractiveLogon     = $SG_Tier2Admins
                    BatchLogon                 = $SG_Tier2ServiceAccount
                    ServiceLogon               = $SG_Tier2ServiceAccount
                    DenyInteractiveLogon       = @($SG_Tier0Admins, $SG_Tier1Admins)
                    DenyRemoteInteractiveLogon = @($SG_Tier0Admins, $SG_Tier1Admins)
                    DenyBatchLogon             = @($SG_Tier0ServiceAccount, $SG_Tier1ServiceAccount)
                    DenyServiceLogon           = @($SG_Tier0ServiceAccount, $SG_Tier1ServiceAccount)
                    RemoteShutdown             = $SG_Tier2Admins
                    SystemTime                 = $SG_Tier2Admins
                    ChangeNotify               = $SG_Tier2Admins
                    ManageVolume               = $SG_Tier2Admins
                    SystemProfile              = $SG_Tier2Admins
                    Shutdown                   = $SG_Tier2Admins
                    Confirm                    = $false
                    Verbose                    = $true
                    Debug                      = $true
                }

                Write-Verbose -Message 'Applying Tier2 PAWs Baseline GPO settings'
                Set-GpoPrivilegeRight @Splat

                #endregion Tier2 PAWs

                Write-Verbose -Message 'Admin/Tier0 Baseline GPO configurations completed successfully'

            } catch {
                Write-Error -Message ('Error configuring Admin/Tier0 Baseline GPO: {0}' -f $_.Exception.Message)
            }

            # Ensure progress bar is removed on error
            Write-Progress -Activity 'Configuring GPO restrictions' -Completed
        } #end If ShouldProcess

    } #end Process

    End {

        if ($null -ne $Variables -and
            $null -ne $Variables.Footer) {

            $txt = ($Variables.Footer -f $MyInvocation.InvocationName,
                'Configure Baseline GPO Restrictions.'
            )
            Write-Verbose -Message $txt
        } #end If

        # Stop transcript if it was started
        if ($EnableTranscript) {
            try {
                Stop-Transcript -ErrorAction Stop
                Write-Verbose -Message 'Transcript stopped successfully'
            } catch {
                Write-Warning -Message ('Failed to stop transcript: {0}' -f $_.Exception.Message)
            } #end Try-Catch
        } #end If
    } #end End
} #end Function New-Tier0GpoRestriction