ozo-ad-lab-implement-installation-prerequisites.ps1
|
#Requires -Modules @{ModuleName="OZO"; ModuleVersion="1.7.0"},OZOLogger -RunAsAdministrator <#PSScriptInfo .VERSION 1.1.2 .GUID 63ebd3a1-0d72-4090-9226-10db30d2e82f .AUTHOR Andy Lievertz <alievertz@onezeroone.dev> .COMPANYNAME One Zero One .COPYRIGHT This script is released under the terms of the GNU General Public License ("GPL") version 2.0. .TAGS .LICENSEURI https://github.com/onezeroone-dev/OZO-AD-Lab-Implement-Installation-Prerequisites/blob/main/LICENSE .PROJECTURI https://github.com/onezeroone-dev/OZO-AD-Lab-Implement-Installation-Prerequisites .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES https://github.com/onezeroone-dev/OZO-AD-Lab-Implement-Installation-Prerequisites/blob/main/CHANGELOG.md .PRIVATEDATA #> <# .SYNOPSIS See description. .DESCRIPTION Implements the installation prerequisites for the One Zero One AD Lab. .PARAMETER FeatureName The name of the Windows feature to install. Default is "Microsoft-Hyper-V-All". .PARAMETER InternalIP The internal IP address for the lab network. Default is "172.16.1.1". .PARAMETER InternalSwitchName The name of the internal virtual switch. Default is "OZO AD Lab NAT". .PARAMETER LocalGroup The local group to which the current user should be added. Default is "Hyper-V Administrators". .PARAMETER OZOADLabISOs An array of ISO filenames for the lab environment. Default is "OZO-AD-Lab-Client.iso" and "OZO-AD-Lab-Server.iso" in the user's Downloads folder. .PARAMETER PrefixLength The prefix length for the lab network subnet. Default is 24. .PARAMETER Subnet The subnet for the lab network. Default is "172.16.1.0". .EXAMPLE ozo-ad-lab-implement-installation-prerequisites .LINK https://github.com/onezeroone-dev/OZO-AD-Lab-Implement-Installation-Prerequisites/blob/main/README.md #> #PARAMETERS [CmdletBinding()] Param( [Parameter(Mandatory=$false)][String] $FeatureName = "Microsoft-Hyper-V-All", [Parameter(Mandatory=$false,HelpMessage="The internal IP address for the lab network.")][String] $InternalIP = "172.16.1.1", [Parameter(Mandatory=$false,HelpMessage="The name of the internal virtual switch.")][String] $InternalSwitchName = "OZO AD Lab NAT", [Parameter(Mandatory=$false)][String] $LocalGroup = "Hyper-V Administrators", [Parameter(Mandatory=$false,HelpMessage="An array of ISO filenames for the lab environment.")][Array] $OZOADLabISOs = @( (Join-Path -Path $Env:UserProfile -ChildPath "Downloads\OZO-AD-Lab-Client.iso"), (Join-Path -Path $Env:UserProfile -ChildPath "Downloads\OZO-AD-Lab-Server.iso") ), [Parameter(Mandatory=$false,HelpMessage="The prefix length for the lab network subnet.")][Int32] $PrefixLength = 24, [Parameter(Mandatory=$false,HelpMessage="The subnet for the lab network.")][String] $Subnet = "172.16.1.0" ) # CLASSES Class Main { # PROPERTIES: Booleans [Boolean] $prerequisitesSatisfied = $true # PROPERTIES: PSCustomObjects [PSCustomObject] $ozoLogger = @() # METHODS: Constructor method Main($FeatureName,$InternalIP,$InternalSwitchName,$LocalGroup,$OZOADLabISOs,$PrefixLength,$Subnet) { # Create a logger object $this.ozoLogger = (New-OZOLogger) # Log a process start message $this.ozoLogger.Write("Process starting.","Information") # Call ValidateEnvironment to determine if we can proceed If ($this.ValidateEnvironment() -eq $true) { # Determine if thefeature is not installed If ($this.InstallFeature($FeatureName) -eq $false) { # Feature not installed $this.prerequisitesSatisfied = $false } Else { # Feature is installed; determine if a restart is required If ($this.RestartRequired($FeatureName) -eq $true) { # Restart is required $this.prerequisitesSatisfied = $false } } # Determine if the user not is added to the local group If ($this.ManageLocalGroup(([System.Security.Principal.WindowsIdentity]::GetCurrent().Name),$LocalGroup) -eq $false) { $this.prerequisitesSatisfied = $false } # Determine if the VM switches are not created If ($this.CreateVMSwitch($InternalIP,$InternalSwitchName,$PrefixLength,$Subnet) -eq $false) { $this.prerequisitesSatisfied = $false } # Determine if the required ISOs do not exist If ($this.ISOsExist($OZOADLabISOs) -eq $false) { $this.prerequisitesSatisfied = $false } # Determine if all prerequisites were met If ($this.prerequisitesSatisfied -eq $true) { # All prerequisites are satisfied $this.ozoLogger.Write("All prerequisites are satisfied. Please see https://onezeroone.dev/active-directory-lab-part-iii-create-the-virtual-machines for the next steps.","Information") } Else { # Not all prerequisites are satisfied $this.ozoLogger.Write("Not all prerequisites are satisfied. Please see the One Zero One event log for details.","Error") } } Else { # Environment did not validate $this.ozoLogger.Write("The environment did not validate.","Error") } # Log a process complete message $this.ozoLogger.Write("Process complete.","Information") } # METHODS: Environment validation method Hidden [Boolean] ValidateEnvironment() { # Control variable [Boolean] $Return = $true # Determine if this a user-interactive session If ((Get-OZOUserInteractive) -eq $false) { # Session is not user-interactive $this.ozoLogger.Write("Please run this script in a user-interactive session.","Error") $Return = $false } # Return return $Return } # METHODS: Install feature method Hidden [Boolean] InstallFeature($FeatureName) { # Control variable [Boolean] $Return = $true # Determine if the feature is present If ([Boolean](Get-WindowsOptionalFeature -Online -FeatureName $FeatureName -ErrorAction SilentlyContinue) -eq $false) { # Report $this.ozoLogger.Write(("Installing " + $FeatureName + " feature."),"Information") # Feature is not present; try to install it Try { Enable-WindowsOptionalFeature -Online -FeatureName $FeatureName -ErrorAction Stop # Success } Catch { # Failure $this.ozoLogger.Write(("Error installing the " + $FeatureName + " feature. Please manually install this feature and then run this script again to continue. See https://onezeroone.dev/active-directory-lab-part-ii-customization-prerequisites/ for more information."),"Error") $Return = $false } } # Return return $Return } # METHODS: Restart required method Hidden [Boolean] RestartRequired($FeatureName) { # Control variable [Boolean] $Return = $false # Determine if a restart is required If ((Get-WindowsOptionalFeature -Online -FeatureName $FeatureName).RestartRequired -eq "Required") { # Restart is required $this.ozoLogger.Write(("Please restart to complete the " + $FeatureName + " feature installation and then run this script again to continue."),"Warning") $Return = $true # Get restart decision If ((Get-OZOYesNo) -eq "y") { # User elects to restart Restart-Computer } } # Return return $Return } # METHODS: Manage local group membership Hidden [Boolean] ManageLocalGroup($CurrentUser,$LocalGroup) { # Control variable [Boolean] $Return = $true # Determine if the current user is a member of the local group If ((Get-LocalGroupMember -Name $LocalGroup).Name -NotContains $CurrentUser) { # Report $this.ozoLogger.Write(("Adding user to the local " + $LocalGroup + " group."),"Information") # User is not in the local group; try to add them Try { Add-LocalGroupMember -Group $LocalGroup -Member $CurrentUser -ErrorAction Stop # Success } Catch { # Failure $this.ozoLogger.Write(("Failure adding user " + $CurrentUser + " to the " + $LocalGroup + " group. Please manually add this user to this group then run this script again to continue. See https://onezeroone.dev/active-directory-lab-part-ii-customization-prerequisites/ for more information."),"Error") $Return = $false } } # Return return $Return } # METHODS: Create VM switch method Hidden [Boolean] CreateVMSwitch($InternalIP,$InternalSwitchName,$PrefixLength,$Subnet) { # Control variable [Boolean] $Return = $true # Determine if the Get-VMSwitch cmdlet is available If ([Boolean](Get-Command -Name Get-VMSwitch -ErrorAction SilentlyContinue) -eq $true) { # Get-VMSwtich cmdlet is available; determine if the NAT switch does not already exist If ([Boolean](Get-VMSwitch -Name $InternalSwitchName -ErrorAction SilentlyContinue) -eq $false) { # NAT switch does not already exist; try to create it and set the IP address Try { New-VMSwitch -SwitchName $InternalSwitchName -SwitchType Internal -ErrorAction Stop | Out-Null New-NetIPAddress -IPAddress $InternalIP -PrefixLength $PrefixLength -InterfaceIndex (Get-NetAdapter -ErrorAction Stop | Where-Object { $_.Name -eq ("vEthernet (" + $InternalSwitchName + ")") }).ifIndex -ErrorAction Stop | Out-Null # Success } Catch { # Failure $this.ozoLogger.Write(("Error creating the NAT switch with error " + $_ + ". You may need to log out and back in to refresh your group membership. If that does not resolve the issue, then run this script again to continue. See https://onezeroone.dev/active-directory-lab-part-ii-customization-prerequisites/ for more information."),"Error") $Return = $false } } # Determine if the NAT network already exists If ([Boolean](Get-NetNat -Name $InternalSwitchName -ErrorAction SilentlyContinue) -eq $false) { # NAT network does not already exist; try to create it Try { New-NetNat -Name $InternalSwitchName -InternalIPInterfaceAddressPrefix ($Subnet + "/" + $PrefixLength.ToString()) -ErrorAction Stop | Out-Null # Success } Catch { # Failure $this.ozoLogger.Write(("Error creating the NAT network with error " + $_ + ". You may need to manually create this network, then run this script again to continue."),"Error") $Return = $false } } } Else { # Get-VMSwitch cmdlet is not available $Return = $false } # Return return $Return } # METHODS: ISOs exist method Hidden [Boolean] ISOsExist($OZOADLabISOs) { # Control variable [Boolean] $Return = $true # Iterate over the list of required ISOs ForEach ($ISO in $OZOADLabISOs) { # Determine if the ISO exists If ([Boolean](Test-Path -Path $ISO -ErrorAction SilentlyContinue) -eq $false) { $this.ozoLogger.Write(("ISO not found: " + $ISO),"Error") $Return = $false } } # Return return $Return } } # MAIN [Main]::new($FeatureName,$InternalIP,$InternalSwitchName,$LocalGroup,$OZOADLabISOs,$PrefixLength,$Subnet) | Out-Null # SIG # Begin signature block # MIIvrwYJKoZIhvcNAQcCoIIvoDCCL5wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCACZw/FKlABDs+t # 43wLfqiHDKKhguu3LNaVVt3Z9RPnrKCCEgUwggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M # UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD # VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv # ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5 # NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp # BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G # CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI # ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV # DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3 # 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw # mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm # +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe # dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4 # 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM # dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY # MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU # pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV # HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG # A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG # AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl # U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0 # aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh # w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd # OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj # cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc # WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO # hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs # zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7 # 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J # KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH # j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2 # Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/ # L9Uo2bC5a4CH2RwwggZwMIIE2KADAgECAhAbV4ef7ZvUwZ6AKRT0hWSAMA0GCSqG # SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw # HhcNMjYwOTE0MDAwMDAwWhcNMjcwOTE0MjM1OTU5WjBiMQswCQYDVQQGEwJVUzER # MA8GA1UECAwIQ29sb3JhZG8xHzAdBgNVBAoMFkxpZXZlcnR6IEFuZHJldyBIdWJl # cnQxHzAdBgNVBAMMFkxpZXZlcnR6IEFuZHJldyBIdWJlcnQwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQCZl/Kqmb1yMMbn0868VlBqxo7LGu/SDy7bO3wz # D6jMoxzh2UT4iFxNnIEpHJq9SzxkhNgy60Lhzr0kGxBXypLJVGKP3JpS9inmF3zn # e/DWJcOFkQPkwYAsqEoJ6xt/klQlJqnwaN7AJUwUIgZ/72j37//UcWxltCMxnwT2 # wVUQ357c3GOafCKfBMUN9dEgUhwxt4x5GZ6Re/WSGKlh+eFtP1wNBsBXoT6Hme5E # u2L5vTYl0fmKVAsTGJ9k7eHvLE7IUWXOD6NI548uxFQ2FeISOdCRt0WmYmpWgi6S # j1Aoh1zLhsMaLgUPP+BXcOy0cO3zDJ+SZky+S4AB37Y0UBqy9hNvX0WbfQh3BF+2 # uWYGxHYc3FtefKKAbhQGNo9EO4pB0SBh/19a/EbbUpv67CRlO8PmGf8hEk6ic8O6 # 28OjkFi5ByIB7y/XKPKCZmeS/TWDrkyMpu8h9NGqHyWONE5oxpqCYMm3a0L92kfd # zY5e6vSLDuZZjlANRUm3VLnbxZcD8znUvaDbR+ALdJeSZryev8NVMnfOzwZM6vKz # fTPbYpFRBo0owFluKK85CKeZ8z+NyKQfvWh5gYXZw0JFZwdE4SE46fnNLJ3z9loF # Qly+7Dn2zUd/+CxwlRgkuEO1ng6EJ1OAAeA7PixyZob0gjg7ob7YzSK2v4AV/QdQ # oXa04QIDAQABo4IBrjCCAaowHwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhek # zQwwHQYDVR0OBBYEFMiE5GpeP6V7hsDSdHBbSjojZscBMA4GA1UdDwEB/wQEAwIH # gDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEw # NQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j # b20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNl # Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5Bggr # BgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20v # U2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdo # dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAjBgNVHREEHDAagRhhbGlldmVydHpAb25l # emVyb29uZS5kZXYwDQYJKoZIhvcNAQEMBQADggGBACvVVz+HNOH8p+CBcwmrYBVx # mlWNkTz84gmJZ/57FF5XK4kHeo6+QFalQkBSkiDheZa13+FdwUYf1zcJu5hfymkZ # 9zmBhLlIkdluT1llv9GKr/tQaJFd2NXoLiJ7ysqRDbu47U1RR7XGU42HZHLUHa00 # Ha8KDHKYeRcCBMhltjpBK4Hw5daTzT+5fLhMHaOy3ZuWn4Fgx8zEcH1/cdEqnWNn # NxxCWbKcp4sRI0v9uStoUYGpvX8LkYtMUUuWPr7tZAAZiPws6ctOrdROmdEwfyah # IMt2drMfTXZVPpL/5okl37qOYhzV+u6vEvbc3xeAicAgsgOYkvvx5L2iUyFfGdLb # JN4ioPTCKcvN7oXFPwHfyGqwBxARyJy3so2OAFvY4AGY/9DwQVE8KZuplrkktC7Y # MzjB9SjEtvqnyW+h0fHd3H85B8GJiL8slRmIb5f+jJDvmu5RgoaoaMAYeX/V4HXY # gpSD92Hq5AwUjjUvj1WPk+AagPBupA+J4OM2S6eO0DGCHQAwghz8AgEBMGgwVDEL # MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMi # U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIQG1eHn+2b1MGegCkU # 9IVkgDANBglghkgBZQMEAgEFAKB8MBAGCisGAQQBgjcCAQwxAjAAMBkGCSqGSIb3 # DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV # MC8GCSqGSIb3DQEJBDEiBCDJjjgJ5pTV5liC3M5mNH7yX2R9Ztjh8m+w7YTNpbdf # 9zANBgkqhkiG9w0BAQEFAASCAgAFiV0EPThgYKWmXdA6EvFjQkiuomjXdq7haQXV # QzwAqlXXm3oEVIpVo5nFmZlhxo9/FDNjfZEMcNOI4rEuOpSccLFCB4nFCcZ8sOFk # ONSFwtaqK+H/vNQxED6BjbaDjtBhhaXa0jpFf3RTkwumtNnWQKpn1udySc9wKyQG # QPxwAlpqIMwnmoyLsA8U+qDuFJgM0JnfmK1bKxXBdkBWL//DTVpusfClYTTN4Oho # yE/m1OGAMZVOeA7ocaVbCwtbECTI3FqsKSdCQfcW7zTqklfnkji8GDq1ifs2524h # Zo5ZlHHonTulPTLE0SQLq34TSvs5PcCQwp2Gk3+lSu2imn6660v+0Qu3plKUJd8A # xXn70BLNDjPhUe6hC5T3d03HScNK7aWNMNXH7oeaKrK6JzlAPjDcbnKlciKxCufj # 9q5zX+kwFSzoXRedZjO+YJIW0MY+fcMcxiE1Eg6ryshboHjYpUexMGunoUsxBcvg # JmOyUoDnpN5+/6gQOnRdDRvIeC89AdV/v3QMv4C9QbBSYr6xj3JIFzRy2d19P/gv # /9KDZKkSTtP98c/9YGFhEDGPznNKAKcsQMmXabUhh9pgBuAHvOB1ouDkvExSfSS0 # kyHT5fbD8cOj+XWiR+e4XbkTUA/Q+zfSZHU9vZedykOSW4r5wQ/G5hqtfbFZ7b3H # bKQTKKGCGeswghnnBgorBgEEAYI3AwMBMYIZ1zCCGdMGCSqGSIb3DQEHAqCCGcQw # ghnAAgEDMQ8wDQYJYIZIAWUDBAICBQAwgfcGCyqGSIb3DQEJEAEEoIHnBIHkMIHh # AgEBBgorBgEEAbIxAgEBMDEwDQYJYIZIAWUDBAIBBQAEIGnpQeQetcxO2TMC0gSo # 5zSj8PdwxjL5CJ3xrtnKrHj2AhRbMFIMRxRFs8E/MR2VBjKvgg0QYBgPMjAyNjA5 # MjgxNTQ0MTFaoHakdDByMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOR3JlYXRlciBM # b25kb24xGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEwMC4GA1UEAxMnU2VjdGln # byBQdWJsaWMgVGltZSBTdGFtcGluZyBTaWduZXIgUjM3oIIUFzCCBuIwggTKoAMC # AQICEQDnTvJVsFBP+tum3/f8i6MVMA0GCSqGSIb3DQEBDAUAMFUxCzAJBgNVBAYT # AkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3RpZ28g # UHVibGljIFRpbWUgU3RhbXBpbmcgQ0EgUjQxMB4XDTI2MDMyNTAwMDAwMFoXDTM3 # MDYyNDIzNTk1OVowcjELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDkdyZWF0ZXIgTG9u # ZG9uMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxMDAuBgNVBAMTJ1NlY3RpZ28g # UHVibGljIFRpbWUgU3RhbXBpbmcgU2lnbmVyIFIzNzCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBALL/w21L3FDZRS0FEXfZuPtUrefibnRSqOT/NNyJLOJh # XjQfUspqHT+gSSVgbjYThUI/cO+wFQHoOakKQNnSMKdkE8gR69ofXlkk5DAVY/Zl # evliOUmlvrw2Vuz4SU28rHfb/Vgd17eqpRIvJuO6XE8vPpPzn4c4iorszUF6nwuy # nKEQ/+rqfDmQbFNKsa+5+Z4f4kXwKdUFxUwUDjQWUhiHRwMlUWGF9N91aAvL+9a4 # sxCgqR/ez8W8HJ/XqvSu1vIeb+J6bDFKKgkv3PJkMMpQ0BsdeXR2FejZXFRXY1w9 # dZe6gqyMv7px+TpWbYMefECUV0WxoEMgXUk6RKcLo94uUHOdmfZu4Xe8ghglyro3 # /N4VEKTj8dcPPvOBGxFEx1QH6uHKTkWhloGPDScurcZnd8KUtTHl6zmlQDHM04Mw # GfsmQViKnYEAYE8RHl5XRE6GTq0ZMb59SIyJX6+CODVic/kW+dhbIS1Z5AP8HaGn # e/PRG+12QzSneKDJp3Ot+k4GrmmlWT9iy6FNCQ/32K+d4cAZ+Ll7uWbEn6Z6gE+t # Eu7MyZvzWvPNsRKMkcyyflFW1zpRyzutwypALXc9Qg7sFsYERNXa58KZXqU9Onc/ # tck6+adQJFM9tW8xOnE//P5I4eDj84IGGKqzgUD37ihC+WST3DfY0YBKWL0Zaubn # AgMBAAGjggGOMIIBijAfBgNVHSMEGDAWgBQ6dKUMZ8ZCUML9tfzHuyk0gvR6uTAd # BgNVHQ4EFgQUYRDpehKvUcSF1PLPpHQPUM0gr/gwDgYDVR0PAQH/BAQDAgbAMAwG # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwSgYDVR0gBEMwQTAI # BgZngQwBBAIwNQYMKwYBBAGyMQECAQMIMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8v # c2VjdGlnby5jb20vQ1BTMEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly9jcmwuc2Vj # dGlnby5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjQxLmNybDB6Bggr # BgEFBQcBAQRuMGwwRQYIKwYBBQUHMAKGOWh0dHA6Ly9jcnQuc2VjdGlnby5jb20v # U2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjQxLmNydDAjBggrBgEFBQcwAYYX # aHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAAPqPY3R # rM36GXqTpsoHn9TpW5I6z3dkFvc9zPL1W0Egq7j3jtnkbAvRoWeAjGX4ZK4sWsmA # +u4EJG8okQmybuS/4tDUI5UIQb21n4hG2vihxShrneWB0VoQ2VLQ3jCCRmRtAQ+/ # 7H7WVKNiH5Pgl4v2ZTOdPsStzpKnl1YuRrmww/+bcZmLqgk909ywIpZqAfubYfbE # MYjIckLk90f2mG+L8qaGSS2JJVM02pV5XltZ1fbOFETpRN/PQhwygIv33qUUjJ1f # E4ITgw0McMzRqziWdOJP8ocxxw7qXxz1OdRWCalyL1qvUgAFnZTVdSRiMYZKf0wL # cQcM/1Xf1W4FW9nff8ERX8RZJGt/TtPuMWmUpf6BCv9Q6o8YyUTtknvZRpSQ0nLt # tWXdtwsrN2mMgfMuR//gxVrVXvDzCoK/lbiA6dEZOW53lQwBFtEzwE/FH8Jdhegy # Yg4PymZOTZrGBEvgsbxe25yEhJ0IdGa1pwCYsarldJhJVMdNcAOU7jyIMqHcczav # 3wtIXp/SwbXZ3xX0mfsLfANSJ47G4qPgx1atb6GIlTaQXzu/p4fTQeAIUVzZXT4K # 984IyfuO7NLjWMtog1wGUpZD98pv+4Mt9Y5bvfPUjaUVjtePy1DVdi0rl5ESNYi0 # zyOmXVxtA5zzxu1H7RdLZOZugT/XjX69rY9bMIIGpzCCBI+gAwIBAgIRAJCsCHIg # /cWnxGtcxw33PQYwDQYJKoZIhvcNAQEMBQAwVzELMAkGA1UEBhMCR0IxGDAWBgNV # BAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgVGlt # ZSBTdGFtcGluZyBSb290IFI0NjAeFw0yNjAzMjUwMDAwMDBaFw00MTAzMjQyMzU5 # NTlaMFUxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAq # BgNVBAMTI1NlY3RpZ28gUHVibGljIFRpbWUgU3RhbXBpbmcgQ0EgUjQxMIICIjAN # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAruRKogGtghxi+WYtW5oDzPDVF8GG # SfgbUKh6bONxi0wvrI1S8qbAYfvLr/ky5ILVRg//70pgNKq8xC3/WEQodjEwAP2h # mkGShoNAUQps4kd6Wwp74Fo7RlwQ1Mp949ytpWQDvCsYBbZccDmBAJC/ggqiuL/c # 805fGcMw6TzIgyBWuUx5PGp9YnheSNPXFzaz0MPtREdZYk4WhtM+hazqasMWVpj0 # WUAcNhN9vO/FAdWy9Gafdb7lmYLDKTTYjwqAY9P9RfixPPjUaJH6mnBSNBdrX7a0 # Qdlux0ApS0fc48RW1m+W3tq3HiHzch1FHyhiLzCNjc6MUpcV5xalBvPOw/FtQo/A # xaJOvPCSsVrx0f/WkMpEm3fvVbrY9+oo9rIKv9ducE6VGfwIAtKYedG0bO4Ba1Mm # lxPcErDqjLwggvrBJu73fwXpkhtE0hzV0psgm2vhQs3pHll9N00SHBdy2qndEcNu # Dh+46XouM2hoXCO533YQQOHPEUnMTWOo3hyxx5kjDE5PVqp+x+HS4VAT+WBMG4Gz # eLr9YvZbU5x5YvLdcR1dErV/QRYK55rp019fZFF2NR+TkSW0WcmQ3b5taGcrXg49 # EpzKM6/mEpnSJXg1E13X6GO29rWs/LNvkGzsS8XGoRCGBls6ruofeebSsHADR3Ge # IE5gIU927bjokLECAwEAAaOCAW4wggFqMB8GA1UdIwQYMBaAFPZ3at0//QET/xah # bIICL9AKPRQlMB0GA1UdDgQWBBQ6dKUMZ8ZCUML9tfzHuyk0gvR6uTAOBgNVHQ8B # Af8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcD # CDAjBgNVHSAEHDAaMAgGBmeBDAEEAjAOBgwrBgEEAbIxAQIBAwgwTAYDVR0fBEUw # QzBBoD+gPYY7aHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljVGlt # ZVN0YW1waW5nUm9vdFI0Ni5jcmwwfAYIKwYBBQUHAQEEcDBuMEcGCCsGAQUFBzAC # hjtodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3RhbXBp # bmdSb290UjQ2LnA3YzAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5j # b20wDQYJKoZIhvcNAQEMBQADggIBADLeUkdm8Z4DZvjfKHOhqu+hsdXNt+X5F+48 # PB6PTAJCRgA3qxxO3YbAV7baps4K/+2WWoWUspBkT4T2NXK49NvJAfCsztHSgtqk # AQMLX4KjCypJF/+m2Ktrk993g+gcgKdv1yg9C3JmYdJCnnL0ga+pZ/Wo1+rtXZ8d # nwO8RCstTN6gYX0ElFi7Y7NpxbdBC1S6bc05V/SA9HC/ojj33W6GdwnpU/iVylSk # dkoHtHeGIhQLT2ZH0qPM9Wdce8v2fZsDCJQQJ8rll7OGLDbsXa2CLf0MRN9Twzif # Q3rEuAXOx/TkzkZRFfwL34hf1XqSmaYq2tTMy2LgsPrqC2Z/6ZKb3fgrzU0vphB4 # wSTWulitY/KlxbvoyKvrBvUCCx4sgeqf8aR65CbvM5MN/d/lahfXipU2NlY0cXcn # GS61XpmeGKd8It92/lufApZR9x6o5qMJWe0jq4JsfGMGDpIKx7FzkB8gaejuBUW/ # CJ9Phc40+xJRonvVewn4S9yJVRWeM47irGbR9YlN3xruM/yZzhk+rAm9AW06nv7o # b6RQkAXR+cTxiAPy620FF41NrViYB4UyKpzfx7x8jh4ubTOMz954YIdqyeiqqtsb # BwXjWLP0dfMUPA3iIPnPdBKGnodGJTdSlPAMmKJdyvTPqmOXs/LMnf+2Za0Z6FXs # IB9z9aXLMIIGgjCCBGqgAwIBAgIQNsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0B # AQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNV # BAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx # LjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw # HhcNMjEwMzIyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjBXMQswCQYDVQQGEwJHQjEY # MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1Ymxp # YyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEAiJ3YuUVnnR3d6LkmgZpUVMB8SQWbzFoVD9mUEES0QUCBdxSZqdTk # dizICFNeINCSJS+lV1ipnW5ihkQyC0cRLWXUJzodqpnMRs46npiJPHrfLBOifjfh # pdXJ2aHHsPHggGsCi7uE0awqKggE/LkYw3sqaBia67h/3awoqNvGqiFRJ+OTWYmU # CO2GAXsePHi+/JUNAax3kpqstbl3vcTdOGhtKShvZIvjwulRH87rbukNyHGWX5tN # K/WABKf+Gnoi4cmisS7oSimgHUI0Wn/4elNd40BFdSZ1EwpuddZ+Wr7+Dfo0lcHf # lm/FDDrOJ3rWqauUP8hsokDoI7D/yUVI9DAE/WK3Jl3C4LKwIpn1mNzMyptRwsXK # rop06m7NUNHdlTDEMovXAIDGAvYynPt5lutv8lZeI5w3MOlCybAZDpK3Dy1MKo+6 # aEtE9vtiTMzz/o2dYfdP0KWZwZIXbYsTIlg1YIetCpi5s14qiXOpRsKqFKqav9R1 # R5vj3NgevsAsvxsAnI8Oa5s2oy25qhsoBIGo/zi6GpxFj+mOdh35Xn91y72J4RGO # JEoqzEIbW3q0b2iPuWLA911cRxgY5SJYubvjay3nSMbBPPFsyl6mY4/WYucmyS9l # o3l7jk27MAe145GWxK4O3m3gEFEIkv7kRmefDR7Oe2T1HxAnICQvr9sCAwEAAaOC # ARYwggESMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvAnfKyA2bLMB0GA1UdDgQW # BBT2d2rdP/0BE/8WoWyCAi/QCj0UJTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ # BAUwAwEB/zATBgNVHSUEDDAKBggrBgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAw # UAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJU # cnVzdFJTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMDUGCCsGAQUFBwEBBCkw # JzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG # 9w0BAQwFAAOCAgEADr5lQe1oRLjlocXUEYfktzsljOt+2sgXke3Y8UPEooU5y39r # AARaAdAxUeiX1ktLJ3+lgxtoLQhn5cFb3GF2SSZRX8ptQ6IvuD3wz/LNHKpQ5nX8 # hjsDLRhsyeIiJsms9yAWnvdYOdEMq1W61KE9JlBkB20XBee6JaXx4UBErc+YuoSb # 1SxVf7nkNtUjPfcxuFtrQdRMRi/fInV/AobE8Gw/8yBMQKKaHt5eia8ybT8Y/Ffa # 6HAJyz9gvEOcF1VWXG8OMeM7Vy7Bs6mSIkYeYtddU1ux1dQLbEGur18ut97wgGwD # iGinCwKPyFO7ApcmVJOtlw9FVJxw/mL1TbyBns4zOgkaXFnnfzg4qbSvnrwyj1Ni # urMp4pmAWjR+Pb/SIduPnmFzbSN/G8reZCL4fvGlvPFk4Uab/JVCSmj59+/mB2Gn # 6G/UYOy8k60mKcmaAZsEVkhOFuoj4we8CYyaR9vd9PGZKSinaZIkvVjbH/3nlLb0 # a7SBIkiRzfPfS9T+JesylbHa1LtRV9U/7m0q7Ma2CQ/t392ioOssXW7oKLdOmMBl # 14suVFBmbzrt5V5cQPnwtd3UOTpS9oCG+ZZheiIvPgkDmA8FzPsnfXW5qHELB43E # T7HHFHeRPRYrMBKjkb8/IN7Po0d0hQoF4TeMM+zYAJzoKQnVKOLg8pZVPT8xggST # MIIEjwIBATBqMFUxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxLDAqBgNVBAMTI1NlY3RpZ28gUHVibGljIFRpbWUgU3RhbXBpbmcgQ0EgUjQx # AhEA507yVbBQT/rbpt/3/IujFTANBglghkgBZQMEAgIFAKCCAfowGgYJKoZIhvcN # AQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjA5MjgxNTQ0MTFa # MD8GCSqGSIb3DQEJBDEyBDCYztPyANR/TXke0XsMas4gpAxFcK6YQKNhTIuePkZ1 # WmiLJMJB4wddmXAeWdoFED0wggF7BgsqhkiG9w0BCRACDDGCAWowggFmMIIBYjAW # BBTpeBipKNoVCp/hv5zMequ5oA7urDCBiAQUZcMoaW99TlAs/QPHwgaXGMr7908w # cDBbpFkwVzELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEu # MCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBSb290IFI0NgIR # AJCsCHIg/cWnxGtcxw33PQYwgbwEFIU9Yy2TgoJhfNCQNcSR3pLBQtrHMIGjMIGO # pIGLMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UE # BxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEu # MCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQIQ # NsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0BAQEFAASCAgCGbwZlhP+xvcveCtGx # AHKVHOwh8sjnU0Yo8B2w9CqGFz4HRwDKudQoDTV7kmd0mevAilM3lQdB/VID5094 # JSElZ10bnbbcFaxcWOF++64u+AFdRXNEhqrh8un9Y7Yiw12Xsm7fxUQ5zgmeAuZl # +3t4/mOula1Nt9k/FCKGGD/aIazTtY7ijr7cmr8ttms2d3Jx8dT75vRYn9BHHUPy # h2OUE/1J4rHcX8Tlv9f1e/AxzdJbLDh/deLeyexowjSOVe+Ee7HDsif/5tVQYWhZ # DtczE8jxhzvxzYyAWmRKjF+aOZOSlLoK9P+Lky52kcumkbRTnrBE1GztSxQmC31J # O3+BQSOO8/kLS5sbvxFS6+r8ga1zo8WI/nYQBHKIjvGht9cnLqe9W97WjIAo+LrL # h/00fWEox1DmL1KS8LhmB4paWQMBA0hGyUrvx6V0LxU2DA4VYof/LoBvaWQ9AEZv # rKOqupPkoWRCMEBblQq9KXVUQi6ussxjPkVavOQQstSybUsB5oJssCeXbiu1B+U3 # 4apmPqP3VgIRUJ38NFs5/h6MsxZ3YXMX46jySLkWaSkswmMzdiFStoQqcYITeVD1 # bdlchrQ5bbc20xVkmOnck1tcDmlGeck0cl2yQY7oT7DL021lR1mJLe7u9Dm3+9KQ # YM6oIAOyj36fKDzC79xOmhSvSA== # SIG # End signature block |