(C) Ondrej Sevecek, 2019 - www.sevecek.com, ondrej@sevecek.com
#===================== # Application installations DBG ("Build step: {0}" -f $MyInvocation.MyCommand.Definition) DBG "Application installations..." DBG ("Machine config: {0}, {1}" -f $vmName, $vmConfig.hostName) $restartRequired = $false $subPhasesToDo = 0 $subPhasesDone = 0 #========================= DBG ("Should install NLB: {0}" -f (Is-ValidString $vmConfig.nlb.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.nlb.instance) -and (-not (Parse-BoolSafe $vmConfig.nlb.dnd)) -and (Do-SubPhase nlb)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run NLB library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-nlb.ps1", $vmName) $true $vmConfig.nlb.app.iLogin $vmConfig.nlb.app.iDomain $vmConfig.nlb.app.iPwd $false $null $true -showWindow if ($buildLibExitCode -eq $global:VM_RECYCLE_REQUIRED) { DBG ('AppLibrary requested recycle and be re-run the next time') $restartRequired = $true } else { $restartRequired = $true # we ignore other statuses and always restart Finish-SubPhase nlb $subPhasesDone ++ } } } #========================= DBG ("Should enable BitLocker for OS volume: {0}" -f ((Is-NonNull $vmConfig.bitlocker) -and (Parse-BoolSafe $vmConfig.bitlocker.os))) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if (((Is-NonNull $vmConfig.bitlocker) -and (Parse-BoolSafe $vmConfig.bitlocker.os)) -and (-not (Parse-BoolSafe $vmConfig.bitlocker.dnd)) -and (Do-SubPhase bitlockerOS)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ('Enable BitLocker for OS volume: {0}' -f (Parse-BoolSafe $vmConfig.bitlocker.os)) Enable-BitLocker $env:SystemDrive -algo $vmConfig.bitlocker.algo -usedOnly (Parse-BoolSafe $vmConfig.bitlocker.usedOnly) -protectors $vmConfig.bitlocker.decrypt $restartRequired = $true Finish-SubPhase bitlockerOS $subPhasesDone ++ } } #========================= DBGSTART $bitLockerVolumes = $vmConfig.SelectNodes('./bitLocker/partition') DBGER $MyInvocation.MyCommand.Name $error DBGEND DBG ("Should enable BitLocker for volumes: {0}" -f ((Get-CountSafe $bitLockerVolumes) -gt 0)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if (((Get-CountSafe $bitLockerVolumes) -gt 0) -and (-not (Parse-BoolSafe $vmConfig.bitlocker.dnd)) -and (Do-SubPhase bitlockerVolumes)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ('Enable BitLocker for volumes: {0}' -f (Get-CountSafe $bitLockerVolumes)) foreach ($oneBitLockerVolume in $bitLockerVolumes) { Enable-BitLocker $oneBitLockerVolume.letter -algo $oneBitLockerVolume.algo -usedOnly (Parse-BoolSafe $oneBitLockerVolume.usedOnly) -protectors $oneBitLockerVolume.decrypt -autoUnlock (Parse-BoolSafe $oneBitLockerVolume.autoUnlock) } Finish-SubPhase bitlockerVolumes $subPhasesDone ++ } } #========================= DBG ("Should install AD CS: {0}" -f (Is-ValidString $vmConfig.ca.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.ca.instance) -and (-not (Parse-BoolSafe $vmConfig.ca.dnd)) -and (Do-SubPhase ca)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run AD CS library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-ca.ps1", $vmName) $true $vmConfig.ca.app.iLogin $vmConfig.ca.app.iDomain $vmConfig.ca.app.iPwd $false $null $true -showWindow Finish-SubPhase ca $subPhasesDone ++ } } #========================= DBG ("Should install IIS: {0}" -f (Is-ValidString $vmConfig.iis.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.iis.instance) -and (-not (Parse-BoolSafe $vmConfig.iis.dnd)) -and (Do-SubPhase iis)) { $subPhasesToDo ++ if (-not $restartRequired) { PossiblyBind-HttpsCertificatesUnderInstallAccount -app iis -vmName $vmName -iLogin $vmConfig.iis.app.iLogin -iDomain $vmConfig.iis.app.iDomain -iPwd $vmConfig.iis.app.iPwd DBG ("Going to run IIS library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-iis.ps1", $vmName) $true $vmConfig.iis.app.iLogin $vmConfig.iis.app.iDomain $vmConfig.iis.app.iPwd $false $null $true -showWindow Finish-SubPhase iis $subPhasesDone ++ } } DBG ('Should install FTP site: {0}' -f (Is-ValidString $vmConfig.ftp.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.ftp.instance) -and (-not (Parse-BoolSafe $vmConfig.ftp.dnd)) -and (Do-SubPhase ftp)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ('Going to install the FTP site requested') Install-FTPSite $vmConfig.ftp Finish-SubPhase ftp $subPhasesDone ++ } } #========================= DBG ("Should install DHCP Server: {0}" -f (Is-ValidString $vmConfig.dhcp.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.dhcp.instance) -and (-not (Parse-BoolSafe $vmConfig.dhcp.dnd)) -and (Do-SubPhase dhcp)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run DHCP Server library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-dhcp.ps1", $vmName) $true $vmConfig.dhcp.app.iLogin $vmConfig.dhcp.app.iDomain $vmConfig.dhcp.app.iPwd $false $null $false -showWindow Finish-SubPhase dhcp $subPhasesDone ++ } } #=============== $cawebInstances = $vmConfig.SelectNodes('./caweb[@instance and (not(@dnd) or @dnd="false")]') DBG ('Should install CA web services: #{0}' -f (Get-CountSafe $cawebInstances)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if (((Get-CountSafe $cawebInstances) -gt 0) -and (Do-SubPhase caweb)) { $subPhasesToDo ++ if (-not $restartRequired) { $cawebInstances | % { $oneInstance = $_ DBG ('Going to run CA web services library to install instance: {0}' -f $oneInstance.instance) $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}" "{2}"' -f "$global:rootDir\buildup-caweb.ps1", $vmName, $oneInstance.instance) $true $oneInstance.app.iLogin $oneInstance.app.iDomain $oneInstance.app.iPwd $false $null $true -showWindow } $restartRequired = $true Finish-SubPhase caweb $subPhasesDone ++ } } #=============== $sqlInstances = $vmConfig.SelectNodes('./sql[@instance and (not(@dnd) or @dnd="false")]') DBG ("Should install SQL servers: #{0}" -f (Get-CountSafe $sqlInstances)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if (((Get-CountSafe $sqlInstances) -gt 0) -and (Do-SubPhase sql)) { $subPhasesToDo ++ if (-not $restartRequired) { $sqlInstances | % { $oneInstance = $_ DBG ('Going to run SQL Server library to install instance: {0}' -f $oneInstance.instance) $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}" "{2}"' -f "$global:rootDir\buildup-sql.ps1", $vmName, $oneInstance.instance) $true $oneInstance.app.iLogin $oneInstance.app.iDomain $oneInstance.app.iPwd $false $null $true -showWindow } $restartRequired = $true Finish-SubPhase sql $subPhasesDone ++ } } #=================== DBG ("Should install SharePoint binaries: {0}" -f (Is-ValidString $vmConfig.sp.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.sp.instance) -and (-not (Parse-BoolSafe $vmConfig.sp.dnd)) -and (Do-SubPhase sp)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run SharePoint binaries library to complete the installation.") Wait-IfRequested sp | Out-Null $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-sp.ps1", $vmName) $true $vmConfig.sp.app.iLogin $vmConfig.sp.app.iDomain $vmConfig.sp.app.iPwd $false $null $true -showWindow if ($buildLibExitCode -eq $global:VM_RECYCLE_REQUIRED) { DBG ('AppLibrary requested recycle and be re-run the next time') $restartRequired = $true } else { $restartRequired = $true # we ignore other statuses and always restart Finish-SubPhase sp $subPhasesDone ++ } } } #=================== DBG ("Should initialize SharePoint server: {0}" -f (Is-ValidString $vmConfig.sp.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.sp.instance) -and (-not (Parse-BoolSafe $vmConfig.sp.dnd)) -and (Do-SubPhase spinit)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run SharePoint initialization library to complete the installation.") Wait-IfRequested spinit | Out-Null PossiblyBind-HttpsCertificatesUnderInstallAccount -app spinit -vmName $vmName -iLogin $vmConfig.sp.app.iLogin -iDomain $vmConfig.sp.app.iDomain -iPwd $vmConfig.sp.app.iPwd $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-spinit.ps1", $vmName) $true $vmConfig.sp.app.iLogin $vmConfig.sp.app.iDomain $vmConfig.sp.app.iPwd $false $null $true -showWindow if ($buildLibExitCode -eq $global:VM_RECYCLE_REQUIRED) { DBGIF ('SPINIT requested recycle and be re-run the next time') { $true } $restartRequired = $true } else { $restartRequired = $true # we ignore other statuses and always restart Finish-SubPhase spinit $subPhasesDone ++ } } } #=================== # Note: "instance" may not be present because the organization name can be specified on a first exchange installation only DBG ("Should install Exchange server: {0}" -f (Is-ValidString $vmConfig.ex.roles)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.ex.roles) -and (-not (Parse-BoolSafe $vmConfig.ex.dnd)) -and (Do-SubPhase ex)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run Exchange library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-ex.ps1", $vmName) $true $vmConfig.ex.app.iLogin $vmConfig.ex.app.iDomain $vmConfig.ex.app.iPwd $false $null $true -showWindow $restartRequired = $true Finish-SubPhase ex $subPhasesDone ++ } } #========================= DBG ("Should install DPM: {0}" -f (Is-ValidString $vmConfig.dpm.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.dpm.instance) -and (-not (Parse-BoolSafe $vmConfig.dpm.dnd)) -and (Do-SubPhase dpm)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run DPM installation library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-dpm.ps1", $vmName) $true $vmConfig.dpm.app.iLogin $vmConfig.dpm.app.iDomain $vmConfig.dpm.app.iPwd $false $null $true -showWindow Finish-SubPhase dpm $subPhasesDone ++ } } #========================= DBG ("Should install RDP farm: {0}" -f (Is-ValidString $vmConfig.rdp.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.rdp.instance) -and (-not (Parse-BoolSafe $vmConfig.rdp.dnd)) -and (Do-SubPhase rdp)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run RDP farm installation library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-rdp.ps1", $vmName) $true $vmConfig.rdp.app.iLogin $vmConfig.rdp.app.iDomain $vmConfig.rdp.app.iPwd $false $null $true -showWindow Finish-SubPhase rdp $subPhasesDone ++ } } #========================= DBG ("Should install SCOM: {0}" -f (Is-ValidString $vmConfig.scom.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.scom.instance) -and (-not (Parse-BoolSafe $vmConfig.scom.dnd)) -and (Do-SubPhase scom)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run SCOM installation library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-scom.ps1", $vmName) $true $vmConfig.scom.app.iLogin $vmConfig.scom.app.iDomain $vmConfig.scom.app.iPwd $false $null $true -showWindow Finish-SubPhase scom $subPhasesDone ++ } } #=================== DBG ("Should configure RRAS: {0}" -f (Is-ValidString $vmConfig.rras.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.rras.instance) -and (-not (Parse-BoolSafe $vmConfig.rras.dnd)) -and (Do-SubPhase rras)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run RRAS configuration library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-rras.ps1", $vmName) $true $vmConfig.rras.app.iLogin $vmConfig.rras.app.iDomain $vmConfig.rras.app.iPwd $false $null $true -showWindow Finish-SubPhase rras $subPhasesDone ++ } } #=================== DBG ("Should install TMG: {0}" -f (Is-ValidString $vmConfig.tmg.type)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.tmg.type) -and (-not (Parse-BoolSafe $vmConfig.tmg.dnd)) -and (Do-SubPhase tmg)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run TMG library to do the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-tmg.ps1", $vmName) $true $vmConfig.tmg.app.iLogin $vmConfig.tmg.app.iDomain $vmConfig.tmg.app.iPwd $false $null $true -showWindow $restartRequired = $true Finish-SubPhase tmg $subPhasesDone ++ } } #=================== DBG ("Should install VisualStudio: {0}" -f (Is-ValidString $vmConfig.vs.version)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.vs.version) -and (-not (Parse-BoolSafe $vmConfig.vs.dnd)) -and (Do-SubPhase vs)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run VisualStudio library to do the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-vs.ps1", $vmName) $true $vmConfig.vs.app.iLogin $vmConfig.vs.app.iDomain $vmConfig.vs.app.iPwd $false $null $true -showWindow $restartRequired = $true Finish-SubPhase vs $subPhasesDone ++ } } #========================= DBG ("Should install ADFS/WAP: {0}" -f (Is-ValidString $vmConfig.adfs.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.adfs.instance) -and (-not (Parse-BoolSafe $vmConfig.adfs.dnd)) -and (Do-SubPhase adfs)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run ADFS library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-adfs.ps1", $vmName) $true $vmConfig.adfs.app.iLogin $vmConfig.adfs.app.iDomain $vmConfig.adfs.app.iPwd $false $null $true -showWindow Finish-SubPhase adfs $subPhasesDone ++ } } #=================== DBG ("Should initialize Forefront/Microsoft Identity Manager (FIM/MIM): {0}" -f (Is-ValidString $vmConfig.mim.instance)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.mim.instance) -and (-not (Parse-BoolSafe $vmConfig.mim.dnd)) -and (Do-SubPhase mim)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run MIM installation library to complete the installation.") $buildLibExitCode = Run-Process 'powershell' ('-ExecutionPolicy Bypass -File "{0}" "{1}"' -f "$global:rootDir\buildup-mim.ps1", $vmName) $true $vmConfig.mim.app.iLogin $vmConfig.mim.app.iDomain $vmConfig.mim.app.iPwd $false $null $true -showWindow if ($buildLibExitCode -eq $global:VM_RECYCLE_REQUIRED) { DBGIF ('MIM requested recycle and be re-run the next time') { $true } $restartRequired = $true } else { $restartRequired = $true # we ignore other statuses and always restart Finish-SubPhase mim $subPhasesDone ++ } } } #========================= DBG ("Should run nested BUILDER: {0}" -f (Is-ValidString $vmConfig.builder.build)) DBG ('Will postpone to the next round: {0}' -f $restartRequired) if ((Is-ValidString $vmConfig.builder.build) -and (-not (Parse-BoolSafe $vmConfig.builder.dnd)) -and (Do-SubPhase builder)) { $subPhasesToDo ++ if (-not $restartRequired) { DBG ("Going to run nested BUILDER to complete the installation.") $buildLibExitCode = Start-NestedBuilder if ($buildLibExitCode -eq $global:VM_RECYCLE_REQUIRED) { DBG ('AppLibrary requested recycle and be re-run the next time') $restartRequired = $true } elseif ($buildLibExitCode -eq $global:VM_FINISHED_RESTART_REQUIRED) { $restartRequired = $true Finish-SubPhase builder $subPhasesDone ++ } else { $restartRequired = $false Finish-SubPhase builder $subPhasesDone ++ } } } ## ReDisable-SystemRestore ReDisable-Updates DBG ('Phases already finished: todo = {0} | done = {1}' -f $subPhasesToDo, $subPhasesDone) DBGIF $MyInvocation.MyCommand.Name { $subPhasesDone -gt $subPhasesToDo } if ($subPhasesToDo -eq $subPhasesDone) { DBG ('Last phase hit. Do some finalizations') DBG ('Should we announce our IPv4 addresses to the Hyper-V host by using KVP: {0}' -f (Parse-BoolSafe $vmConfig.wks.ipv4kvp)) if (Parse-BoolSafe $vmConfig.wks.ipv4kvp) { [string[]] $validIPv4sToNotifyHost = (Get-WmiQueryArray '.' $global:wmiFltValidNIC) | ? { Is-NonNull $_.IPAddress } | select -Expand IPAddress | ? { $_ -match $global:rxIPv4 } DBGIF $MyInvocation.MyCommand.Name { (Get-CountSafe $validIPv4sToNotifyHost) -lt 1 } if ((Get-CountSafe $validIPv4sToNotifyHost) -gt 0) { Set-KvpValue 'sevecek-VMB-IPv4' (Format-MultiValue $validIPv4sToNotifyHost) } } if (Is-LocalComputerDomainController) { # Note: rather force replication again because RODCs are not # masaged with change notifications so we rather be on the safe side Run-Process 'repadmin' '/SyncAll /e /A' } DBG ('Should we remove any members of local groups: {0} | {1}' -f (Is-ValidString $vmConfig.wks.removeLocalMbr), $vmConfig.wks.removeLocalMbr) if (Is-ValidString $vmConfig.wks.removeLocalMbr) { [string[]] $removeLocalMbrs = Split-MultiValue $vmConfig.wks.removeLocalMbr DBG ('Local group member removals: #{0} | {1}' -f (Get-CountSafe $removeLocalMbrs), ($removeLocalMbrs -join ' ; ')) if ((Get-CountSafe $removeLocalMbrs) -gt 0) { foreach ($removeLocalMember in $removeLocalMbrs) { $localGroup = Get-ValueFlags $removeLocalMember $memberToRemove = Strip-ValueFlags $removeLocalMember DBG ('Will remove local membership: {0} | {1}' -f $localGroup, $memberToRemove) DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $localGroup } DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $memberToRemove } if ((Is-ValidString $localGroup) -and (Is-ValidString $memberToRemove)) { Add-MemberLocalGroup -localGroup $localGroup -memberLogin $memberToRemove -memberDomain $null -removeInstead $true } } } } # Note: this weird check is here due to a PS 2.0 bug which loads # empty XML elements as an empty string and not as an empty XmlElement # So if the XML contains emptyelement it is parsed as [string] $vmConfig.wks.GetType() = string if ((Is-NonNull $vmConfig.wks) -and ($vmConfig.wks -is [System.Xml.XmlElement])) { $prelogons = $vmConfig.wks.SelectNodes('./prelogon') DBG ('Should we prelogon some users: {0} | {1}' -f ((Get-CountSafe $prelogons) -gt 0), (Get-CountSafe $prelogons)) if ((Get-CountSafe $prelogons) -gt 0) { [System.Collections.ArrayList] $deList = @() foreach ($onePrelogon in $prelogons) { DBG ('One prelogon request: {0} | {1} | {2} | {3}' -f $onePrelogon.ou, $onePrelogon.domain, $onePrelogon.filter, $onePrelogon.scope) DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $onePrelogon.ou } DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $onePrelogon.domain } DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $onePrelogon.filter } DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $onePrelogon.scope } DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $onePrelogon.pwd } DBG ('Determine domain DN: {0}' -f $onePrelogon.domain) $rootDSE = Get-DE ('LDAP://{0}/RootDSE' -f $onePrelogon.domain) ([ref] $deList) $domainDN = GDES $rootDSE defaultNamingContext $searchRootDN = '{0},{1}' -f $onePrelogon.ou.Trim(','), $domainDN DBG ('Search root DN: {0}' -f $searchRootDN) $searchRootDE = Get-DE $searchRootDN ([ref] $deList) $adUsersFound = Get-ADSearch $searchRootDE $onePrelogon.scope $onePrelogon.filter @('userPrincipalName') DBGIF $MyInvocation.MyCommand.Name { -not $adUsersFound.found } if ($adUsersFound.found) { foreach ($oneAdUserFound in $adUsersFound.result) { $oneAdUserUPN = GSRS $oneAdUserFound userPrincipalName DBG ('One user to be prelogged: {0}' -f $oneAdUserUPN) Prelogon-User $oneAdUserUPN '' $onePrelogon.pwd $true | Out-Null } } Dispose-ADSearch ([ref] $adUsersFound) } Dispose-List ([ref] $deList) } } DBG ('Check if any other account needs profile customization') $accountsWithProfileInit = $vmConfig.SelectNodes('./*/*[(name()="account" or name()="app" or name()="svc") and translate(@loadProfile,"TRUE","true")="true" and translate(@randomDesktop,"TRUE","true")="true"]') DBG ('Found accounts with profile customization: {0}' -f (Get-CountSafe $accountsWithProfileInit)) if ((Get-CountSafe $accountsWithProfileInit) -gt 0) { foreach ($oneAccountWithProfileInit in $accountsWithProfileInit) { if (Is-ValidString $oneAccountWithProfileInit.iLogin) { Prelogon-User $oneAccountWithProfileInit.iLogin $oneAccountWithProfileInit.iDomain $oneAccountWithProfileInit.iPwd $true | Out-Null } if (Is-ValidString $oneAccountWithProfileInit.aLogin) { Prelogon-User $oneAccountWithProfileInit.aLogin $oneAccountWithProfileInit.iDomain $oneAccountWithProfileInit.aPwd $true | Out-Null } if (Is-ValidString $oneAccountWithProfileInit.login) { Prelogon-User $oneAccountWithProfileInit.login $oneAccountWithProfileInit.domain $oneAccountWithProfileInit.pwd $true | Out-Null } } } DBG ('Check if we installed from ISO and rather rename the autounattended files on A:') if ($global:phaseCfg.sevecekBuildup.media.source -eq 'iso') { if (Test-Path 'A:\winnt.sif') { DBG ('WINNT.SIF found, disabling') DBGSTART Rename-Item 'A:\winnt.sif' 'A:\winnt.sif.disabled' -Force DBGER $MyInvocation.MyCommand.Name $error DBGEND } if (Test-Path 'A:\autounattend.xml') { DBG ('AUTOUNATTEND.XML found, disabling') DBGSTART Rename-Item 'A:\autounattend.xml' 'A:\autounattend.xml.disabled' -Force DBGER $MyInvocation.MyCommand.Name $error DBGEND } } DBG ('Custom PowerShell execution policy requested: {0} | {1}' -f (Is-ValidString $vmConfig.commonVM.psPolicy), $vmConfig.commonVM.psPolicy) if (Is-ValidString $vmConfig.commonVM.psPolicy) { DBG ('Setting PS execution policy: {0}' -f $vmConfig.commonVM.psPolicy) DBGSTART Set-ExecutionPolicy $vmConfig.commonVM.psPolicy DBGER $MyInvocation.MyCommand.Name $error DBGEND } if ((Is-LocalComputerMemberOfDomain) -or ($global:thisOSVersionNumber -ge 6)) { DBG ('Pulse machine autoenrollment if the CAs are already finished') # Note: this can be done on domain members only in case of Windows 2003- # because they do not have the Enrollment Web Service client Run-Process certutil '-pulse' } DBG ('Verify our analytics code at the last phase') DBGIF '======= ANALYTIC CODE START =======' { $true } $libDir = Split-Path -parent $MyInvocation.MyCommand.Definition & "$libDir\lib-analytics.ps1" DBG ('Assert NICs just before finishing.') Get-BestServerInternalNIC -returnAll $true -saveCsvDebugFile (Get-DataFileApp 'nics-assert' $null '.csv' -randomize $true) | Out-Null if (Is-LocalComputerDomainController) { DBG ('Also assert sensitive domain groups just before finishing') [Collections.ArrayList] $deList = @() $rootDSE = Get-DE ('LDAP://RootDSE') ([ref] $deList) DBG ('Are we running a sub-domain DC here?') if ((GDES $rootDSE configurationNamingContext) -ne ('CN=Configuration,{0}' -f (GDES $rootDSE defaultNamingContext))) { DBG ('We are a subdomain DC') $SIDstoProcess = @{ 'BUILTIN\Administrators' = 'S-1-5-32-544' 'BUILTIN\Backup Operators' = 'S-1-5-32-551' 'BUILTIN\Server Operators' = 'S-1-5-32-549' 'BUILTIN\Account Operators' = 'S-1-5-32-548' 'BUILTIN\Pre-Windows 2000 Compantible Access' = 'S-1-5-32-554' 'BUILTIN\Windows Authorization Access Group' = 'S-1-5-32-560' "$thisComputerDomainNetBIOS\Domain Admins" = "$thisComputerSID-512" "$thisComputerDomainNetBIOS\Domain Computers" = "$thisComputerSID-515" } } else { DBG ('We are a forest root DC') $SIDstoProcess = @{ 'BUILTIN\Administrators' = 'S-1-5-32-544' 'BUILTIN\Backup Operators' = 'S-1-5-32-551' 'BUILTIN\Server Operators' = 'S-1-5-32-549' 'BUILTIN\Account Operators' = 'S-1-5-32-548' 'BUILTIN\Pre-Windows 2000 Compantible Access' = 'S-1-5-32-554' 'BUILTIN\Windows Authorization Access Group' = 'S-1-5-32-560' "$thisComputerDomainNetBIOS\Domain Admins" = "$thisComputerSID-512" "$thisComputerDomainNetBIOS\Domain Computers" = "$thisComputerSID-515" "$thisComputerDomainNetBIOS\Enterprise Admins" = "$thisComputerSID-519" "$thisComputerDomainNetBIOS\Schema Admins" = "$thisComputerSID-518" } } foreach ($oneSIDtoProcess in $SIDstoProcess.Keys) { DBG ('One principal to process: {0} | {1}' -f $oneSIDtoProcess, $SIDstoProcess[$oneSIDtoProcess]) $groupDE = Get-DE ('LDAP:// ' -f $SIDstoProcess[$oneSIDtoProcess]) ([ref] $deList) $groupDN = GDES $groupDE distinguishedName Get-GroupMembership $groupDN -maximum 50 | Out-Null } DBG ('Also check some default user accounts') $SIDstoProcess = @{ "$thisComputerDomainNetBIOS\administrator" = "$thisComputerSID-500" "$thisComputerDomainNetBIOS\guest" = "$thisComputerSID-501" "$thisComputerDomainNetBIOS\krbtgt" = "$thisComputerSID-502" } foreach ($oneSIDtoProcess in $SIDstoProcess.Keys) { DBG ('One principal to process: {0} | {1}' -f $oneSIDtoProcess, $SIDstoProcess[$oneSIDtoProcess]) $userDE = Get-DE ('LDAP:// ' -f $SIDstoProcess[$oneSIDtoProcess]) ([ref] $deList) $userDN = GDES $userDE distinguishedName Get-UserMembership $userDN | Out-Null } Dispose-List ([ref] $deList) } else { DBG ('Also assert sensitive local groups just before finishing') $SIDstoProcess = @{ 'BUILTIN\Administrators' = 'S-1-5-32-544' 'BUILTIN\Users' = 'S-1-5-32-545' } foreach ($oneSIDtoProcess in $SIDstoProcess.Keys) { Get-LocalGroupMembership $SIDstoProcess[$oneSIDtoProcess] $oneSIDtoProcess -doNotTraversDefaults $true -maximum 50 | Out-Null } } DBG ('We can also assert LSA secrets') $lsaSecrets = Get-LsaSecrets -name $null -returnAsByteArray $false -forceMachineSecretsDecryptionByKeyCopyOperation $true $machineAccPwd = $lsaSecrets | ? { $_.Secret -eq '$MACHINE.ACC' } | Select -Expand 'String' # Note: US ASCII examples # 0x20 = space # 0x21 = ! # 0x7E = ~ # 0x7F = DEL DBGIF ('Weird $MACHINE.ACC password: {0}' -f $machineAccPwd) { (Is-LocalComputerMemberOfDomain) -and (-not (Is-LocalComputerDomainController)) -and ($machineAccPwd -notmatch '\A[\x20-\x7E]{120}\Z') } DBG ('We also verify our audit policy code') $auditPolicies = Get-AuditPolicy DBG ('Current audit policy settings from API ADVAPI32: {0}' -f ($auditPolicies | Out-String)) if ($global:thisOSVersionNumber -ge 6) { Run-Process 'auditpol' '/get /category:*' Run-Process 'auditpol' '/list /subcategory:* /v' } DBG ('Check USER certificates and private keys as well') # Note: there is a weird store on Vista called "Active Directory User Object" # for which the Get-ChildItem (dir) command fails with "The system cannot open the device or file specified" # Thus I had to make the enumeration a bit more sensitive Assert-CertificatesInStores CurrentUser DBG ('Check SYSTEM certificates and private keys as well') Assert-CertificatesInStores LocalMachine DBG ('Only verify our code for IE version detection here') [void] (Get-IEVersion) if ((Is-LocalComputerDomainController) -or (Is-ValidString $vmConfig.ex.roles)) { DBG ('Verify our OID BER transformation logic') # Note: this takes about 25 minutes to complete, no need to spend the time #Verify-OidEncoding } DBG ('What if the SVCHOST got corrupted sometime later than phase 5') Verify-SvchostServiceRegistrations -fix $false DBG ('Verify PATH environment variable contents. There were some issues with Ex2013 corrupting it') DBGSTART $envPATHvalueToBeValidated = [System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE') DBGER $MyInvocation.MyCommand.Name $error DBGEND DBG ('Current PATH value: {0}' -f $envPATHvalueToBeValidated) $envPATHvalueToBeValidatedTokens = $envPATHvalueToBeValidated.Split(';') [Collections.ArrayList] $envPATHvalueToBeValidatedTokensProcessed = @() foreach ($oneEnvPATHvalueToBeValidatedToken in $envPATHvalueToBeValidatedTokens) { DBGIF ('Weird PATH token found: "{0}"' -f $oneEnvPATHvalueToBeValidatedToken) { $oneEnvPATHvalueToBeValidatedToken.Trim() -ne $oneEnvPATHvalueToBeValidatedToken } DBGIF ('Weird PATH token found: "{0}"' -f $oneEnvPATHvalueToBeValidatedToken) { Is-EmptyString $oneEnvPATHvalueToBeValidatedToken } DBGIF ('Weird PATH token found: "{0}"' -f $oneEnvPATHvalueToBeValidatedToken) { -not (Test-Path -Literal $oneEnvPATHvalueToBeValidatedToken) } DBGIF ('Duplicate PATH token found: "{0}"' -f $oneEnvPATHvalueToBeValidatedToken) { Contains-Safe $envPATHvalueToBeValidatedTokensProcessed $oneEnvPATHvalueToBeValidatedToken } [void] $envPATHvalueToBeValidatedTokensProcessed.Add($oneEnvPATHvalueToBeValidatedToken) } Detect-NetFxVersions | Out-Null DBGIF '======== ANALYTIC CODE END ========' { $true } DBGSTART; DBGEND } DBGIF $MyInvocation.MyCommand.Name { $subPhasesToDo -lt $subPhasesDone } $global:restartCurrentPhase = ($subPhasesToDo -gt $subPhasesDone) $global:proceedWithoutRestart = ($subPhasesToDo -eq 0) # SIG # Begin signature block # MIIYMAYJKoZIhvcNAQcCoIIYITCCGB0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCChn1Fs2yO6focI # Nhn9DvrZAZf6wMOmFxJssHPOzsIFO6CCE0cwggYEMIID7KADAgECAgoqHIRwAAEA # AAB/MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYTAkNaMRcwFQYDVQQIEw5DemVj # aCBSZXB1YmxpYzENMAsGA1UEBxMEQnJubzEQMA4GA1UEChMHU2V2ZWNlazEjMCEG # A1UEAxMaU2V2ZWNlayBFbnRlcnByaXNlIFJvb3QgQ0EwHhcNMTkwNjExMTkyMzMy # WhcNMjQwNjA5MTkyMzMyWjCBjzELMAkGA1UEBhMCQ1oxFzAVBgNVBAgTDkN6ZWNo # IFJlcHVibGljMQ0wCwYDVQQHEwRCcm5vMRwwGgYDVQQKExNJbmcuIE9uZHJlaiBT # ZXZlY2VrMRcwFQYDVQQDEw5PbmRyZWogU2V2ZWNlazEhMB8GCSqGSIb3DQEJARYS # b25kcmVqQHNldmVjZWsuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEAnkjWNkK4FfUUN8iAN91ry+wsSn8cFKJbMnROAqTrx8t3H315p2/bUG2DosCF # Odu0WcaTOLdm5obhT+/3O7BqpdcnlWKlSEz4AL9zQeCbe4++NObBVPBbPE16j9C4 # xELoXW/Ti86C2PEkN5azGUvxGxzQQ45g32OsEI+Bh05qHMkk3oQ6L8O0Fpd5W4e+ # L4HuKS3JOikNhhryTNPD9grF/0wXTzn94TrL1GohuaCPh8g9HOtMoDCd+ExnqV8q # 4k60D37BOK1I81hYFIBn8MvCsjMRC5TK87MtI7aUUIeve5kopc8ZpxNti3F/+Puh # 4UUxL3nKjfAM6HE0b7FqkfkRpwIDAQABo4IBgjCCAX4wEwYDVR0lBAwwCgYIKwYB # BQUHAwMwDgYDVR0PAQH/BAQDAgbAMBsGCSsGAQQBgjcVCgQOMAwwCgYIKwYBBQUH # AwMwHQYDVR0OBBYEFOKbNkkiAht2GxCISJMJxLg4gOC9MB0GA1UdEQQWMBSBEm9u # ZHJlakBzZXZlY2VrLmNvbTAfBgNVHSMEGDAWgBQNnMgyfdUi8l9UfithS4FQ88Vs # wDBSBgNVHR8ESzBJMEegRaBDhkFodHRwOi8vcGtpLnNldmVjZWsuY29tL0NBL1Nl # dmVjZWslMjBFbnRlcnByaXNlJTIwUm9vdCUyMENBKDEpLmNybDCBhgYIKwYBBQUH # AQEEejB4ME0GCCsGAQUFBzAChkFodHRwOi8vcGtpLnNldmVjZWsuY29tL0NBL1Nl # dmVjZWslMjBFbnRlcnByaXNlJTIwUm9vdCUyMENBKDEpLmNydDAnBggrBgEFBQcw # AYYbaHR0cDovL3BraS5zZXZlY2VrLmNvbS9vY3NwMA0GCSqGSIb3DQEBCwUAA4IC # AQCfr6XDtt/O8OBr+X5l49UBLaJrjUXHkAHofdC7p7BLCXIs4GYIti1lf6pas5yB # Q428aKITITq/vEHUTyiiyKtzVkafILWXXKPxy+zmmuw9odB3Hea4ECNpcaG8UNtz # vMm1Dr0ZrkENhcv6I3tNhRr2AOE9AKOfnVEullFD/mZqfmaNkhpnl31jk7OMSUQc # oY8qD6BDQP9371C10gJOmp57sHfPa4Vn5E4aNzn8+o9C9HI7nNagZF5BamKOFdR2 # ui7K3krMbTuDHo+ZcA9nHnzZqiVKpEBFu8lGv9Mf+GDb9yxz6EjV3xS2RcnywX2v # z0VUt2NGno8LudrnWpgrRy4Sl7x6FwVVKtS/o7zFSIiHgntIKFv8urSKSTukCLFK # Y9fBIDDlWFV1ZV1DNpNWxnexWIRv2AH7YlzKQCA4Rysn01hVeBGsWFkCr9J33LmV # enQYpk9eoYMPRwAYg48r65wOOOzLvmyLSGllH88BMvmTQ9myXqwp6NDH1psljXTl # PUbpf7w6IZwsY0dhGhP9iyqbcrGdK0Bnf8Za6Qdj3iXtwd1VgpatFZrxOM5KawCL # pkYl1ABupbzNpWzmC+nfymqwbYiCogPt1vHOyF4EJ73ExVDCqXkpiNvFRqmu1eaZ # IOdbPCdl00a9rk52NKqo/BUsw16TKsDEYTA/7ACbEsnERzCCBmowggVSoAMCAQIC # EAMBmgI6/1ixa9bV6uYX8GYwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCVVMx # FTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNv # bTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNzdXJlZCBJRCBDQS0xMB4XDTE0MTAyMjAw # MDAwMFoXDTI0MTAyMjAwMDAwMFowRzELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERp # Z2lDZXJ0MSUwIwYDVQQDExxEaWdpQ2VydCBUaW1lc3RhbXAgUmVzcG9uZGVyMIIB # IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo2Rd/Hyz4II14OD2xirmSXU7 # zG7gU6mfH2RZ5nxrf2uMnVX4kuOe1VpjWwJJUNmDzm9m7t3LhelfpfnUh3SIRDsZ # yeX1kZ/GFDmsJOqoSyyRicxeKPRktlC39RKzc5YKZ6O+YZ+u8/0SeHUOplsU/UUj # joZEVX0YhgWMVYd5SEb3yg6Np95OX+Koti1ZAmGIYXIYaLm4fO7m5zQvMXeBMB+7 # NgGN7yfj95rwTDFkjePr+hmHqH7P7IwMNlt6wXq4eMfJBi5GEMiN6ARg27xzdPpO # 2P6qQPGyznBGg+naQKFZOtkVCVeZVjCT88lhzNAIzGvsYkKRrALA76TwiRGPdwID # AQABo4IDNTCCAzEwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0l # AQH/BAwwCgYIKwYBBQUHAwgwggG/BgNVHSAEggG2MIIBsjCCAaEGCWCGSAGG/WwH # ATCCAZIwKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw # ggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgA # aQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQA # ZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcA # aQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwA # eQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkA # YwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEA # cgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIA # eQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9bAMVMB8GA1UdIwQYMBaA # FBUAEisTmLKZB+0e36K+Vw0rZwLNMB0GA1UdDgQWBBRhWk0ktkkynUoqeRqDS/Qe # icHKfTB9BgNVHR8EdjB0MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v # RGlnaUNlcnRBc3N1cmVkSURDQS0xLmNybDA4oDagNIYyaHR0cDovL2NybDQuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcmwwdwYIKwYBBQUHAQEE # azBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYB # BQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRENBLTEuY3J0MA0GCSqGSIb3DQEBBQUAA4IBAQCdJX4bM02yJoFcm4bOIyAP # gIfliP//sdRqLDHtOhcZcRfNqRu8WhY5AJ3jbITkWkD73gYBjDf6m7GdJH7+IKRX # rVu3mrBgJuppVyFdNC8fcbCDlBkFazWQEKB7l8f2P+fiEUGmvWLZ8Cc9OB0obzpS # CfDscGLTYkuw4HOmksDTjjHYL+NtFxMG7uQDthSr849Dp3GdId0UyhVdkkHa+Q+B # 0Zl0DSbEDn8btfWg8cZ3BigV6diT5VUW8LsKqxzbXEgnZsijiwoc5ZXarsQuWaBh # 3drzbaJh6YoLbewSGL33VVRAA5Ira8JRwgpIr7DUbuD0FAo6G+OPPcqvao173NhE # MIIGzTCCBbWgAwIBAgIQBv35A5YDreoACus/J7u6GzANBgkqhkiG9w0BAQUFADBl # MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 # d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv # b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMjExMTEwMDAwMDAwWjBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBBc3N1cmVkIElEIENBLTEwggEiMA0G # CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDogi2Z+crCQpWlgHNAcNKeVlRcqcTS # QQaPyTP8TUWRXIGf7Syc+BZZ3561JBXCmLm0d0ncicQK2q/LXmvtrbBxMevPOkAM # Rk2T7It6NggDqww0/hhJgv7HxzFIgHweog+SDlDJxofrNj/YMMP/pvf7os1vcyP+ # rFYFkPAyIRaJxnCI+QWXfaPHQ90C6Ds97bFBo+0/vtuVSMTuHrPyvAwrmdDGXRJC # geGDboJzPyZLFJCuWWYKxI2+0s4Grq2Eb0iEm09AufFM8q+Y+/bOQF1c9qjxL6/s # iSLyaxhlscFzrdfx2M8eCnRcQrhofrfVdwonVnwPYqQ/MhRglf0HBKIJAgMBAAGj # ggN6MIIDdjAOBgNVHQ8BAf8EBAMCAYYwOwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsG # AQUFBwMCBggrBgEFBQcDAwYIKwYBBQUHAwQGCCsGAQUFBwMIMIIB0gYDVR0gBIIB # yTCCAcUwggG0BgpghkgBhv1sAAEEMIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3 # dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUF # BwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUA # cgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMA # YwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQA # IABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAA # UABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkA # bQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4A # YwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYA # ZQByAGUAbgBjAGUALjALBglghkgBhv1sAxUwEgYDVR0TAQH/BAgwBgEB/wIBADB5 # BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 # LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNy # bDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl # ZElEUm9vdENBLmNybDAdBgNVHQ4EFgQUFQASKxOYspkH7R7for5XDStnAs0wHwYD # VR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQEFBQADggEB # AEZQPsm3KCSnOB22WymvUs9S6TFHq1Zce9UNC0Gz7+x1H3Q48rJcYaKclcNQ5IK5 # I9G6OoZyrTh4rHVdFxc0ckeFlFbR67s2hHfMJKXzBBlVqefj56tizfuLLZDCwNK1 # lL1eT7EF0g49GqkUW6aGMWKoqDPkmzmnxPXOHXh2lCVz5Cqrz5x2S+1fwksW5Etw # TACJHvzFebxMElf+X+EevAJdqP77BzhPDcZdkbkPZ0XN1oPt55INjbFpjE/7WeAj # D9KqrgB87pxCDs+R1ye3Fu4Pw718CqDuLAhVhSK46xgaTfwqIa1JMYNHlXdx3LEb # S0scEJx3FMGdTy9alQgpECYxggQ/MIIEOwIBATB6MGwxCzAJBgNVBAYTAkNaMRcw # FQYDVQQIEw5DemVjaCBSZXB1YmxpYzENMAsGA1UEBxMEQnJubzEQMA4GA1UEChMH # U2V2ZWNlazEjMCEGA1UEAxMaU2V2ZWNlayBFbnRlcnByaXNlIFJvb3QgQ0ECCioc # hHAAAQAAAH8wDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAA # oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w # DAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgBRxHEKWnwKoCGCLvnWlv203m # JSi0yfkJQfa51MH2GhAwDQYJKoZIhvcNAQEBBQAEggEAjmTkx9BeMIoJWt0d39Eq # /sTCVATV++ppBxFK6QsFuTP/17IwfkBpY6EwwydlV7py5OJtWx4GdfzqP5dOKhiX # 1hQBGn7/mrn40Nwg/NYUxC6cwpag/OEDHE/qPbGMDVg6WZ64g0BBX46UWejF2OR0 # 8SucoLhNg5ejwQK3bMlGNNcAlDHVGrYIYUuIEWsnKnQyU15GA1Hr78YoN57Ooo2M # GAAoNlXqMDs0595wzf5wZPXXr1avbz8fEzf8nuQ4SGoqTlbrzrhVXMCUM/vVMroH # owze0B04pLLnRmBaKJnD9O5XibEsWPDfK/Wnho+Rx/P/tfEyFbFVNSB0wXOahriC # t6GCAg8wggILBgkqhkiG9w0BCQYxggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr # 1tXq5hfwZjAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc # BgkqhkiG9w0BCQUxDxcNMTkwOTIxMDgxNDA1WjAjBgkqhkiG9w0BCQQxFgQUH1n5 # HTcfjkg9mwci495HZnnRuZ4wDQYJKoZIhvcNAQEBBQAEggEAE2JrG2R2T6Bx+2sF # gnN3FSTmTpquo+CUTpnd5jqiEeQqPzgf/ePBcn2IxTpTu69KYbkz7bRZBsmHbRXo # AesYoSDg8/CogqrvTm2y4UKpbAiiPWT3KFXbYFi4e00UAQIKWC/1b0wFjKCl4ehl # VVLro8kdD6BqBSh4Ghufnk44wyljj98AR9ny0R0kNM+Y/sI5gA7bgF5SSwchfO7n # vSNSFGHnHunmvGI462hV08H5JFdxAQpzGkjVGuzIgRL9gKIVRalo8IhNrQrcsDXV # yIxHy80IevqnvX1CNPIJzn2x/U0qW4Yrf1SD1fE4Mcli80kudLLFE0RvUu07dO3y # pSPdgw== # SIG # End signature block