(C) Ondrej Sevecek, 2019 - www.sevecek.com, ondrej@sevecek.com
#===================== # Domain things DBG ("Build step: {0}" -f $MyInvocation.MyCommand.Definition) DBG "Domain related steps..." DBG ("Machine config: {0}, {1}" -f $vmName, $vmConfig.hostName) # The only valid combinations: # @join - member machine # @new + @dcpromo - first DC of a forest # @join + @new + @dcpromo - first dc in a new domain in an existing forest DBGIF $MyInvocation.MyCommand.Name { (Is-ValidString $vmConfig.domain.join) -and (Is-ValidString $vmConfig.domain.new) -and (Is-EmptyString $vmConfig.domain.dcPromo) } DBGIF $MyInvocation.MyCommand.Name { (Is-ValidString $vmConfig.domain.join) -and (Is-ValidString $vmConfig.domain.new) -and ($vmConfig.domain.new -eq $vmConfig.domain.join) } DBGIF $MyInvocation.MyCommand.Name { (Is-ValidString $vmConfig.domain.new) -and (Is-EmptyString $vmConfig.domain.dcPromo) } #=============== DBG ("Should wait for domain explicitly: {0}" -f $vmConfig.domain.wait) [string] $firstDC = '' [bool] $areWeFirstDC = $false [string] $ourAdSite = $null if (Is-ValidString $vmConfig.domain.adsite.site) { $ourAdSite = $vmConfig.domain.adsite.site } ## ## DBG ('Any machines that we should wait for explicitly: {0}' -f $vmConfig.domain.wait.machines) if (Is-ValidString($vmConfig.domain.wait.machines)) { $machinesToWaitForFirst = Split-MultiValue $vmConfig.domain.wait.machines DBGIF '======== MACHINE WAIT START ========' { $true } DBG ('We are going to wait for some machines before anything else: #{0} | {1}' -f (Get-CountSafe $machinesToWaitForFirst), ($machinesToWaitForFirst -join ',')) foreach ($oneMachineToWaitForFirst in $machinesToWaitForFirst) { Wait-Machine $oneMachineToWaitForFirst } DBGIF '========= MACHINE WAIT END =========' { $true } } ## ## DBG ('Not waiting explicitly. Check for domain membership') $joinDomainFQDN = $vmConfig.domain.join DBG ('Is this a domain joined machine or a new replica DC or a subdomain DC: {0}' -f (Is-ValidString $joinDomainFQDN)) DBG ('Arent we already domain members in case we are adapting: adapting = {0} | domain = {1}' -f $global:adaptingExistingEnv, $global:thisComputerDomain) if ((Is-ValidString $joinDomainFQDN) -and ($joinDomainFQDN -ne $global:thisComputerDomain)) { DBG ('We will have to wait for the domain to become stable') $firstDC = Get-FirstDC $joinDomainFQDN $areWeFirstDC = $vmConfig.hostName -eq $firstDC DBG ('Are we the first DC ourselves: {0} | {1} | {2}' -f $joinDomainFQDN, $vmConfig.hostName, ((Is-ValidString $joinDomainFQDN) -and ($vmConfig.hostName -eq $firstDC))) # Just a matter of some backward compatibility DBGIF 'First DC of a (sub)domain must have @new (plus)instead of @join' { $vmConfig.hostName -eq $firstDC } if (-not $areWeFirstDC) { if (Is-EmptyString $vmConfig.domain.dcPromo) { # Note: this actually gets machines from the whole forest, so # we have to compare the domain name later again $ourDomainMachines = Get-ForestMachines $joinDomainFQDN DBGIF $MyInvocation.MyCommand.Name { (Get-CountSafe $ourDomainMachines) -lt 2 } $waitForTheWholeForest = Is-NonNull $vmConfig.SelectSingleNode('.//app[translate(@waitForTheWholeForest,"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz")="true"]') DBG ('Joining domain as a member, so wait for all our DCs first: wholeForest = {0}' -f $waitForTheWholeForest) DBGIF '======= DOMAIN WAIT START =======' { $true } foreach ($oneOurDomainMachine in $ourDomainMachines) { # Note: generally, we do not wait for RODCs to complete # but if the machine specifies its site, it might be because of a RODC site # so in such a case we wait indiscrimately for RWDC or RODC if ($oneOurDomainMachine.isDC -and (($oneOurDomainMachine.domain -eq $joinDomainFQDN) -or $waitForTheWholeForest) -and $oneOurDomainMachine.do -and ((-not $oneOurDomainMachine.isRODC) -or ((Is-ValidString $ourAdSite) -and ($oneOurDomainMachine.adSite -eq $ourAdSite)))) { Wait-Machine (Format-MultiValue @($oneOurDomainMachine.hostName, $oneOurDomainMachine.domain)) } } DBGIF '======== DOMAIN WAIT END ========' { $true } } else { DBG ('Joining domain as a DC and we are not the first DC, so wait') DBGIF '======= DOMAIN WAIT START =======' { $true } Wait-Machine (Format-MultiValue @($firstDC, $joinDomainFQDN)) DBGIF '======== DOMAIN WAIT END ========' { $true } } } } #=============== [bool] $joinDomainAsMember = (Is-ValidString $vmConfig.domain.join) -and (Is-EmptyString $vmConfig.domain.dcPromo) [bool] $joinDomainBeforeDCPROMO = (Is-ValidString $vmConfig.domain.join) -and (Is-ValidString $vmConfig.domain.dcPromo) -and (-not $areWeFirstDC) -and ($global:phaseRetrial -eq 1) [bool] $joinDomainBeforeDCPROMODone = (Is-ValidString $vmConfig.domain.join) -and (Is-ValidString $vmConfig.domain.dcPromo) -and (-not $areWeFirstDC) -and ($global:phaseRetrial -gt 1) DBG ("Join domain as member: {0}" -f $joinDomainAsMember) DBG ('Join domain as DC before DCPROMO: should = {0} | alreadyDone = {1}' -f $joinDomainBeforeDCPROMO, $joinDomainBeforeDCPROMODone) DBGIF $MyInvocation.MyCommand.Name { $joinDomainAsMember -and $joinDomainBeforeDCPROMO } DBG ('New domain name vs. current domain name if adapting: current = {0} | new = {1}' -f $vmConfig.domain.join, $global:thisComputerDomain) if (($joinDomainAsMember -or $joinDomainBeforeDCPROMO) -and ($vmConfig.domain.join -ne $global:thisComputerDomain)) { DBG ('We should actually join domain: {0}' -f $vmConfig.domain.join) $joinerCred = Get-JoinerCredentials $vmConfig if (Parse-BoolSafe $vmConfig.domain.prestage) { $joinFlags = 1 } else { $joinFlags = 3 # NETSETUP_JOIN_DOMAIN = 1, NETSETUP_ACCT_CREATE = 2 } DBG ("Joining domain: {0} | {1} | {2}" -f $vmConfig.domain.join, $joinerCred.Login, $joinFlags) Run-Process 'IPCONFIG' '/flushdns' #$cmdRs = & { IPCONFIG /flushdns } | Out-String #DBG ("CMD output: {0}" -f $cmdRs) Run-Process 'nslookup' ('-q=SRV _ldap._tcp.dc._msdcs.{0}' -f $vmConfig.domain.join) DBGSTART $thisComp = Get-WMIQuerySingleObject '.' "SELECT * FROM Win32_ComputerSystem" DBGER $MyInvocation.MyCommand.Name $error DBGEND Wait-Periodically -maxTrialCount 3 -sleepSec 37 -sleepMsg 'If the domain join operation fails, retry again' -sleepMsgOnlyIfNotFinishedImmediatelly -scriptBlockWhichReturnsTrueToStop { # Note: here we try to fix the problems which arise when an old DC is hit during the join attempt # such as the SMBv1 on 2003 DCs or any later potential problems Run-Process 'IPCONFIG' '/flushdns' DBG ('Calling JoinDomainOrWorkgroup: {0} | {1}' -f $vmConfig.domain.join, $joinerCred.FullLogin) DBGSTART $wmiRs = $null $wmiRs = $thisComp.JoinDomainOrWorkGroup( $vmConfig.domain.join, $joinerCred.Pwd, $joinerCred.FullLogin, $null, 3) DBGER $MyInvocation.MyCommand.Name $error DBGEND DBGWMI $wmiRs DBGIF $MyInvocation.MyCommand.Name { ($wmiRs.returnValue -ne 0) -and ($wmiRs.returnValue -ne 1316) } return (($wmiRs.returnValue -eq 0) -or ($wmiRs.returnValue -eq 1316)) } if ($joinDomainBeforeDCPROMO) { DBG ('This is a secondary DC in a domain, we restart now to let it promote in the next round only') $global:restartCurrentPhase = $true exit } } #=============== DBG ("Install AD DS: {0}" -f (Is-ValidString($vmConfig.domain.dcPromo))) if (Is-ValidString $vmConfig.domain.dcPromo) { DBGIF $MyInvocation.MyCommand.Name { $global:thisOSVersionNumber -gt 10 } DBGIF $MyInvocation.MyCommand.Name { $global:thisOSVersionNumber -lt 5 } if ($joinDomainBeforeDCPROMODone) { DBG ('Precheck domain membership quality for already joined machine') Run-Process 'gpupdate' '/force' if ($global:thisOSVersionNumber -ge 6.1) { Run-Process 'nltest' ('/sc_reset:{0}' -f $vmConfig.domain.join) Run-Process 'nltest' ('/sc_verify:{0}' -f $vmConfig.domain.join) } } if (($global:thisOSVersionNumber -ge 5) -and ($global:thisOSVersionNumber -le 10)) { if ($global:thisOSVersionNumber -ge 6.2) { DBG ('On some newer systems DFSRDIAG is missing, so we just go for all the features implicitly') $restartRequired = Install-WindowsFeaturesUniversal @('AD-Domain-Services', 'RSAT-ADDS', 'RSAT-DFS-Mgmt-Con', 'RSAT-Feature-Tools-BitLocker') $false $global:installMediaVolume $global:installISOVolume DBGIF $MyInvocation.MyCommand.Name { $restartRequired } } DBG ("Preparing DCPROMO for Win5/6.0/6.1/6.2/6.3: {0}" -f $vmConfig.domain.dcPromo) $dcPromoParams = Split-MultiValue $vmConfig.domain.dcPromo DBG ("Loaded DCPROMO parameters:") DBG ("{0}" -f ($dcPromoParams | Out-String)) if ($thisOSVersion -like '5.*') { if ($dcPromoParams[0].Trim() -like '/*:*') { DBG ('DCPROMO params come in 6.x format. Reformat to 5.x INI syntax.') [System.Collections.ArrayList] $dcPromoParams50 = @() foreach ($oneDcPromoParam in $dcPromoParams) { $oneDcPromoParamTrimmed = $oneDcPromoParam.Trim() DBGIF $MyInvocation.MyCommand.Name { $oneDcPromoParamTrimmed -like '=' } DBGIF $MyInvocation.MyCommand.Name { $oneDcPromoParamTrimmed -notlike '/?*:?*' } if ($oneDcPromoParamTrimmed -like '/*:*') { $oneParam = $oneDcPromoParamTrimmed.SubString(1, $oneDcPromoParamTrimmed.IndexOf(':') - 1).Trim() $oneValue = $oneDcPromoParamTrimmed.SubString($oneDcPromoParamTrimmed.IndexOf(':') + 1).Trim() if ($oneParam -eq 'RebootOnCompletion') { DBG ('RebootOnCompletion parameter is 6.x syntax. Replace it with 5.x version of RebootOnSuccess:NoAndNoPromptEither: {0}' -f $oneDcPromoParamTrimmed) $oneParam = 'RebootOnSuccess' $oneValue = 'NoAndNoPromptEither' } [void] $dcPromoParams50.Add(('{0}={1}' -f $oneParam, $oneValue)) } else { [void] $dcPromoParams50.Add($oneDcPromoParamTrimmed) } } $dcPromoParams = $dcPromoParams50 DBG ('Raparsed 5.x DCPROMO parameters:') DBG ('{0}' -f ($dcPromoParams | Out-String)) } $dcPromoFile = Get-DataFileApp "dcpromoUnattend" $null '.txt' DBG ("Building Win5.x DCPROMO answer file: {0}" -f $dcPromoFile) @('[Unattended]', 'UnattendMode=FullUnattended', '', '[DCINSTALL]') | Out-File -FilePath $dcPromoFile -Force -EV er -EA SilentlyContinue DBGER $MyInvocation.MyCommand.Name $er $dcPromoParams | Out-File -FilePath $dcPromoFile -Append -Force -EV er -EA SilentlyContinue DBGER $MyInvocation.MyCommand.Name $er DBG ("Starting Win5.x DCPROMO") Run-Process "DCPROMO" "/adv /answer:`"$dcPromoFile`"" } else { DBG ('We have to reparse all DC promo params to enclose the values in double quotes in order to fix problems with random password generations') [Collections.ArrayList] $reparsedDcPromoParams = @() foreach ($oneDcPromoParam in $dcPromoParams) { $oneDcPromoParamTrimmed = $oneDcPromoParam.Trim() DBGIF $MyInvocation.MyCommand.Name { $oneDcPromoParamTrimmed -notlike '/?*:?*' } $oneParam = $oneDcPromoParamTrimmed.SubString(1, $oneDcPromoParamTrimmed.IndexOf(':') - 1).Trim() $oneValue = $oneDcPromoParamTrimmed.SubString($oneDcPromoParamTrimmed.IndexOf(':') + 1).Trim() [void] $reparsedDcPromoParams.Add(('/{0}:"{1}"' -f $oneParam, $oneValue)) } DBG ('Starting Win6.x DCPROMO') Run-Process "DCPROMO" ("/unattend {0}" -f ($reparsedDcPromoParams -join ' ')) } } # if ($thisOSVersion -like '6.2.*') { # # DBG ("Starting Install-ADDSForest for Win6.2: {0}" -f $vmConfig.domain.dcPromo) # } #$firstDC = Get-FirstDC $vmConfig.domain.join DBG ('Are we a secondary DC in an existing domain: {0}' -f (Is-EmptyString $vmConfig.domain.new)) if (Is-EmptyString $vmConfig.domain.new) { DBG ('Going to adjust autologon account as we are secondary DC and might not be able to continue with the current account anymore.') # Note: we can safely proceed with JoinerCredentials as the secondary DC requires login/pwd in theelement $joinerCred = Get-JoinerCredentials $vmConfig DBG ('New autologon identity: {0} | {1}' -f $joinerCred.login, $joinerCred.domain) $global:phaseCfg.sevecekBuildup.login.autoLogin = [string] $joinerCred.login $global:phaseCfg.sevecekBuildup.login.pwd = [string] $joinerCred.pwd $global:phaseCfg.sevecekBuildup.login.domain = [string] $joinerCred.domain } # Note: there is a slight difference, exactly and only on 2008 RTM, with autologon # all other systems can autologon with .\builtin-admin except for 2008 RTM DC which cannot use the . as the domain # name in the autologon registry. Thus we must adjust the domain name to be our new promoted domain name DBG ('Are we a first 2008 RTM DC for a new domain: {0}' -f (($global:thisOSVersionNumber -eq 6.0) -and (Is-ValidString $vmConfig.domain.new))) if (($global:thisOSVersionNumber -eq 6.0) -and (Is-ValidString $vmConfig.domain.new)) { DBG ('New autologon domain on first 2008 RTM DC: {0}' -f $vmConfig.domain.new) $global:phaseCfg.sevecekBuildup.login.domain = [string] $vmConfig.domain.new } } #=============== DBG ("Do not wait for initial DC sync: {0}" -f (Parse-BoolSafe($vmConfig.domain.noWaitInitSync))) if (Parse-BoolSafe($vmConfig.domain.noWaitInitSync)) { Set-RegistryValue 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' 'Repl Perform Initial Synchronizations' 0 DWord } # SIG # Begin signature block # MIIYMAYJKoZIhvcNAQcCoIIYITCCGB0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBBBG2HQ7sLUG+7 # WXoHS4sE5i9Qegerl2UOQ7ctqyFnyaCCE0cwggYEMIID7KADAgECAgoqHIRwAAEA # 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 # DAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg7DrLC0ZxVljikFbe+nKIMmHR # 3B2RMY1D3lYfwKb+QygwDQYJKoZIhvcNAQEBBQAEggEAacTy0GWHL4PO4920rx7N # GvhHKnlXz17bJNIqeQBZa0M/icBCAkRsxleh7vdiYmZoK2texrTn8RsJAawVEYGB # +X+jfSeDcTKnXlxVydRG2XrHeo66E/svoGX+NbugFKdF7vaXUqC3Apc/IcVriqRc # VI9SUQnCDQdp8EvRZo1OdQoOm+uhkjAxFx7TnJohEIw5aAjQtF0kbq+NYOcYEn2K # b5twcKHUjzncbT5vP1sX5sCfd8TuKlTgqtab7bWXefe9REAkd8+4cnXasV7wcvZe # J1pcgTLLpG2IVhFVeHLcPA3XVTf8XbgQQnkh81qa+a4rm3nIHnKaf4rZv+dtBUr5 # cKGCAg8wggILBgkqhkiG9w0BCQYxggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr # 1tXq5hfwZjAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc # BgkqhkiG9w0BCQUxDxcNMTkwNzI5MDQyOTE0WjAjBgkqhkiG9w0BCQQxFgQUVNma # +pv4zcEI0BS5Jqj54IDLHfEwDQYJKoZIhvcNAQEBBQAEggEAMTn6mnlcIGXUWqkj # 085xauKUdTRUu6rE32yh99w39oVSmlXbdptN4Ym3po/cGPoo7FiqXFF/pPVU32Tw # CZc+SlGwR4cuCcWj+po9m6K59tLpsc0BagbwjhczC9L+l4ZxoQkhTrg18/5D8w8s # BLoYfwMCXtzsq3QvXzwiGWLDmBOAI4NiODlG1eOcYtn1uLOmtQmU4/7fR0u3FBSl # io4BHzSduAqD+41eV17rBEgZQ9KWyvHt0J6Iof0acA1iFeWWfuTfqhIBaV9fP/mB # WtJ42/oU1ahj7LnQsslCeiPQ5ya++UXKVVT+DHofLw/mJa/mbFeJzZ1+wMj6SGzc # szEhCQ== # SIG # End signature block