Engines/Terraform/Invoke-AvmTerraformLint.ps1
|
function Resolve-AvmTflintConfigDir { <# .SYNOPSIS Resolve the directory holding the vendored AVM tflint configs. .DESCRIPTION Returns the absolute path to the directory that ships the three AVM tflint rulesets ('avm.tflint.hcl', 'avm.tflint_module.hcl', 'avm.tflint_example.hcl'). Resolution order: 1. $env:AVM_TFLINT_CONFIG_DIR - explicit override (test injection and power users pointing at a locally-checked-out governance copy). 2. <ModuleRoot>/Resources/tflint - the configs vendored inside the module, kept byte-for-byte in sync with the governance tflint-configs/ folder. The chosen candidate must be a directory containing all three files. Throws AvmConfigurationException when none resolve, so the lint engine surfaces a clear package-integrity error rather than linting with no AVM rules. .OUTPUTS [string] absolute path to the resolved config directory. #> [CmdletBinding()] [OutputType([string])] param() Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' $required = @('avm.tflint.hcl', 'avm.tflint_module.hcl', 'avm.tflint_example.hcl') $candidates = New-Object System.Collections.Generic.List[string] if ($env:AVM_TFLINT_CONFIG_DIR) { $candidates.Add($env:AVM_TFLINT_CONFIG_DIR) } $moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) $candidates.Add((Join-Path $moduleRoot (Join-Path 'Resources' 'tflint'))) foreach ($candidate in $candidates) { if (-not $candidate) { continue } if (-not (Test-Path -LiteralPath $candidate -PathType Container)) { continue } $present = $true foreach ($file in $required) { if (-not (Test-Path -LiteralPath (Join-Path $candidate $file) -PathType Leaf)) { $present = $false break } } if ($present) { return (Resolve-Path -LiteralPath $candidate).ProviderPath } } throw [AvmConfigurationException]::new( ("Cannot resolve the AVM tflint config bundle (looked in: {0}). " -f ($candidates -join '; ')) + 'Set the AVM_TFLINT_CONFIG_DIR environment variable or reinstall Avm.Authoring so Resources/tflint is present.') } function Get-AvmTflintScope { <# .SYNOPSIS Build the ordered list of directories tflint should lint, each paired with the AVM ruleset that applies to it. .DESCRIPTION The AVM tflint rulesets are directory-specific: the repository root and every nested module use the strict rulesets, while examples use a relaxed ruleset (interface/docs rules disabled). A single recursive tflint invocation cannot express that, so the lint engine runs tflint once per scope with the matching '--config'. Scope order (deterministic): 1. the repository root -> avm.tflint.hcl 2. each direct modules/* dir -> avm.tflint_module.hcl (sorted by name) 3. each direct examples/* dir -> avm.tflint_example.hcl (sorted by name) modules/ and examples/ are enumerated one level deep (matching the governance 'foreachdirectory depth:1' behaviour) and skipped entirely when absent. .PARAMETER Root The Terraform repository root. .PARAMETER ConfigDir The directory returned by Resolve-AvmTflintConfigDir. .OUTPUTS [object[]] of hashtables with keys Dir (absolute), Config (absolute), Label, and RelPath ('.' for the root). #> [CmdletBinding()] [OutputType([object[]])] param( [Parameter(Mandatory)] [string] $Root, [Parameter(Mandatory)] [string] $ConfigDir ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' $rootFull = (Resolve-Path -LiteralPath $Root).ProviderPath $scopes = New-Object System.Collections.Generic.List[object] $scopes.Add(@{ Dir = $rootFull Config = (Join-Path $ConfigDir 'avm.tflint.hcl') Label = 'root' RelPath = '.' }) $groups = @( @{ Name = 'modules'; Config = 'avm.tflint_module.hcl' } @{ Name = 'examples'; Config = 'avm.tflint_example.hcl' } ) foreach ($group in $groups) { $groupDir = Join-Path $rootFull $group.Name if (-not (Test-Path -LiteralPath $groupDir -PathType Container)) { continue } $children = @(Get-ChildItem -LiteralPath $groupDir -Directory -ErrorAction SilentlyContinue | Sort-Object Name) foreach ($child in $children) { $scopes.Add(@{ Dir = $child.FullName Config = (Join-Path $ConfigDir $group.Config) Label = ('{0}/{1}' -f $group.Name, $child.Name) RelPath = ('{0}/{1}' -f $group.Name, $child.Name) }) } } return $scopes.ToArray() } function Initialize-AvmTerraformLintScope { [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] $Scope, [Parameter(Mandatory)] $Options ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' $filesProcessed = @( Get-ChildItem ` -LiteralPath $Scope.Dir ` -File ` -Filter '*.tf' ` -ErrorAction SilentlyContinue ).Count $null = Invoke-AvmTerraformInit ` -TerraformPath $Options.TerraformPath ` -WorkingDirectory $Scope.Dir ` -Label ('{0}: terraform init' -f $Scope.Label) ` -StreamOutput:$Options.StreamOutput if ($Scope.Label -like 'examples/*') { Invoke-AvmScriptHook ` -HookPath (Join-Path $Scope.Dir 'tflint-pre.ps1') ` -WorkingDirectory $Scope.Dir ` -Label ('{0}: tflint-pre.ps1' -f $Scope.Label) } return [pscustomobject]@{ Label = $Scope.Label FilesProcessed = $filesProcessed } } function Invoke-AvmTflintScope { [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] $Scope, [Parameter(Mandatory)] $Options ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' $lintArgs = @( '--config', $Scope.Config, '--format=json', ('--minimum-failure-severity={0}' -f $Options.MinimumFailureSeverity) ) $run = Invoke-AvmProcess ` -FilePath $Options.TflintPath ` -ArgumentList $lintArgs ` -WorkingDirectory $Scope.Dir ` -IgnoreExitCode ` -StreamOutput:$Options.StreamOutput ` -Label ('{0}: tflint' -f $Scope.Label) if ($run.ExitCode -ne 0 -and $run.ExitCode -ne 2) { $stderr = if ($run.StdErr) { $run.StdErr.Trim() } else { '' } $tail = if ($stderr) { ": $stderr" } else { '.' } throw [AvmProcessException]::new( ("tflint for scope '{0}' exited with code {1}{2}" -f $Scope.Label, $run.ExitCode, $tail)) } $issues = [System.Collections.Generic.List[object]]::new() $payload = if ($run.StdOut) { $run.StdOut.Trim() } else { '' } if (-not $payload) { return [pscustomobject]@{ Label = $Scope.Label Issues = @() } } try { $parsed = $payload | ConvertFrom-Json -ErrorAction Stop } catch { throw [AvmProcessException]::new( ("Could not parse tflint --format=json output for scope '{0}': {1}" -f $Scope.Label, $_.Exception.Message)) } if (-not ($parsed -and ($parsed.PSObject.Properties.Name -contains 'issues'))) { return [pscustomobject]@{ Label = $Scope.Label Issues = @() } } foreach ($issue in @($parsed.issues)) { $severity = if ($issue.rule -and $issue.rule.severity) { ([string]$issue.rule.severity).ToLowerInvariant() } else { 'warning' } if ($severity -eq 'info') { $severity = 'notice' } $code = if ($issue.rule -and $issue.rule.name) { [string]$issue.rule.name } else { '' } # AVM-DEFERRED-AZAPI: report the finding, but not at a severity that fails # the gate. Demoting here, at parse time, keeps Status, the emitted # warnings and the returned Issues agreeing on one severity. if ((Test-AvmDeferredAzapiRule -Code $code) -and $severity -ne 'notice') { $severity = 'notice' } $message = if ($issue.message) { [string]$issue.message } else { '' } $file = '' $line = 0 $column = 0 if ($issue.range) { if ($issue.range.filename) { $file = [string]$issue.range.filename } if ($issue.range.start) { if ($issue.range.start.line) { $line = [int]$issue.range.start.line } if ($issue.range.start.column) { $column = [int]$issue.range.start.column } } } if ($Scope.RelPath -ne '.' -and $file) { $file = ('{0}/{1}' -f $Scope.RelPath, $file) } $file = $file -replace '\\', '/' $issues.Add([pscustomobject][ordered]@{ File = $file Line = $line Column = $column Severity = $severity Code = $code Message = $message Scope = $Scope.Label }) } return [pscustomobject]@{ Label = $Scope.Label Issues = $issues.ToArray() } } function Test-AvmDeprecatedInterfaceNotice { [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory)] [object] $Issue ) $severity = $Issue.PSObject.Properties['Severity'] $code = $Issue.PSObject.Properties['Code'] return ( $null -ne $severity -and [string]$severity.Value -eq 'notice' -and $null -ne $code -and [string]$code.Value -cmatch '^deprecated_[a-z0-9]+(?:_[a-z0-9]+)*_interface$' ) } function Get-AvmDeferredAzapiRule { <# .SYNOPSIS Rule names reported but demoted to 'notice' instead of failing the gate. .DESCRIPTION AVM-DEFERRED-AZAPI. These rules became active fleet-wide in 0.10.0, when 'disabled_by_default' was dropped from the packaged configurations, and together they failed 'avm pr-check' at the lint step in 180 of 188 AVM Terraform module repositories. They stay enabled so every run still reports them with source locations; Invoke-AvmTerraformLint demotes them so they do not fail the run. To restore enforcement, delete names from this function: - one rule -> delete its entry - one family -> delete that array and its term in the return - everything -> return an empty array, or delete this function, Test-AvmDeferredAzapiRule, and the two call sites tagged AVM-DEFERRED-AZAPI Nothing else needs to change: an empty list makes the demotion a no-op. The guard test in tests/Pester/Unit/Private/Engines/DeferredAzapiRules.Tests.ps1 pins this list, so any change is deliberate and reviewed. Tracked in https://github.com/Azure/azure-verified-modules-tools/issues/80. .OUTPUTS [string[]] deferred rule names. #> [CmdletBinding()] [OutputType([string[]])] param() Set-StrictMode -Version 3.0 # TFFR6/7/8 AzAPI interface requirements. Mechanical to satisfy - declare the # variables with the documented shapes - so this family returns first. $interface = @( 'azapi_response_export_values' 'ignore_body_changes' 'resource_types' 'retry' 'timeouts' ) # TFFR3 AzureRM-to-AzAPI migration. Returns once the per-module migrations land. $provider = @( 'provider_azurerm_disallowed' ) return @($interface + $provider) } function Test-AvmDeferredAzapiRule { <# .SYNOPSIS Is this tflint rule name currently deferred to 'notice' severity? .DESCRIPTION AVM-DEFERRED-AZAPI. Case-sensitive match against Get-AvmDeferredAzapiRule. tflint rule names are lowercase and stable, so a case-sensitive compare avoids demoting a differently-cased rule that happens to collide. .PARAMETER Code The tflint rule name from a parsed issue. May be empty. .OUTPUTS [bool] #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory)] [AllowEmptyString()] [string] $Code ) Set-StrictMode -Version 3.0 if ([string]::IsNullOrWhiteSpace($Code)) { return $false } return (Get-AvmDeferredAzapiRule) -ccontains $Code } function Invoke-AvmTerraformLint { <# .SYNOPSIS Run the AVM tflint rulesets against every Terraform scope and fail on warnings by default. .DESCRIPTION Engine implementation called by Invoke-AvmLint when the module context is Ecosystem='terraform'. Resolves 'tflint' via Resolve-AvmTool and the vendored AVM rulesets via Resolve-AvmTflintConfigDir. Repository-root avm.tflint.override.hcl, avm.tflint_example.override.hcl, and avm.tflint_module.override.hcl files are merged over those immutable bases in an isolated cache directory. A direct module or example scope can add a final avm.tflint.override.hcl file in its own directory. The repository is copied to a clean temporary tree before every scope produced by Get-AvmTflintScope is evaluated. Terraform initialization and lint execution are bounded parallel phases; each distinct TFLint configuration is initialized once between them: terraform init -upgrade -input=false tflint --init --config <absolute ruleset> (install plugins) tflint --config <absolute ruleset> --format=json \ --minimum-failure-severity=<threshold> (lint) This mirrors the legacy Terraform governance pre-check flow, including its repository-root override lookup and override-first attribute precedence. Example scopes reject tflint-pre.sh and run tflint-pre.ps1, when present, after Terraform initialization and before TFLint starts. Generated Terraform state remains confined to the temporary tree. A single recursive invocation with no '--config' (the previous behaviour) applied none of the AVM rules and could not express the per-directory rulesets. The failure threshold defaults to 'warning', so any warning-severity rule fails the gauntlet - most built-in tflint rules are warnings, so an 'error'-only threshold reported false confidence. The threshold is passed to tflint (via --minimum-failure-severity, driving its exit code) and used to compute Status from the parsed issues, so both agree. All issues are still parsed and returned for reporting regardless of the threshold. AVM-plugin notice rules named 'deprecated_*_interface' are also emitted immediately as non-failing warnings with source locations. They remain notice issues in the returned result. The rules listed by Get-AvmDeferredAzapiRule (AVM-DEFERRED-AZAPI) stay enabled in the packaged configurations but are demoted from 'error' to 'notice' at parse time, then emitted as non-failing warnings the same way. They therefore appear on every run, with file and line, without failing the gate. Deleting a name from that list restores enforcement for it; nothing else has to change. tflint exit codes for the lint call: 0 - no issues at or above the threshold 2 - issues found (parsed; drives Status via the threshold) other - tflint itself failed (throws AvmProcessException) .PARAMETER Context Module context produced by Get-AvmModuleContext. Must have Ecosystem='terraform'. .PARAMETER AllowPathFallback Pass through to Resolve-AvmTool. .PARAMETER MinimumFailureSeverity The lowest tflint severity that fails the run. One of 'error', 'warning' (default), or 'notice'. .PARAMETER ThrottleLimit Maximum number of independent Terraform scopes to process at once. Defaults to one for direct engine calls. .OUTPUTS pscustomobject with Engine, Tool, ToolPath, ToolSource, Status, FilesProcessed, Issues. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)] $Context, [switch] $AllowPathFallback, [ValidateSet('error', 'warning', 'notice')] [string] $MinimumFailureSeverity = 'warning', [ValidateRange(1, 32)] [int] $ThrottleLimit = 1 ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' if ($Context.Ecosystem -ne 'terraform') { throw [System.ArgumentException]::new( "Invoke-AvmTerraformLint requires a terraform context (got Ecosystem='$($Context.Ecosystem)').") } $shellHooks = @(Get-ChildItem ` -LiteralPath (Join-Path $Context.Root 'examples') ` -Filter 'tflint-pre.sh' ` -File ` -Depth 1 ` -ErrorAction SilentlyContinue | ForEach-Object { [System.IO.Path]::GetRelativePath($Context.Root, $_.FullName).Replace('\', '/') }) if ($shellHooks.Count -gt 0) { throw [AvmConfigurationException]::new( ("The terraform lint engine runs PowerShell hooks only. Refactor these shell hooks to '.ps1': {0}" -f ($shellHooks -join ', '))) } $tool = Resolve-AvmTool -Name 'tflint' -AllowPathFallback:$AllowPathFallback $terraform = Resolve-AvmTool -Name 'terraform' -AllowPathFallback:$AllowPathFallback $baseConfigDir = Resolve-AvmTflintConfigDir $sourceScopes = @( Get-AvmTflintScope -Root $Context.Root -ConfigDir $baseConfigDir ) $configSet = New-AvmTflintConfigSet ` -Root $Context.Root ` -BaseConfigDir $baseConfigDir ` -Scopes $sourceScopes $stageParent = Join-Path (Get-AvmFolder -Kind Cache) 'lint-stage' $stageRoot = Join-Path $stageParent ('avm-lint-' + [guid]::NewGuid().ToString('N')) # Severities at or above the threshold fail the run. tflint emits lowercase # 'error' / 'warning' / 'notice'. $failSeverities = switch ($MinimumFailureSeverity) { 'error' { @('error') } 'warning' { @('error', 'warning') } 'notice' { @('error', 'warning', 'notice') } } $issues = New-Object System.Collections.Generic.List[object] $filesProcessed = 0 $streamOutput = Test-AvmVerboseEnabled $effectiveThrottle = if ($streamOutput) { 1 } else { $ThrottleLimit } try { Write-AvmLog ("lint: staging terraform module at {0}" -f $stageRoot) -Level Verbose | Out-Null Copy-AvmTerraformModuleTree -SourceRoot $Context.Root -DestinationRoot $stageRoot $scopes = @(Get-AvmTflintScope -Root $stageRoot -ConfigDir $configSet.ConfigDir) foreach ($scope in $scopes) { if ($configSet.ScopeConfigNames.ContainsKey($scope.RelPath)) { $scope.Config = Join-Path ` $configSet.ConfigDir ` $configSet.ScopeConfigNames[$scope.RelPath] } } Write-AvmLog ("lint: discovered {0} terraform scope(s); failure threshold = {1}" -f $scopes.Count, $MinimumFailureSeverity) -Level Info | Out-Null Write-AvmLog ("lint: processing scopes with {0} worker(s)" -f $effectiveThrottle) -Level Verbose | Out-Null for ($scopeIndex = 0; $scopeIndex -lt $scopes.Count; $scopeIndex++) { $scope = $scopes[$scopeIndex] Write-AvmLog ("lint: scope {0}/{1} = {2}" -f ($scopeIndex + 1), $scopes.Count, $scope.Label) -Level Info | Out-Null Write-AvmLog ("lint: scope directory = {0}; config = {1}" -f $scope.Dir, $scope.Config) -Level Verbose | Out-Null } $prepareOptions = [pscustomobject]@{ TerraformPath = $terraform.Path StreamOutput = $streamOutput } $prepared = @( Invoke-AvmParallel ` -InputObject $scopes ` -FunctionName 'Initialize-AvmTerraformLintScope' ` -Argument $prepareOptions ` -ThrottleLimit $effectiveThrottle ) $filesProcessed = ($prepared | Measure-Object -Property FilesProcessed -Sum).Sum $pathComparer = if ($IsWindows) { [System.StringComparer]::OrdinalIgnoreCase } else { [System.StringComparer]::Ordinal } $initializedConfigs = [System.Collections.Generic.HashSet[string]]::new($pathComparer) foreach ($scope in $scopes) { if (-not $initializedConfigs.Add([string]$scope.Config)) { continue } $init = Invoke-AvmProcess ` -FilePath $tool.Path ` -ArgumentList @('--init', '--config', $scope.Config) ` -WorkingDirectory $scope.Dir ` -IgnoreExitCode ` -StreamOutput:$streamOutput ` -Label ('{0}: tflint init' -f $scope.Label) if ($init.ExitCode -ne 0) { $stderr = if ($init.StdErr) { $init.StdErr.Trim() } else { '' } $tail = if ($stderr) { ": $stderr" } else { '.' } throw [AvmProcessException]::new( ("tflint --init for config '{0}' exited with code {1}{2}" -f $scope.Config, $init.ExitCode, $tail)) } } $lintOptions = [pscustomobject]@{ TflintPath = $tool.Path MinimumFailureSeverity = $MinimumFailureSeverity StreamOutput = $streamOutput } $scopeResults = @( Invoke-AvmParallel ` -InputObject $scopes ` -FunctionName 'Invoke-AvmTflintScope' ` -Argument $lintOptions ` -ThrottleLimit $effectiveThrottle ) foreach ($scopeResult in $scopeResults) { foreach ($issue in $scopeResult.Issues) { $issues.Add($issue) if ( ( (Test-AvmDeprecatedInterfaceNotice -Issue $issue) -or # AVM-DEFERRED-AZAPI: surface the deferred rules the same # way, so the debt stays visible on every run. (Test-AvmDeferredAzapiRule -Code ([string]$issue.Code)) ) -and -not (Test-AvmIssuePresented -Issue $issue) ) { Write-AvmLog ` -Message ('[{0}] {1}' -f $issue.Code, $issue.Message) ` -Level Warning ` -File $issue.File ` -Line $issue.Line ` -Column $issue.Column Register-AvmPresentedIssue -Issue $issue } } } } finally { if (Test-Path -LiteralPath $stageRoot) { Remove-Item -LiteralPath $stageRoot -Recurse -Force -ErrorAction SilentlyContinue } if ($configSet.StageDir -and (Test-Path -LiteralPath $configSet.StageDir)) { Remove-Item -LiteralPath $configSet.StageDir -Recurse -Force -ErrorAction SilentlyContinue } } $status = if ($issues | Where-Object { $failSeverities -contains $_.Severity }) { 'fail' } else { 'pass' } Write-AvmLog ("lint: terraform completed with {0} issue(s) across {1} file(s)" -f $issues.Count, $filesProcessed) -Level Verbose | Out-Null return [pscustomobject][ordered]@{ Engine = 'terraform' Tool = ('{0}/{1}' -f $tool.Name, $tool.Version) ToolPath = $tool.Path ToolSource = $tool.Source Status = $status FilesProcessed = $filesProcessed Issues = $issues.ToArray() } } # SIG # Begin signature block # MIInRAYJKoZIhvcNAQcCoIInNTCCJzECAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAEn9zXODky2FQC # O5BXrvx65rBS/wHkowbbtaeZ6k+1v6CCDLowggX1MIID3aADAgECAhMzAAACHU0Z # yE7XD1dIAAAAAAIdMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQzWhcNMjcwNDE1MTg1 # OTQzWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD # VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDQvewXxx9gZZFC6Ys1WBay8BJ8kGA4JQnH5CMafqOASlTpK9H8 # o5ZXTXt0caVQTNMUPt445wXYD+dFtaKWTwDn1I52oUSrC9vJin1Gsqt+zyKJL5Dg # 3eQXbQNR61DmMy20GLTIO3SFed9Rfi/ophgCLGFLDR3r0KvHjwMb/jYWS0celV/4 # Lz27LfAekm8v9E5IXaeiXbAUYZKK090n4CVl3JBtbN+9DtI9SNu/yjvozW52/u7R # X/Ttpa/KDlpuokZ+Zcbvmtd9ur9gFLvZzh41o9MsE/clQtdaFWGvuo6Jua/ntpgk # ey3E5/vBFe+MJPG6phdnuo6r57ZudCudiI1bAgMBAAGjggGbMIIBlzAOBgNVHQ8B # Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O # BBYEFH6QuMwqcPG0hQlQ6c5jCtTTLrVeMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQL # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAxMis1MDc1NTkw # HwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEwYAYDVR0fBFkwVzBVoFOg # UYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0 # JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNybDBtBggrBgEFBQcBAQRh # MF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy # dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQBKTbYOjzwTG/DXGaz9 # s6+fQeaTtDcFmMY+5UyVFCyj7Pv+5i37qfX8lSL/tBIfYQfWsMuBQlfZurJD6r4H # VJ2CeH+1fgiq8dcHdVKoZ3Sa2qXoX3cq9iS8cVb06B7+5/XJ7I0OxHH9fDsvJ3T3 # w5V/ZtAIFmLrl+P0CtG+92uzRsn0nTbdFjOkLMLWPLAU3THohKRlSEMgFJpPkm5n # 5UAZ35xX6FWCrDLsSKb555bTifwa8mJBwdlof0bmfYidH+dxZ1FdDxvLnNl9zeKs # A4kejaaIqqIPguhwAti5Ql7BlTNoJNwxCvBmqW2MQLnCkYN/VVUsR3V2x/rcTNzo # Bf/Z/SpROvdaA2ZOOd1uioXJt3tdLQ7vHpqpib0KfWr/FWXW10q38VxfCnRQBqzb # SuztR7nEMuzX7Ck+B/XaPDXd1qh72+QYyB0Z2VzWmO9zsnb9Uq/dwu8LGeQqnyu6 # 7SDGACvnXii2fb9+US492VTnXSnFKyqwgzUyFMtZK1/sHYTv6bG4TtQUygQxTN+Z # V+aJIlKO2MqZ7bKrAnOzS9m6NgoTdWOq11bTOZwKlIEV/EhV9SWkDmdpR/hPPT2v # 6TEj4F8PT/zHjRezIU5c/DGlt/VhY/pK0XkJtEyMmmS1BMtjU/rqBZVMIm3dnxQs # /TBByr+Cf8Z1r7aifQVQ+WSqzjCCBr0wggSloAMCAQICEzMAAAA5O7Y3Gb8GHWcA # AAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoXDTM2MDMyMjIyMTMwNFow # VzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEo # MCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAyNDCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeqlRYHNa265v4IY9fH8TKh # emHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo0dtS/EW6I/yEL/bLSY8h # KpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATvQVL4tcf03aTycsz8QeCd # M0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a1uv1zerOYMnsneRRwCbp # yW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1FyQfK0fVkaya8SmVHQ/t # Of23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfOGSWHIIV4YrTJTT6PNty5 # REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7ttOu1bVnXfHaqPYl2rPs # 20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJuz2MXMCt7iw7lFPG9LXK # Gjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxSCwyoGIq0PhaA7Y+VPct5 # pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOmVQop36wUVUYklUy++vDW # eEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3SkE/xIkgpfl22MM1itkZ # 35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGC # NxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPXLQaUEggxMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # ci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUHMAKGQmh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAFJQfOChP7onn6fLI # MKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D5W4wMwYeLystcEqfkjz4 # NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBYnbu0+THSuVHTe0VTTPVh # ily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSIvgn0JksVBVMYVI5QFu/q # hnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6aR9y34aiM1qmxaxBi6OU # nyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4wPKC5OmHm1DQIt/MNokbb # H3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7RTX8AdBPo0I6OEojf39z # uFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK/fg8B2qjW88MT/WF5V5u # vZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSKYBv0VisCzfxgeU+dquXW # 9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkwYTu/9dLeH2pDqeJZAABV # DWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVTQl0v4q8J/AUmQN5W4n10 # 1cY2L4A7GTQG1h32HHAvfQESWP0xghngMIIZ3AIBATBuMFcxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jv # c29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIdTRnITtcPV0gAAAAAAh0w # DQYJYIZIAWUDBAIBBQCggZAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwLwYJ # KoZIhvcNAQkEMSIEIPbIFAUmwF1cF9+/m7Ahl6Dna7VkIX42zM0lV20kzA++MEIG # CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAvwtQ5NMSRRU0tbb/ # 6OrBXyWTVaFp0uYcU19Az8qEhj5oLu7Uo1g5IXTHXsOVKVLI34R2rnMsx1l7YPim # CQbDqZk7UdJxIGdbh9jdjOWehMtR4y3tyt16uFiSvLRUZHAsg1MR26jYfVfLbW42 # IF4QxOQUM5t5EDEVZldoTq5edHSQeVwKC7FODwI4q5UsbC+Vi6OVddq7DwVPPUMS # 56V5Z0g46Nh8sJgjk6pQnPZDwpih4KyO11IbmOUUCCIDqFs087s7cjI4K7pzKh4l # G4h+ie7OOzsw5S4LT4v9POPqFSTJQccSojqAXm4bOslwZFB4ZrAJVgJtpe87SfZq # Vu835qGCF7AwghesBgorBgEEAYI3AwMBMYIXnDCCF5gGCSqGSIb3DQEHAqCCF4kw # gheFAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFF # MIIBQQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCAZh5j6YJ9CmUJP # +MOyXlUw5U4ezCTfSGzRhUIOrheYmAIGaomzBFdTGBMyMDI2MDgyNjIzMTU1OS40 # MjdaMASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExp # bWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo1NTFBLTA1RTAtRDk0NzEl # MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEf4wggcoMIIF # EKADAgECAhMzAAACG9CyuAJn93LPAAEAAAIbMA0GCSqGSIb3DQEBCwUAMHwxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgzMFoXDTI2MTEx # MzE4NDgzMFowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEn # MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjU1MUEtMDVFMC1EOTQ3MSUwIwYDVQQD # ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAjsWd52ZZkzB5Xe5g/l2GsOjAz30sg6jVxfFJV+w4xIDV # yaI3LO8bIpmzYul3AZHg50UIQ8PrSRZGpQqFkRNu+o3YKJ4g2uGYBRksHnHYR0uV # SCQg58ThkYyeplGX3oAvGRVuPIpQtAiTsR76A/gdoU7HDwEbb73bJwTyrbKHhR+W # aMy9DQHI4k5Qo4+bZDs0kj76bvhJvdGU+S8zxQBp7UAhjJnFqKxIusSITE7zCCR4 # 22ELhkhVVOFqK2w6h1MAvILe76hxRIcPj0SBL2r8O9tx5njU4+tg2rAdU153pmyh # qazdpUccYBE9wDRFUd/e9CoWx7TdnUicB+Mai7RT6qse7e5aGqX1B7bnj/ZHvrrf # F+BJEIlS9iDXAUgekvXZ+FZmjvLwP+dN+0/crh++r4e8FknF7EX6IJfnmNeDN/68 # Z59kbaJ1f+P5mnKYfydCeZmxrGpS0taWkDk36D3jPVZflvxrc+1rhCIlM5v9agLE # FI12QiBTfpOBOBr3AGCPk+eH0+latjQajug+2/BD12qb82500LQytUWT2ota/HYn # RgSv1jvZ0/dml1FsxWYzOnCrjfdB/7N6pNySt4vn+PGN6dFLim7kxos+B9WfQPez # Ji3fuKyyDAB9zSHPj1Zu8nZfecZJ9um4zj7DFgvJXTDTnG5qlG4ZdbFRa/rrfzkC # AwEAAaOCAUkwggFFMB0GA1UdDgQWBBS2vp93/lxLppNK8OkauJ2AvNmIUDAfBgNV # HSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5o # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU # aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG # CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRz # L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNV # HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIH # gDANBgkqhkiG9w0BAQsFAAOCAgEAZkU1XxQD4OTM3GTht32TXShIfPBoMfSsFsBQ # qFOZqLJOxyJOllIBFpmpvOtGNPkC5Z8ldG8aCpvgFNo/jDWeT5FiW53dAj9KnZxp # sQ3Pf5fRzSGHRcxEMOdXIVzDJwcZUX0cjfxna7ydNv8eXB/Xk6G6SyrR2OH6S1LH # MW11m3UvKF+eLjIPl45rximuDCoEd+ad0lOAXA5/vZOKN5n/ePYeP0LRchZX0Q6H # 8n/ZmSPMlbli3MO851Q09RmT/ZGHa+/Fdy+WLDrwcYykV9mUy/4TbwKw6FtdR6ZP # HxMdIi1pk8Y2mC/GzCq0LCsH0uTFeQ6Q7Nc3MRmER/3mLWUhbaWHgX1FbYchvR22 # b+Bup+YPR5Q/0BhaaAN6AIBfcGs+u/nJoIByyZKA8cTyCmnUI/4vW6D4vywg3XBF # f4f2DwFHy/evsC+58KMl+k2wa05X2kK0T/bCPLhaov9ZXyobawfNOLYGiauKT2FW # vbwZzHIFCTxjBww6Pt5uRvCE/jnUcf/xhlOGMn6iKO9Xt49vZTE2SfIBk/34iLTR # BJ6H7aGPTTQnza3OfWu1/dRycC6Wl5ons3PjnGXTSKSxXllJPmg6R/ulGonP/UCY # oJ6mN+EXjfyDLPXLqsr91+VTG1rYzRCjPwBFAHv4EIwaE0ajCrf75eUGI3+oXU0U # P6rloZ8wggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3 # DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw # MAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx # MDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l # LVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA # 5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/ # XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1 # hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7 # M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3K # Ni1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy # 1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF80 # 3RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQc # NIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahha # YQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkL # iWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV # 2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIG # CSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUp # zxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBT # MFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jv # c29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYI # KwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGG # MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186a # GMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br # aS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsG # AQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcN # AQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1 # OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYA # A7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbz # aN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6L # GYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3m # Sj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0 # SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxko # JLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFm # PWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC482 # 2rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7 # vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDWTCC # AkECAQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExp # bWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo1NTFBLTA1RTAtRDk0NzEl # MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsO # AwIaAxUAhoV6r49M4GBd41K1RYB1Z0f4zuCggYMwgYCkfjB8MQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt # ZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO45dxUwIhgPMjAyNjA4 # MjYxNDMwNDVaGA8yMDI2MDgyNzE0MzA0NVowdzA9BgorBgEEAYRZCgQBMS8wLTAK # AgUA7jl3FQIBADAKAgEAAgIJ1QIB/zAHAgEAAgISHzAKAgUA7jrIlQIBADA2Bgor # BgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAID # AYagMA0GCSqGSIb3DQEBCwUAA4IBAQB4ffaiToQAQBZZ5nj4lOIjshhietoBLVXf # 3o3WFLjJJXAU2HDhDfzcsq9VLlB6+5KThGMZPvfAXnT0CccRr586MF+obsE/WICB # J1u6YGbkxQNkCPEV3rU5hrjoUvCpguZjqJoOUpsLLDVt6KsdNs+KIBlgD0kWKv+k # YeT+sXv6HcC09fwJpc0G7oWJh/zXlmtfpZvMIjlGCEZCQhgTwrOnh7rOU79mkpyG # OgFSzgXQeMuZf7CJ8AilVDFw3ulLOxxqgKtl/mcnUCtdDt2Bh6qEl/ZtSeqh0ew5 # b71ASh1HMonGrWoGdieB9vqrlRLmOCLOUXzz+fNt7mNVyPZMclJrMYIEDTCCBAkC # AQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIb0LK4Amf3 # cs8AAQAAAhswDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG # 9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgUvvfO8u2VaQjTq4Y45s9Fd2UdSrgPldd # Rl5TJgdiibIwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAwJRSVuD2jmMcQ # CFXdLuJAwDpUVNZ6bc6dfJU83Q2LgDCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0 # YW1wIFBDQSAyMDEwAhMzAAACG9CyuAJn93LPAAEAAAIbMCIEILuVRIYL+B0sdwHL # fXYcETP/u3qnvug1Vi0KUvQ+uDWMMA0GCSqGSIb3DQEBCwUABIICAHf2mA66hKcp # RxVN9RJPsSWf1zOYE6LnofmBsYTHL7S/hz5wtqQ+fbRFaZ5qDzZUy15mSy8zatKu # 0PPFZy37dMA+pFKRO6d8iRiVfhC+u0obcTQgKE7Y5wFFQfx+l6wmTIwDCjm0mDsB # 55QLkkeM2ywPgg1TzvWjwQLZGqcgJIkyDuhSmncOGXIc+B0JSLQqfyUOJr1eOh8u # KjlOHbXQgWU5PuVlypeebN2jR7/lyJfbmtiUcrXj15sflZvYz+Rw56CgCKPgtVGf # YKFiVmc7l5wmkfBAw5A+7Jzv/runVcl0rWm8ruK89zl4BsOVVGvczQNePP4KuA0X # 8wmhuwyLrlnykfbYf8Hk66OXeWtKr3hGmYUct0hrAuX9gIxdZ62kdu7y7k0wk/Rq # 3yEVvBBsbqwbqXKauzYO1VzKEkwplLacst0+/c9z6phmHcLgLXKKWeFfl/lzQLSY # BBn94nq9uAOn6Cd7gn/JyY4ctqmHKT9uLu8ColmXEVaWY0FL5JjHrYoNjGm7LmNJ # s+6vrHMrOt+eprWSMs8h1zp0OO0VewnmdP+V3eVaxpjoB+GPtQdavp1yBvPMQHfp # +Ev/kU7kriACLGuGt/J/Nr2sl66fh8Qk/lpjjExRTbE1LBqom2MF+pGXCn2dqEe8 # CsQp5SCCv0BPqVjWXiENg4Jaz5T3vLs5 # SIG # End signature block |