Framework/Managers/ControlBaselineManager.ps1
Set-StrictMode -Version Latest class ControlBaselineManager { hidden [PSObject] $AzSDKResourceGroup = $null; hidden [PSObject] $AzSDKStorageAccount = $null; hidden [PSObject] $AzSDKStorageResourceBaselineContainer = $null; hidden [int] $HasWritePermissions = -1; hidden [string] $BaselineResourceBlobName = "BaselineResourceBlob.json" hidden [string] $BaselineContainerName = "azsdk-controls-baseline" hidden [BaselineResourceMap] $BaselineControlObj = $null [PSObject] $ControlSettings; hidden [ActiveStatus] $ActiveStatus = [ActiveStatus]::NotStarted; hidden static [ControlBaselineManager] $Instance = $null; static [ControlBaselineManager] GetInstance() { if ( $null -eq [ControlBaselineManager]::Instance) { [ControlBaselineManager]::Instance = [ControlBaselineManager]::new(); } return [ControlBaselineManager]::Instance } ControlBaselineManager() { $this.ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); #$this.GetAzSDKControlBaselineContainer() } hidden [bool] HasControlBaselineStatusWritePermissions() { $hasPermissions = $false; return $hasPermissions; } hidden [void] GetAzSDKControlBaselineContainer() { if($null -eq $this.AzSDKStorageAccount) { $this.GetAzSDKStorageAccount() } if($null -eq $this.AzSDKStorageAccount) { return; } try { #Able to read the container then read permissions are good $containerObject = Get-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction Stop $this.AzSDKStorageResourceBaselineContainer = $containerObject; } catch { try { New-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction SilentlyContinue $containerObject = Get-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction SilentlyContinue $this.AzSDKStorageResourceBaselineContainer = $containerObject; } catch { #Do nothing } } } hidden [void] GetAzSDKStorageAccount() { if($null -eq $this.AzSDKResourceGroup) { $this.GetAzSDKRG(); } if($null -ne $this.AzSDKResourceGroup) { $StorageAccount = Get-AzureRmStorageAccount -ResourceGroupName $this.AzSDKResourceGroup.ResourceGroupName | Where-Object {$_.StorageAccountName -like 'azsdk*'} -ErrorAction SilentlyContinue #if no storage account found then it assumes that there is no control state feature is not used and if there are more than one storage account found it assumes the same $this.AzSDKStorageAccount = $StorageAccount; } } hidden [PSObject] GetAzSDKRG() { $azSDKConfigData = [ConfigurationManager]::GetAzSdkConfigData() $resourceGroup = Get-AzureRmResourceGroup -Name $azSDKConfigData.AzSDKRGName -ErrorAction SilentlyContinue $this.AzSDKResourceGroup = $resourceGroup return $resourceGroup; } [void] UpdateResourceStatus([string] $resourceId, [ScanState] $state) { $resourceValues = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { #$idHash = [Helpers]::ComputeHash($resourceId) $resourceValue = $this.BaselineControlObj.ResourceMapTable | Where-Object { $_.Id -eq $resourceId}; if($null -ne $resourceValue) { $resourceValue.ModifiedDate = [DateTime]::UtcNow; $resourceValue.State = $state; #$this.BaselineControlObj.ResourceMapTable[$idHash] = $resourceValue; } else { $resourceValue = [BaselineResource]@{ Id = $resourceId; State = $state; CreatedDate = [DateTime]::UtcNow; ModifiedDate = [DateTime]::UtcNow; } $this.BaselineControlObj.ResourceMapTable +=$resourceValue; } $this.PersistStorageBlob(); } } [void] RemoveControlBaseline() { if($null -ne $this.BaselineControlObj) { Get-AzureStorageBlob -Container $this.BaselineContainerName -Context $this.AzSDKStorageAccount.Context | Remove-AzureStorageBlob $this.BaselineControlObj = $null } } [void] CreateResourceMasterList([PSObject] $resourceIds) { if(($resourceIds | Measure-Object).Count -gt 0) { $resourceIdMap = @(); $resourceIds | ForEach-Object { $resourceId = $_; #$hashId = [Helpers]::ComputeHash($resourceId); $resourceValue = [BaselineResource]@{ Id = $resourceId; State = [ScanState]::INIT CreatedDate = [DateTime]::UtcNow; ModifiedDate = [DateTime]::UtcNow; } #$resourceIdMap.Add($hashId,$resourceValue); $resourceIdMap +=$resourceValue } $masterControlBlob = [BaselineResourceMap]@{ Id = [DateTime]::UtcNow.ToString("yyyyMMdd_HHmmss"); CreatedDate = [DateTime]::UtcNow; ResourceMapTable = $resourceIdMap; } $this.BaselineControlObj = $masterControlBlob; $this.PersistStorageBlob(); $this.ActiveStatus = [ActiveStatus]::Yes; } } [void] PersistStorageBlob() { $this.GetBaselineControlObject(); if($null -ne $this.BaselineControlObj) { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $masterFilePath = "$AzSDKTemp\ControlsBaseline\$($this.BaselineResourceBlobName)" [Helpers]::ConvertToJsonCustom($this.BaselineControlObj) | Out-File $masterFilePath -Force Set-AzureStorageBlobContent -File $masterFilePath -Container $this.BaselineContainerName -BlobType Block -Context $this.AzSDKStorageAccount.Context -Force } } hidden [void] GetBaselineControlObject() { if($null -eq $this.BaselineControlObj) { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $masterFilePath = "$AzSDKTemp\ControlsBaseline\$($this.BaselineResourceBlobName)" $controlStateBlob = Get-AzureStorageBlob -Container $this.BaselineContainerName -Context $this.AzSDKStorageAccount.Context if($null -ne $controlStateBlob) { Get-AzureStorageBlobContent -CloudBlob $controlStateBlob.ICloudBlob -Context $this.AzSDKStorageAccount.Context -Destination $masterFilePath -Force $this.BaselineControlObj = Get-ChildItem -Path $masterFilePath -Force | Get-Content | ConvertFrom-Json } } } [ActiveStatus] IsMasterListActive() { if($null -eq $this.AzSDKStorageAccount -or $null -eq $this.AzSDKStorageResourceBaselineContainer ) { $this.GetAzSDKControlBaselineContainer(); } if($null -ne $this.ControlSettings.BaselineControls) { $this.GetBaselineControlObject(); $expiryInDays = [Int32]::Parse($this.ControlSettings.BaselineControls.ExpiryInDays); if($null -eq $this.BaselineControlObj) { return $this.ActiveStatus = [ActiveStatus]::No; } if([datetime]::Parse($this.BaselineControlObj.CreatedDate).AddDays($expiryInDays) -lt [DateTime]::UtcNow) { $this.RemoveControlBaseline(); return $this.ActiveStatus = [ActiveStatus]::No; } return $this.ActiveStatus = [ActiveStatus]::Yes } else { return $this.ActiveStatus = [ActiveStatus]::No; } } [PSObject] GetResourceStatus([string] $resourceId) { $resourceValues = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $idHash = [Helpers]::ComputeHash($resourceId) $resourceValue = $this.BaselineControlObj.ResourceMapTable[$idHash]; $resourceValues += $resourceValue; return $resourceValues; } return $null; } [PSObject] GetNonScannedResources() { $nonScannedResources = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $nonScannedResources +=[BaselineResource[]] $this.BaselineControlObj.ResourceMapTable | Where-Object {$_.State -eq [ScanState]::INIT} return $nonScannedResources; } return $null; } [PSObject] GetAllListedResources() { $nonScannedResources = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $nonScannedResources += $this.BaselineControlObj.ResourceMapTable return $nonScannedResources; } return $null; } [Bool] IsListAvailableAndActive() { if($null -ne $this.BaselineControlObj -and $this.ActiveStatus -eq [ActiveStatus]::Yes -and $null -ne $this.BaselineControlObj.ResourceMapTable) { return $true } else { return $false } } [PSObject] GetBaselineControlDetails() { return $this.ControlSettings.BaselineControls } } # SIG # Begin signature block # MIIj/wYJKoZIhvcNAQcCoIIj8DCCI+wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBuRoZv2xJTN6UW # m1nqr8o+0ykhcCzCzwSSgSh83T+vmqCCDZMwggYRMIID+aADAgECAhMzAAAAjoeR # pFcaX8o+AAAAAACOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMTYxMTE3MjIwOTIxWhcNMTgwMjE3MjIwOTIxWjCBgzEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q # UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEA0IfUQit+ndnGetSiw+MVktJTnZUXyVI2+lS/qxCv # 6cnnzCZTw8Jzv23WAOUA3OlqZzQw9hYXtAGllXyLuaQs5os7efYjDHmP81LfQAEc # wsYDnetZz3Pp2HE5m/DOJVkt0slbCu9+1jIOXXQSBOyeBFOmawJn+E1Zi3fgKyHg # 78CkRRLPA3sDxjnD1CLcVVx3Qv+csuVVZ2i6LXZqf2ZTR9VHCsw43o17lxl9gtAm # +KWO5aHwXmQQ5PnrJ8by4AjQDfJnwNjyL/uJ2hX5rg8+AJcH0Qs+cNR3q3J4QZgH # uBfMorFf7L3zUGej15Tw0otVj1OmlZPmsmbPyTdo5GPHzwIDAQABo4IBgDCCAXww # HwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFKvI1u2y # FdKqjvHM7Ww490VK0Iq7MFIGA1UdEQRLMEmkRzBFMQ0wCwYDVQQLEwRNT1BSMTQw # MgYDVQQFEysyMzAwMTIrYjA1MGM2ZTctNzY0MS00NDFmLWJjNGEtNDM0ODFlNDE1 # ZDA4MB8GA1UdIwQYMBaAFEhuZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0Nv # ZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsG # AQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # Y0NvZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEARIkCrGlT88S2u9SMYFPnymyoSWlmvqWaQZk62J3SVwJR # avq/m5bbpiZ9CVbo3O0ldXqlR1KoHksWU/PuD5rDBJUpwYKEpFYx/KCKkZW1v1rO # qQEfZEah5srx13R7v5IIUV58MwJeUTub5dguXwJMCZwaQ9px7eTZ56LadCwXreUM # tRj1VAnUvhxzzSB7pPrI29jbOq76kMWjvZVlrkYtVylY1pLwbNpj8Y8zon44dl7d # 8zXtrJo7YoHQThl8SHywC484zC281TllqZXBA+KSybmr0lcKqtxSCy5WJ6PimJdX # jrypWW4kko6C4glzgtk1g8yff9EEjoi44pqDWLDUmuYx+pRHjn2m4k5589jTajMW # UHDxQruYCen/zJVVWwi/klKoCMTx6PH/QNf5mjad/bqQhdJVPlCtRh/vJQy4njpI # BGPveJiiXQMNAtjcIKvmVrXe7xZmw9dVgh5PgnjJnlQaEGC3F6tAE5GusBnBmjOd # 7jJyzWXMT0aYLQ9RYB58+/7b6Ad5B/ehMzj+CZrbj3u2Or2FhrjMvH0BMLd7Hald # G73MTRf3bkcz1UDfasouUbi1uc/DBNM75ePpEIzrp7repC4zaikvFErqHsEiODUF # he/CBAANa8HYlhRIFa9+UrC4YMRStUqCt4UqAEkqJoMnWkHevdVmSbwLnHhwCbww # ggd6MIIFYqADAgECAgphDpDSAAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5 # MDlaFw0yNjA3MDgyMTA5MDlaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIw # MTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQ # TTS68rZYIZ9CGypr6VpQqrgGOBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULT # iQ15ZId+lGAkbK+eSZzpaF7S35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYS # L+erCFDPs0S3XdjELgN1q2jzy23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494H # DdVceaVJKecNvqATd76UPe/74ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZ # PrGMXeiJT4Qa8qEvWeSQOy2uM1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5 # bmR/U7qcD60ZI4TL9LoDho33X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGS # rhwjp6lm7GEfauEoSZ1fiOIlXdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADh # vKwCgl/bwBWzvRvUVUvnOaEP6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON # 7E1JMKerjt/sW5+v/N2wZuLBl4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xc # v3coKPHtbcMojyyPQDdPweGFRInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqw # iBfenk70lrC8RqBsmNLg1oiMCwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMC # AQAwHQYDVR0OBBYEFEhuZOVQBdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQM # HgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud # IwQYMBaAFHItOgIxkEO5FAVO4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0 # dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUF # BzAChkJodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGC # Ny4DMIGDMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # b3BzL2RvY3MvcHJpbWFyeWNwcy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcA # YQBsAF8AcABvAGwAaQBjAHkAXwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZI # hvcNAQELBQADggIBAGfyhqWY4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4s # PvjDctFtg/6+P+gKyju/R6mj82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKL # UtCw/WvjPgcuKZvmPRul1LUdd5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7 # pKkFDJvtaPpoLpWgKj8qa1hJYx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft # 0N3zDq+ZKJeYTQ49C/IIidYfwzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4 # MnEnGn+x9Cf43iw6IGmYslmJaG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxv # FX1Fp3blQCplo8NdUmKGwx1jNpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG # 0QaxdR8UvmFhtfDcxhsEvt9Bxw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf # 0AApxbGbpT9Fdx41xtKiop96eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkY # S//WsyNodeav+vyL6wuA6mk7r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrv # QQqxP/uozKRdwaGIm1dxVk5IRcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIV # wjCCFb4CAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAA # AI6HkaRXGl/KPgAAAAAAjjANBglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMx # DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkq # hkiG9w0BCQQxIgQgfR7as2M2tIp/E+7q9iMvx2tMhhtvbw4gxKGst0vlr20wRAYK # KwYBBAGCNwIBDDE2MDSgEoAQAEEAegBTAEQASwAyADUAMqEegBxodHRwczovL2Fr # YS5tcy9henNka29zc2RvY3MgMA0GCSqGSIb3DQEBAQUABIIBAAZh38lGwqAlBmJW # 5t7tEwjF/sDycs9xRlG0RWSfCoEv8zIPHT7cZ7P6m90FeTPJkirmMptVuPaU81Ij # 99RqnFrVCfRIEAJo975V1MWKGwtWEpNTbhWSAJ5AGkkPeGCCUuHFSTH2SPdHJwc8 # 3UJ1ucqzJsX2v3m1yshJq2Gigy5uZ5vWKz3Pxm2Knx4LJaX3Ra3ERkt10AVADXGc # R8mAen0MaE0ci/ENXv5Ev9m4S8pCpP3OPx7P8hWw01X9/5jkG+5s7Jkr0XkccN1e # qlr8CiyTwj6HrJIa52yrjushZc/S2krnlOsk1Z4VgeEH4UdvTstIynewNGeH0DL8 # B4RXn4ehghNKMIITRgYKKwYBBAGCNwMDATGCEzYwghMyBgkqhkiG9w0BBwKgghMj # MIITHwIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBPQYLKoZIhvcNAQkQAQSgggEsBIIB # KDCCASQCAQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQglVP6IAne6/Ht # HiI7n+B3I/oygTU8dSACudV56l0Rs4ICBlmV0kismhgTMjAxNzA5MDUwOTM3MjYu # Mjg5WjAHAgEBgAIB9KCBuaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0Ug # RVNOOkI4RUMtMzBBNC03MTQ0MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt # cCBTZXJ2aWNloIIOzTCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcN # AQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw # BgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEw # MB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp # HQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVT # JwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q # 6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h # /EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+ # 79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4 # zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAd # BgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBT # AHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgw # FoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov # L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0 # XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAx # MC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0G # CCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BT # L2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBs # AGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4IC # AQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efw # eL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt0 # 70IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQi # PM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93F # SguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4a # rgRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qA # xdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995y # fmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaY # LeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL # 32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4 # L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvTX4/edIhJEjCCBNowggPCoAMCAQIC # EzMAAACfZ/K1qCMGW3sAAAAAAJ8wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTAwHhcNMTYwOTA3MTc1NjQ3WhcNMTgwOTA3MTc1NjQ3 # WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UE # CxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkI4RUMtMzBBNC03MTQ0 # MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuQjxI5zdxAIvAoWhoyeXZPkDnBJUP1OC # Wrg+631uGMVywSfVcCkM8JZL1o+ExxY5Yp77sQ0jhKLjMPfSdVAL09nQ0O76kr1d # Xzc5+MZyEWQrM4FF106GmxCTEWAwXdF8tM1cASp9+c1pF5fC1VSSIYQm9boqYAGL # HM/Rp5RWYnowecmeaj5Mpl2hWXtyDpNjosKjN78XquE5eaL8/df8reMe2YBrEv06 # 7neOMOA7lGPG3pkRqZ0SwYXZJZnrAfoOaD0bqJk/GDD6aM4PBF4vqPCHsfZeGy/O # gUytIREzMgh/Z4kYAz0LQZHQFkfJG2LXtCovlNoK5Y+MzFMpdfgOWQIDAQABo4IB # GzCCARcwHQYDVR0OBBYEFP2LGyLDfSNHdqYe3+Bm1FLptvmgMB8GA1UdIwQYMBaA # FNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j # cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y # MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAt # MDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJ # KoZIhvcNAQELBQADggEBAGUQwWxrzxUerw9INuvfLQu8AADmkWYaUJZluTEPZYyp # 8XTLx+eW+BvzvjPyzPxBnMHIKZjWMfIdNz3xl6TPsvZjlIA1QhryPJTfpzrgKTl9 # jo972FQDVEb/XM/56rTzRyFQ8IXbN7OF/C7P05vShs7rgHBbQZmBhjPWGOyr4MGR # IIFFXn2vIWnOApHCFYXyq5e0cOmKaInH52zZVlLARWT9BFjuku5S9503w/kM24tp # pHDeglyzZbGHaNZLlPxjcl69SjcrdVO0c+LYgFYhKQQbtM6c0RRxRcMwZI55nbuS # 48XMqQNVu3O/ARV6mQauxnVb7XG4Ng9DVvcEwbwLv0ehggN2MIICXgIBATCB46GB # uaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsG # A1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkI4RUMtMzBBNC03 # MTQ0MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiUKAQEw # CQYFKw4DAhoFAAMVAGzTJwjy+dmoy/kZ3pJLSq3bGaPBoIHCMIG/pIG8MIG5MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BS # MScwJQYDVQQLEx5uQ2lwaGVyIE5UUyBFU046NTdGNi1DMUUwLTU1NEMxKzApBgNV # BAMTIk1pY3Jvc29mdCBUaW1lIFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcN # AQEFBQACBQDdWK1PMCIYDzIwMTcwOTA1MDQ1NzUxWhgPMjAxNzA5MDYwNDU3NTFa # MHQwOgYKKwYBBAGEWQoEATEsMCowCgIFAN1YrU8CAQAwBwIBAAICBm0wBwIBAAIC # GH0wCgIFAN1Z/s8CAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAaAK # MAgCAQACAxbjYKEKMAgCAQACAwehIDANBgkqhkiG9w0BAQUFAAOCAQEAJX/cCcBK # RMXCtHoYvQd/JchaOFxraPIImdjPIQeUvTHptRsk/iNnIE1IrvBnK1n3kQr5Gpqy # h7i2M5y4fldOIr6yA/gaBO2v5X/Xe54qXMugaIReq6orhdJqM4ewjaJrFbcbr0zj # dtpyUyLadO5lAeHRimMy+IvIzE8rpTOWcF92kvoi7cJuTp609eWgusewNALxxinf # bgGV45soyOGKYknq71jSNAA9hfWx480TI/d5tmwXf4nDIEJSji7SjdhH5bvNnu0h # pvWZriA+DibRnmkwXsWefvOf/n+tjdmoBCkrs0MI+aXyjPUR337CNfSBqPZl8dtN # c2mrXS1UdxWGTjGCAvUwggLxAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD # QSAyMDEwAhMzAAAAn2fytagjBlt7AAAAAACfMA0GCWCGSAFlAwQCAQUAoIIBMjAa # BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIHCOa325 # EmXMZRBVvPPkLvwzsLOmk1OaWdzFCdyTGozfMIHiBgsqhkiG9w0BCRACDDGB0jCB # zzCBzDCBsQQUbNMnCPL52ajL+RnekktKrdsZo8EwgZgwgYCkfjB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg # VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAJ9n8rWoIwZbewAAAAAAnzAWBBQzMc8v # zGX0GV6aNrmwEMOU/gnrejANBgkqhkiG9w0BAQsFAASCAQAQRQU42C113Bv65aZc # MFodBaXcTF8JVyGIrL+wdfEX+PMGwUV40HYTTktgw92149yU9tK8ejlBytS5NeB1 # FWCowy7U4SE/niSiCjf2qRFsd39NArGflf3geaE8pUYL39md6JTPX3lDZDvYKms6 # BqvqI4nTmOeVJukx8r3+GkkJUeUFgeVFzt6KgR06BZSNrBczxtxFEtUdwmB8awyc # vOIK6luVmfQEfhj3XH4eVncPMHdXubZzUVNpfuV/Z40njZ0D7+rRb45uP7eul77e # Hb5uY6bLuqupQtUkfnV3mlk8WqxH8AWasE1JOKq25F1708ZY5xpJS85f7Y2n/3Rd # 8U+L # SIG # End signature block |