Tests/AMPowerShellTemplate.tests.ps1
<#
Author: Flemming Rohde - flr@automize.dk #> #region variables #ModuleName $ModuleName = ($MyInvocation.MyCommand.Name).Substring(0, ($MyInvocation.MyCommand.Name).IndexOf(".")) $TestsFolderPath = Split-Path $MyInvocation.MyCommand.path $temppath = $TestsFolderPath.Substring(0, $TestsFolderPath.LastIndexOf("\")) $Version = $temppath.Substring($temppath.LastIndexOf("\") + 1) Set-location $TestsFolderPath Set-Location '..\' #Params for Module file $ModuleFileName = "$ModuleName.psm1" $ModuleFileParams = @{ name = $ModuleFileName path = "..\$Version\$ModuleFileName" } #Params for Manifest file $ManifestFileName = "$ModuleName.psd1" $manifestFileParams = @{ name = $ManifestFileName path = "..\$Version\$ManifestFileName" } #Params for test file $TestFileName = "$ModuleName.tests.ps1" $TestFileParams = @{ name = $TestFileName path = "..\$Version\Tests\$TestFileName" } #endregion <# .Synopsis Test a script with PowerShellScriptAnalyzer and Pester .DESCRIPTION Takes a name and path as parameters and does standard PowerShellScriptAnalyzer tests with Pester .EXAMPLE Test-SciptAnalyzer -Name PowerShellScript.ps1 -Path .\PowerShellScript.ps1 .FUNCTIONALITY Pester PowerShellScriptAnalyzer #> Function Test-SciptAnalyzer { param( [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Name, [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Path ) $analysis = Invoke-ScriptAnalyzer -Path $Path $scriptAnalyzerRules = Get-ScriptAnalyzerRule forEach ($rule in $scriptAnalyzerRules) { It "Should pass $rule" { If ($analysis.RuleName -contains $rule) { $analysis | Where-Object RuleName -EQ $rule -outvariable failures | Out-Default $failures.Count | Should -Be 0 -Because 'It is recommended to avoid in PowerShell scripts/modules' } } } } Describe "Verify $ModuleName Files" { Context "Verify minimum version of Pester" { It "Major Version should be at least 4" { ((Get-Module -Name Pester).Version.Major -ge 4)| Should be $true } It "Minor Version should be at least 2" { ((Get-Module -Name Pester).Version.Minor -ge 2) | Should be $true } } Context "Testing $ModuleFileName against PowerShellScriptAnalyzer rules" { Test-SciptAnalyzer @ModuleFileParams } Context "Testing $ManifestFileName against PowerShellScriptAnalyzer rules" { Test-SciptAnalyzer @manifestFileParams } Context "Testing $TestFileName against PowerShellScriptAnalyzer rules" { Test-SciptAnalyzer @TestFileParams } Context "PowerShell Manifest tests" { $ModuleManifestPath = "..\$Version\$ManifestFileName" $Manifest = Import-PowerShellDataFile -Path $ModuleManifestPath it "Must have the root module fullfilled" { $Manifest.rootmodule | Should not benullorempty } it "Must have the author key fullfilled" { $Manifest.Author | should not benullorempty } it "Must have the description key fullfilled" { $Manifest.Description | should not benullorempty } it "Must have the company name key fullfilled" { $Manifest.CompanyName | should not benullorempty } it "Must have version $Version" { $Manifest.ModuleVersion | Should -Be $Version } it 'Must pass the Test-ModuleManifest Validation' { Test-ModuleManifest -Path $ModuleManifestPath | should be $true } } Context "Code Unit tests" { It 'Import the module' { {Import-Module .\$ModuleName} | Should -Not -Throw } It 'Check whatif property of New-AMPowerShellModule output is null' { New-AMPowerShellModule -Name MyModule -Path C:\MyPath\ -Author 'Flemming Rohde' -CompanyName Automize -Copyright 2018 -ModuleVersion 1.0.0.0 -Description testing -WhatIf | Should -Be $null } It 'Check whatif property of New-AMPowerShellScript output is null' { New-AMPowerShellScript -Name MyScript -Path C:\MyPath -WhatIf | Should -Be $null } It 'Test New-AMPowerShellModule' { Mock New-AMPowerShellModule {} New-AMPowerShellModule -Name MyModule -Path C:\MyPath\ -Author 'Flemming Rohde' -CompanyName Automize -Copyright 2018 -ModuleVersion 1.0.0.0 -Description testing | Should -Be $Null } It 'Test New-AMPowerShellScript' { mock New-Item {} -ModuleName $ModuleName -Verifiable Mock Out-File {} -ModuleName $ModuleName -Verifiable mock Get-Content {} -ModuleName $ModuleName -Verifiable mock Push-Location {} -ModuleName $ModuleName -Verifiable mock Invoke-Pester {} -ModuleName $ModuleName -Verifiable New-AMPowerShellScript -Name MyScript -Path C:\MyPath | should -Be $null Assert-VerifiableMock } It 'Remove the module' { {Remove-Module $ModuleName} | Should -Not -Throw } } Context "Verify Codesigning of files" { $files = Get-ChildItem -File -Recurse | Where-Object {$PSItem.name -notlike "*.json"} foreach ($file in $files) { it "$($file.name) should be signed" { (Get-AuthenticodeSignature -FilePath $file.FullName).Status | Should -Be 'Valid' } } } } set-location ..\..\ # SIG # Begin signature block # MIIcbQYJKoZIhvcNAQcCoIIcXjCCHFoCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU/iUzb11ZUP34eMRVhMffQ99T # ALugghecMIIFJTCCBA2gAwIBAgIQBvr9sL154xnLx2xzI6KkMjANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE2MTAxNDAwMDAwMFoXDTE5MTAy # MzEyMDAwMFowYjELMAkGA1UEBhMCREsxEzARBgNVBAgTClN5ZGRhbm1hcmsxEDAO # BgNVBAcTB0tvbGRpbmcxFTATBgNVBAoTDEF1dG9taXplIFAvUzEVMBMGA1UEAxMM # QXV0b21pemUgUC9TMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw9ot # S4zzE1kP2SFLvYVXeM16FNJOMaESNYXUuE9rrzXUDyBpLA9EiCvOvnAaii1XvFfg # 6OJpCppnNzrJCZ3rTdHm7Lf/P7LCQUk3Pc6xI5jHcLKUaINFo529+2yVqNPzqMJ/ # OgT2nxQiU6BaEwauK5xEbRwF/Fu3jZMvC7+1TM3MjO6aGnoey0kYaHrXdY+lqTlp # QJ287vrYrJIsYZfrlYkEQTJe5wMx8QL6KvkMfXxeFoUVz9SIS9CPsYhHRYlEAWhD # hgV+x/8l3Kpiu8lrsfpqQndS/rfS46sIhtmI2ppc2kWqvcXfAvxzVF/3P5p0JbbF # hPBrjKE6V6C/nhKvHwIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6Xq # cQPAYPkt9mV1DlgwHQYDVR0OBBYEFLZGaqf5X3DRHeeZ1xZYk5xr4MKDMA4GA1Ud # DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Ax # hi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNy # bDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1j # cy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYc # aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUF # BwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4G # CCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRT # SEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAQEANMxgqONAb/uyja3uk0w1n/9pNE82rs8Mt6HrB4N6Xe2Y # EHD01OXq97y1wikMG/G5rD8N16S9LtQpI3YqmjukuKr96Rm8oPapw13hTyYYPouV # Wkxm/jzEmvp6rkLXR4cX4+VRHbepyZRv3ATzH/3B9zu/wM54AmNShgpSobYC6YR1 # RdeaDI9kbQbv4x0qlkAGTiF4O5bzX3EQyOgx8LTF1WuKVQySTNukrC36XaCZ1TgG # 1lG5M3/AV0Aw6f6RvzPZqwAypj2/ncuRJ19ElsMmXd7f3CMO/gJKV2yhr90yS0ik # DHb1vm6mdP1QnBe/em2i40GF4tvCOKZAGm6+YLdruDCCBTAwggQYoAMCAQICEAQJ # GBtf1btmdVNDtW+VUAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk # MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTEzMTAyMjEy # MDAwMFoXDTI4MTAyMjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMo # RGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQTCCASIwDQYJ # KoZIhvcNAQEBBQADggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsxSRnP0PtFmbE6 # 20T1f+Wondsy13Hqdp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawOeSg6funRZ9PG # +yknx9N7I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJRdQtoaPpiCwg # la4cSocI3wz14k1gGL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEcz+ryCuRXu0q1 # 6XTmK/5sy350OTYNkO/ktU6kqepqCquE86xnTrXE94zRICUj6whkPlKWwfIPEvTF # jg/BougsUfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8lk9ECAwEAAaOC # Ac0wggHJMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNV # HR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRB # c3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARIMEYwOAYKYIZI # AYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v # Q1BTMAoGCGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAf # BgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQsFAAOC # AQEAPuwNWiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/Er4v97yrfIFU3 # sOH20ZJ1D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3nEZOXP+QsRsH # DpEV+7qvtVHCjSSuJMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpoaK+bp1wgXNlx # sQyPu6j4xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW6Fkd6fp0ZGuy # 62ZD2rOwjNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ92JuoVP6EpQY # hS6SkepobEQysmah5xikmmRR7zCCBmowggVSoAMCAQICEAMBmgI6/1ixa9bV6uYX # 8GYwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGln # aUNlcnQgQXNzdXJlZCBJRCBDQS0xMB4XDTE0MTAyMjAwMDAwMFoXDTI0MTAyMjAw # MDAwMFowRzELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSUwIwYDVQQD # ExxEaWdpQ2VydCBUaW1lc3RhbXAgUmVzcG9uZGVyMIIBIjANBgkqhkiG9w0BAQEF # AAOCAQ8AMIIBCgKCAQEAo2Rd/Hyz4II14OD2xirmSXU7zG7gU6mfH2RZ5nxrf2uM # nVX4kuOe1VpjWwJJUNmDzm9m7t3LhelfpfnUh3SIRDsZyeX1kZ/GFDmsJOqoSyyR # icxeKPRktlC39RKzc5YKZ6O+YZ+u8/0SeHUOplsU/UUjjoZEVX0YhgWMVYd5SEb3 # yg6Np95OX+Koti1ZAmGIYXIYaLm4fO7m5zQvMXeBMB+7NgGN7yfj95rwTDFkjePr # +hmHqH7P7IwMNlt6wXq4eMfJBi5GEMiN6ARg27xzdPpO2P6qQPGyznBGg+naQKFZ # OtkVCVeZVjCT88lhzNAIzGvsYkKRrALA76TwiRGPdwIDAQABo4IDNTCCAzEwDgYD # VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH # AwgwggG/BgNVHSAEggG2MIIBsjCCAaEGCWCGSAGG/WwHATCCAZIwKAYIKwYBBQUH # AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwggFkBggrBgEFBQcCAjCC # AVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABp # AGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBw # AHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQ # AC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQBy # AHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0 # ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwBy # AHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBl # AG4AYwBlAC4wCwYJYIZIAYb9bAMVMB8GA1UdIwQYMBaAFBUAEisTmLKZB+0e36K+ # Vw0rZwLNMB0GA1UdDgQWBBRhWk0ktkkynUoqeRqDS/QeicHKfTB9BgNVHR8EdjB0 # MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk # SURDQS0xLmNybDA4oDagNIYyaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lD # ZXJ0QXNzdXJlZElEQ0EtMS5jcmwwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzAB # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9j # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEuY3J0MA0G # CSqGSIb3DQEBBQUAA4IBAQCdJX4bM02yJoFcm4bOIyAPgIfliP//sdRqLDHtOhcZ # cRfNqRu8WhY5AJ3jbITkWkD73gYBjDf6m7GdJH7+IKRXrVu3mrBgJuppVyFdNC8f # cbCDlBkFazWQEKB7l8f2P+fiEUGmvWLZ8Cc9OB0obzpSCfDscGLTYkuw4HOmksDT # jjHYL+NtFxMG7uQDthSr849Dp3GdId0UyhVdkkHa+Q+B0Zl0DSbEDn8btfWg8cZ3 # BigV6diT5VUW8LsKqxzbXEgnZsijiwoc5ZXarsQuWaBh3drzbaJh6YoLbewSGL33 # VVRAA5Ira8JRwgpIr7DUbuD0FAo6G+OPPcqvao173NhEMIIGzTCCBbWgAwIBAgIQ # Bv35A5YDreoACus/J7u6GzANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJVUzEV # MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t # MSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEw # MDAwMDAwWhcNMjExMTEwMDAwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQD # ExhEaWdpQ2VydCBBc3N1cmVkIElEIENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDogi2Z+crCQpWlgHNAcNKeVlRcqcTSQQaPyTP8TUWRXIGf7Syc # +BZZ3561JBXCmLm0d0ncicQK2q/LXmvtrbBxMevPOkAMRk2T7It6NggDqww0/hhJ # gv7HxzFIgHweog+SDlDJxofrNj/YMMP/pvf7os1vcyP+rFYFkPAyIRaJxnCI+QWX # faPHQ90C6Ds97bFBo+0/vtuVSMTuHrPyvAwrmdDGXRJCgeGDboJzPyZLFJCuWWYK # xI2+0s4Grq2Eb0iEm09AufFM8q+Y+/bOQF1c9qjxL6/siSLyaxhlscFzrdfx2M8e # CnRcQrhofrfVdwonVnwPYqQ/MhRglf0HBKIJAgMBAAGjggN6MIIDdjAOBgNVHQ8B # Af8EBAMCAYYwOwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcD # AwYIKwYBBQUHAwQGCCsGAQUFBwMIMIIB0gYDVR0gBIIByTCCAcUwggG0BgpghkgB # hv1sAAEEMIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3dy5kaWdpY2VydC5jb20v # c3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUFBwICMIIBVh6CAVIAQQBu # AHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0 # AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4AYwBl # ACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAAUwAg # AGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAAQQBn # AHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkAYQBi # AGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIAYQB0 # AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUALjAL # BglghkgBhv1sAxUwEgYDVR0TAQH/BAgwBgEB/wIBADB5BggrBgEFBQcBAQRtMGsw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw # AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov # L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDAd # BgNVHQ4EFgQUFQASKxOYspkH7R7for5XDStnAs0wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQEFBQADggEBAEZQPsm3KCSnOB22Wymv # Us9S6TFHq1Zce9UNC0Gz7+x1H3Q48rJcYaKclcNQ5IK5I9G6OoZyrTh4rHVdFxc0 # ckeFlFbR67s2hHfMJKXzBBlVqefj56tizfuLLZDCwNK1lL1eT7EF0g49GqkUW6aG # MWKoqDPkmzmnxPXOHXh2lCVz5Cqrz5x2S+1fwksW5EtwTACJHvzFebxMElf+X+Ee # vAJdqP77BzhPDcZdkbkPZ0XN1oPt55INjbFpjE/7WeAjD9KqrgB87pxCDs+R1ye3 # Fu4Pw718CqDuLAhVhSK46xgaTfwqIa1JMYNHlXdx3LEbS0scEJx3FMGdTy9alQgp # ECYxggQ7MIIENwIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl # cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp # Q2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBAhAG+v2wvXnjGcvH # bHMjoqQyMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkG # CSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE # AYI3AgEVMCMGCSqGSIb3DQEJBDEWBBSAt1aclg7LU1UtzB5ViDaDTiyNFTANBgkq # hkiG9w0BAQEFAASCAQAUbT2xM7aZJz2QvybEZRt+Dl4WWA0CoAfy6Q0t1e0SCZZ7 # bvoj+oxr1i8ZVGY4m3XtB76OXE/ma/gIIm42+FYtnexoZp7g9V4H7Ks88bYIigu3 # MXVXLzLsvbVAXrZkC0jj2l3o7CRC6zn0jHqJ4wIJvVBjz0RUgfkU7Mnj6YMJ2I5q # xLux085UE8hHKv9I4+AFKtgBs6lOZG3ZRIOS4tn0qpX5QMIV/9dGh12OxXHFU3fo # zQqegbo/ojOc33AUWr+ubxN0xXSc9PIsH/qSs2nFWPa4s93IdJLtIoTfRWcDiNZK # Lf8f6R8yLx3+eYGgQXCQhAwPi0Ba22dq6Vn8tfk6oYICDzCCAgsGCSqGSIb3DQEJ # BjGCAfwwggH4AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl # cnQgQXNzdXJlZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCg # XTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODAz # MTUxMzM2MzVaMCMGCSqGSIb3DQEJBDEWBBQ/cJKyQKUQtUwuuEku1BiaIgScCTAN # BgkqhkiG9w0BAQEFAASCAQB3fnEx+9ShvdDlxv7XOa5RHNPv2f3M+dm4BQK2O/Dk # 5SScKll0xGn8m1zPN3fXBKyrS+YruXYRDhrlxiiKYh2A9usZ2O9eTI+0Q4u2Tj6G # WMo+KHbZ4Tiy4TPQxa82GrMvMpFl2gWdm5Lun44c4X3hJvs9VkMEz6/MhoYeTlo7 # B45hnZpIGl+T12//V4nHZ8pDxpgA79f9iPXRG2jv4sNyzbhEUX6uTIz/u8j8VqqU # XkwcKII9kVG9g0VUWeQLkHMIg6DyS4IliRCvmzABMaiX0mcQCSb8syAwFKW0l88L # 0E3MP2AJVxGdiXBD50/BlsFWmB2AKHxXEd5QSMtcNG5N # SIG # End signature block |