Public/New-Tier1.ps1
function New-Tier1 { <# .SYNOPSIS .DESCRIPTION .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 #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] [OutputType([System.String])] 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.Servers -or $null -eq $xml.n.NC) { throw 'XML file is missing required elements (Admin or OUs 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 ('{0}_{1}.LOG' -f $MyInvocation.MyCommand.Name, (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 ############################## # Initialize progress tracking variables # Progress counter and total for percentage calculation [int]$script:CurrentStep = 0 [int]$script:TotalSteps = 4 # OUs creation, GPOs creation, GPO restrictions, delegations # Base progress parameters for reuse [hashtable]$script:ProgressParams = @{ Activity = 'Creating Tier 1 Infrastructure' Status = 'Starting...' PercentComplete = 0 Id = 1 } ############################## # Module imports Import-MyModule -Name 'ServerManager' -UseWindowsPowerShell -SkipEditionCheck -Verbose:$false Import-MyModule -Name 'GroupPolicy' -UseWindowsPowerShell -SkipEditionCheck -Verbose:$false Import-MyModule -Name 'ActiveDirectory' -UseWindowsPowerShell -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) #$ArrayList = [System.Collections.ArrayList]::New() [System.Collections.Generic.List[object]]$ArrayList = [System.Collections.Generic.List[object]]::New() $DenyLogon = [System.Collections.Generic.List[object]]::New() # Load the XML configuration file try { $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } catch { Write-Error -Message "Error reading XML file: $($_.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 Variables $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: {0}' -f $_.Exception.Message) $null } } $NewAdminExists = 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 Variables #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 -Filter * | Where-Object { $_.SID -like '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 } } #endregion Well-Known groups Variables #region Global groups Variables # 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 $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 } #endregion Global groups Variables #region Local groups Variables $SL_AdRight = Get-SafeVariable -Name 'SL_AdRight' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.AdRight.Name) Get-AdObjectType -Identity $groupName } $SL_InfraRight = Get-SafeVariable -Name 'SL_InfraRight' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.InfraRight.Name) Get-AdObjectType -Identity $groupName } $SL_SvrAdmRight = Get-SafeVariable -Name 'SL_SvrAdmRight' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrAdmRight.Name) Get-AdObjectType -Identity $groupName } $SL_SvrOpsRight = Get-SafeVariable -Name 'SL_SvrOpsRight' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrOpsRight.Name) Get-AdObjectType -Identity $groupName } $SL_GpoAdminRight = Get-SafeVariable -Name 'SL_GpoAdminRight' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) Get-AdObjectType -Identity $groupName } #endregion Local groups Variables [String]$ServersOu = $confXML.n.Servers.OUs.ServersOU.Name [string]$ServersOuDn = ('OU={0},{1}' -f $ServersOu, $Variables.AdDn) } #end Begin Process { if ($PSCmdlet.ShouldProcess('Create Tier1 Organizational Units')) { # Update progress $script:CurrentStep++ $script:ProgressParams.Status = ('Step {0}/{1}: Creating Tier 1 Organizational Units' -f $script:CurrentStep, $script:TotalSteps) $script:ProgressParams.PercentComplete = [math]::Min(100, [math]::Round(($script:CurrentStep / $script:TotalSteps) * 100)) Write-Progress @script:ProgressParams # Create Servers and Sub OUs $Splat = @{ ouName = $ServersOu ouPath = $Variables.AdDn ouDescription = $confXML.n.Servers.OUs.ServersOU.Description } New-DelegateAdOU @Splat # Create Sub-OUs for Servers $Splat = @{ ouPath = $ServersOuDn } # Count of sub-OUs for progress reporting $totalSubOUs = 7 # Update this if more OUs are added $currentSubOU = 0 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.ApplicationOU.Name ouDescription = $confXML.n.Servers.OUs.ApplicationOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.FileOU.Name ouDescription = $confXML.n.Servers.OUs.FileOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.HypervOU.Name ouDescription = $confXML.n.Servers.OUs.HypervOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.LinuxOU.Name ouDescription = $confXML.n.Servers.OUs.LinuxOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.RemoteDesktopOU.Name ouDescription = $confXML.n.Servers.OUs.RemoteDesktopOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.SqlOU.Name ouDescription = $confXML.n.Servers.OUs.SqlOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 $Splat1 = @{ ouName = $confXML.n.Servers.OUs.WebOU.Name ouDescription = $confXML.n.Servers.OUs.WebOU.Description } $currentSubOU++ New-DelegateAdOU @Splat @Splat1 } #end If ShouldProcess if ($PSCmdlet.ShouldProcess('Create Tier1 Baseline GPOs')) { # Update progress $script:CurrentStep++ $script:ProgressParams.Status = ('Step {0}/{1}: Creating Baseline GPOs' -f $script:CurrentStep, $script:TotalSteps) $script:ProgressParams.PercentComplete = [math]::Min(100, [math]::Round(($script:CurrentStep / $script:TotalSteps) * 100)) Write-Progress @script:ProgressParams # Create basic GPO for Servers $Splat = @{ gpoDescription = '{0}-Baseline' -f $ServersOu gpoScope = $confXML.n.Admin.GPOs.ServersBaseline.Scope gpoLinkPath = $ServersOuDn GpoAdmin = $sl_GpoAdminRight gpoBackupId = $confXML.n.Admin.GPOs.ServersBaseline.backupID gpoBackupPath = Join-Path -Path $DMScripts -ChildPath 'SecTmpl' -Resolve } New-DelegateAdGpo @Splat # Create basic GPOs for different types under Servers $Splat = @{ gpoScope = 'C' GpoAdmin = $sl_GpoAdminRight gpoBackupPath = Join-Path -Path $DMScripts -ChildPath 'SecTmpl' -Resolve } $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.ApplicationOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.ApplicationOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.FileOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.FileOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.HypervOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.HypervOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.RemoteDesktopOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.RemoteDesktopOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.SqlOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.SqlOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 $Splat1 = @{ gpoDescription = ('{0}-Baseline' -f $confXML.n.Servers.OUs.WebOU.Name) gpoLinkPath = ('OU={0},{1}' -f $confXML.n.Servers.OUs.WebOU.Name, $ServersOuDn) } New-DelegateAdGpo @Splat @Splat1 } #end If ShouldProcess if ($PSCmdlet.ShouldProcess('Create Tier1 GPO Restrictions')) { # Update progress $script:CurrentStep++ $script:ProgressParams.Status = ('Step {0}/{1}: Creating GPO Restrictions' -f $script:CurrentStep, $script:TotalSteps) $script:ProgressParams.PercentComplete = [math]::Min(100, [math]::Round(($script:CurrentStep / $script:TotalSteps) * 100)) Write-Progress @script:ProgressParams # Access this computer from the network / Deny Access this computer from the network # Not Defined # Allow Logon Locally / Allow Logon throug RDP/TerminalServices # Logon as a Batch job / Logon as a Service # Deny Allow Logon Locally / Deny Allow Logon throug RDP/TerminalServices # Deny Logon as a Batch job / Deny Logon as a Service $DenyLogon.Clear() [void]$DenyLogon.Add($SchemaAdmins) [void]$DenyLogon.Add($EnterpriseAdmins) [void]$DenyLogon.Add($DomainAdmins) [void]$DenyLogon.Add($Administrators) [void]$DenyLogon.Add($AccountOperators) [void]$DenyLogon.Add($BackupOperators) [void]$DenyLogon.Add($PrintOperators) [void]$DenyLogon.Add($ServerOperators) if ($null -ne $AdminName) { [void]$DenyLogon.Add($AdminName) } if ($null -ne $NewAdminExists) { [void]$DenyLogon.Add($NewAdminExists) } if ($null -ne $SG_Tier0Admins) { [void]$DenyLogon.Add($SG_Tier0Admins) } if ($null -ne $SG_Tier2Admins) { [void]$DenyLogon.Add($SG_Tier2Admins) } # 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 $ArrayList.Clear() [void]$ArrayList.Add($Administrators) if ($null -ne $SG_Tier1Admins) { [void]$ArrayList.Add($SG_Tier1Admins) } $Splat = @{ GpoToModify = 'C-{0}-Baseline' -f $ServersOu BatchLogon = $SG_Tier1ServiceAccount ServiceLogon = $SG_Tier1ServiceAccount InteractiveLogon = $SG_Tier1Admins RemoteInteractiveLogon = $SG_Tier1Admins DenyInteractiveLogon = $DenyLogon DenyRemoteInteractiveLogon = $DenyLogon DenyBatchLogon = @($SG_Tier0ServiceAccount, $SG_Tier2ServiceAccount) DenyServiceLogon = @($SG_Tier0ServiceAccount, $SG_Tier2ServiceAccount) Backup = $ArrayList MachineAccount = $ArrayList CreateGlobal = @($ArrayList, 'LOCAL SERVICE', 'NETWORK SERVICE') Systemtime = @($ArrayList, 'LOCAL SERVICE') TimeZone = $ArrayList CreatePagefile = $ArrayList CreateSymbolicLink = $ArrayList RemoteShutDown = $ArrayList Impersonate = @($ArrayList, '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 } Set-GpoPrivilegeRight @Splat } #end If ShouldProcess if ($PSCmdlet.ShouldProcess('Create Tier1 Delegations')) { # Update progress for final phase $script:CurrentStep++ $script:ProgressParams.Status = ('Step {0}/{1}: Creating Delegations' -f $script:CurrentStep, $script:TotalSteps) $script:ProgressParams.PercentComplete = [math]::Min(100, [math]::Round(($script:CurrentStep / $script:TotalSteps) * 100)) Write-Progress @script:ProgressParams # Delegation to SL_SvrAdmRight and SL_SvrOpsRight groups to SERVERS area # Get the DN of 1st level OU underneath SERVERS area $Splat = @{ Filter = '*' SearchBase = $ServersOuDn SearchScope = 'OneLevel' } $AllSubOu = Get-ADOrganizationalUnit @Splat | Select-Object -ExpandProperty DistinguishedName # Count of sub-OUs for progress reporting $totalSubOUs = $AllSubOu.Count $currentSubOU = 0 # Iterate through each sub OU and invoke delegation Foreach ($Item in $AllSubOu) { $currentSubOU++ # Update progress for sub-OU processing $script:ProgressParams.Status = ('Step {0}/{1}: Delegating permissions for sub-OU {2}/{3}' -f $script:CurrentStep, $script:TotalSteps, $currentSubOU, $totalSubOUs) $subProgress = ($currentSubOU / $totalSubOUs) $script:ProgressParams.PercentComplete = [math]::Min(100, [math]::Round((($script:CurrentStep - 1 + $subProgress) / $script:TotalSteps) * 100)) Write-Progress @script:ProgressParams ############################################################################### # Delegation to SL_SvrAdmRight group to SERVERS area Set-AdAclDelegateComputerAdmin -Group $SL_SvrAdmRight -LDAPpath $Item ############################################################################### # Delegation to SL_SvrOpsRight group on SERVERS area # Change Public Info Set-AdAclComputerPublicInfo -Group $SL_SvrOpsRight -LDAPpath $Item # Change Personal Info Set-AdAclComputerPersonalInfo -Group $SL_SvrOpsRight -LDAPpath $Item } #end foreach # Complete the delegations $script:ProgressParams.Status = ('Step {0}/{1}: Completing Delegations' -f $script:CurrentStep, $script:TotalSteps) $script:ProgressParams.PercentComplete = 100 Write-Progress @script:ProgressParams # Create/Delete OUs within Servers Set-AdAclCreateDeleteOU -Group $SL_InfraRight -LDAPpath $ServersOuDn # Change OUs within Servers Set-AdAclChangeOU -Group $SL_AdRight -LDAPpath $ServersOuDn } #end If ShouldProcess } #end Process End { if ($null -ne $Variables -and $null -ne $Variables.Footer) { $txt = ($Variables.Footer -f $MyInvocation.InvocationName, 'creating Tier1 objects.' ) 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 # Complete progress tracking $script:ProgressParams.Status = 'Completed' $script:ProgressParams.PercentComplete = 100 Write-Progress @script:ProgressParams -Completed } #end End } #end Function New-Tier1 |