Framework/Core/SVT/Services/Storage.ps1
using namespace Microsoft.Azure.Management.Storage.Models using namespace Microsoft.WindowsAzure.Storage.Shared.Protocol Set-StrictMode -Version Latest class Storage: SVTBase { hidden [PSObject] $ResourceObject; Storage([string] $subscriptionId, [string] $resourceGroupName, [string] $resourceName): Base($subscriptionId, $resourceGroupName, $resourceName) { $this.GetResourceObject(); } Storage([string] $subscriptionId, [SVTResource] $svtResource): Base($subscriptionId, $svtResource) { $this.GetResourceObject(); } hidden [PSObject] GetResourceObject() { if (-not $this.ResourceObject) { $this.ResourceObject = Get-AzureRmStorageAccount -Name $this.ResourceContext.ResourceName -ResourceGroupName $this.ResourceContext.ResourceGroupName -ErrorAction Stop if(-not $this.ResourceObject) { throw ("Resource '{0}' not found under Resource Group '{1}'" -f ($this.ResourceContext.ResourceName), ($this.ResourceContext.ResourceGroupName)) } } return $this.ResourceObject; } hidden [ControlResult] CheckStorageContainerPublicAccessTurnOff([ControlResult] $controlResult) { $allContainers = @(); try { $allContainers += Get-AzureStorageContainer -Context $this.ResourceObject.Context -ErrorAction Stop } catch { if(($_.Exception).Response.StatusCode -eq [System.Net.HttpStatusCode]::Forbidden) { $controlResult.AddMessage([VerificationResult]::Manual, ($_.Exception).Message); return $controlResult } else { throw $_ } } #Containers others than private $publicContainers = $allContainers | Where-Object { $_.PublicAccess -ne [Microsoft.WindowsAzure.Storage.Blob.BlobContainerPublicAccessType]::Off } if(($publicContainers | Measure-Object ).Count -eq 0) { $controlResult.AddMessage([VerificationResult]::Passed, "There are no containers having pubic access with anonymous authentication"); } else { $controlResult.AddMessage([VerificationResult]::Failed , [MessageData]::new("Remove public access from following containers. Total - $(($publicContainers | Measure-Object ).Count)", ($publicContainers | Select-Object -Property Name, PublicAccess))); } return $controlResult; } hidden [ControlResult] CheckStorageEnableDiagnosticsLog([ControlResult] $controlResult) { #Checking for storage kind $serviceMapping = $this.ControlSettings.StorageKindMapping | Where-Object { $_.Kind -eq $this.ResourceObject.Kind } | Select-Object -First 1; if(-not $serviceMapping) { #Currently only 'General purpose' or 'Blob storage' account kind is present #If new storage kind is introduced code needs to be updated as per new storage kind $controlResult.AddMessage("Storage Account kind is not supported"); return $controlResult; } #Checking for applicable sku $daignosticsSkuMapping = $this.ControlSettings.StorageDiagnosticsSkuMapping | Where-Object { $_ -eq $this.ResourceObject.Sku.Name } | Select-Object -First 1; if(-not $daignosticsSkuMapping) { #Diagnostics settings are not available for premium storage and zone redundant storage. $controlResult.AddMessage([VerificationResult]::Failed, [MessageData]::new("Diagnostics settings are not supported for Sku Tier - [$($this.ResourceObject.Sku.Name)]")); return $controlResult; } try{ $result = $true #Check Metrics diagnostics log property $serviceMapping.DiagnosticsLogServices | ForEach-Object { $result = $this.GetServiceLoggingProperty($_, $controlResult) -and $result ; } #Check Metrics logging property $serviceMapping.Services | ForEach-Object { $result = $this.GetServiceMetricsProperty($_, $controlResult) -and $result ; } if($result){ $controlResult.VerificationResult = [VerificationResult]::Passed } else{ $controlResult.VerificationResult = [VerificationResult]::Failed } } catch{ #With Reader Role exception will be is thrown. if(($_.Exception).Response.StatusCode -eq [System.Net.HttpStatusCode]::Forbidden) { $controlResult.AddMessage(($_.Exception).Message); return $controlResult } else { throw $_ } } return $controlResult; } hidden [ControlResult] CheckStorageGeoRedundantReplication([ControlResult] $controlResult) { if($null -ne $this.ResourceObject.Sku.Tier -and $null -ne $this.ResourceObject.Sku.Name){ $controlResult.AddMessage("Current storage sku tier is - [$($this.ResourceObject.Sku.Tier)] and sku name is - [$($this.ResourceObject.Sku.Name)]"); } else{ $controlResult.AddMessage("Unable to get sku details for - [$($this.ResourceContext.ResourceName)]"); return $controlResult } if($this.ResourceObject.Sku.Tier -eq [SkuTier]::Standard){ $isGeoRedundantSku = $this.ControlSettings.StorageGeoRedundantSku | Where-Object { $_ -eq $this.ResourceObject.Sku.Name } | Select-Object -First 1; if($isGeoRedundantSku){ $controlResult.VerificationResult = [VerificationResult]::Passed } else { $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else{ $controlResult.AddMessage([VerificationResult]::Failed, [MessageData]::new("A premium storage account supports only locally redundant storage as the replication option")); } return $controlResult; } hidden [ControlResult] CheckStorageBlobEncryptionEnabled([ControlResult] $controlResult) { if($null -ne $this.ResourceObject.Encryption) { if([Helpers]::CheckMember($this.ResourceObject.Encryption, "Services")){ if([Helpers]::CheckMember($this.ResourceObject.Encryption.Services, "Blob")){ if($null -eq $this.ResourceObject.Encryption.Services.Blob.Enabled ){ $controlResult.EnableFixControl = $true; $controlResult.AddMessage([MessageData]::new("Unable to get Blob encryption settings")) return $controlResult; } if($this.ResourceObject.Encryption.Services.Blob.Enabled -eq $true){ $controlResult.VerificationResult = [VerificationResult]::Passed } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else { $controlResult.EnableFixControl = $true; $controlResult.AddMessage([MessageData]::new("Storage blob encryption is not enabled")) $controlResult.VerificationResult = [VerificationResult]::Failed } return $controlResult; } hidden [ControlResult] CheckStorageFileEncryptionEnabled([ControlResult] $controlResult) { if($null -ne $this.ResourceObject.Encryption) { if([Helpers]::CheckMember($this.ResourceObject.Encryption, "Services")){ if([Helpers]::CheckMember($this.ResourceObject.Encryption.Services, "File")){ if($null -eq $this.ResourceObject.Encryption.Services.File ) { $controlResult.EnableFixControl = $true; $controlResult.AddMessage([VerificationResult]::Failed, "Unable to get file encryption settings") return $controlResult; } else { if($this.ResourceObject.Encryption.Services.File.Enabled -eq $true) { $controlResult.VerificationResult = [VerificationResult]::Passed } else { $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed } } else { $controlResult.EnableFixControl = $true; $controlResult.AddMessage([MessageData]::new("Storage file encryption is not enabled")) $controlResult.VerificationResult = [VerificationResult]::Failed } return $controlResult; } hidden [ControlResult] CheckStorageMetricAlert([ControlResult] $controlResult) { $serviceMapping = $this.ControlSettings.StorageKindMapping | Where-Object { $_.Kind -eq $this.ResourceObject.Kind } | Select-Object -First 1; if(-not $serviceMapping) { #Currently only 'General purpose' or 'Blob storage' account kind is present #If new storage kind is introduced code needs to be updated as per new storage kind $controlResult.AddMessage("Storage Account kind is not supported"); return $controlResult; } #Checking for applicable sku $daignosticsSkuMapping = $this.ControlSettings.StorageAlertSkuMapping | Where-Object { $_ -eq $this.ResourceObject.Sku.Name } | Select-Object -First 1; if(-not $daignosticsSkuMapping) { #Metrics or logging capability not enabled for premium storage and zone redundant storage account. $controlResult.AddMessage([VerificationResult]::Failed, [MessageData]::new("Diagnostics settings are not supported for Sku Tier - [$($this.ResourceObject.Sku.Name)]")); return $controlResult; } $result = $true; $serviceMapping.Services | ForEach-Object { $result = $this.CheckMetricAlertConfiguration($this.ControlSettings.MetricAlert.Storage, $controlResult, ("/services/" + $_)) -and $result ; } if($result) { $controlResult.VerificationResult = [VerificationResult]::Passed } else { $controlResult.VerificationResult = [VerificationResult]::Failed } return $controlResult; } hidden [boolean] GetServiceLoggingProperty([string] $serviceType,[ControlResult] $controlResult) { $loggingProperty = Get-AzureStorageServiceLoggingProperty -ServiceType $ServiceType -Context $this.ResourceObject.Context -ErrorAction Stop if($null -ne $loggingProperty){ #Check For Retention day's if($loggingProperty.LoggingOperations -eq [LoggingOperations]::All -and (($loggingProperty.RetentionDays -eq $this.ControlSettings.Diagnostics_RetentionPeriod_Forever) -or ($loggingProperty.RetentionDays -eq $this.ControlSettings.Diagnostics_RetentionPeriod_Min))){ return $True } else{ $controlResult.AddMessage("Diagnostics settings($($serviceType) logs) is either disabled OR not retaining logs for at least $($this.ControlSettings.Diagnostics_RetentionPeriod_Min) days for service type - [$($serviceType)]") return $false } } else { $controlResult.AddMessage("Diagnostics settings($($serviceType) logs) is disabled for service type - [$($serviceType)]") return $false } } hidden [boolean] GetServiceMetricsProperty([string] $serviceType,[ControlResult] $controlResult) { $serviceMetricsProperty= Get-AzureStorageServiceMetricsProperty -MetricsType Hour -ServiceType $ServiceType -Context $this.ResourceObject.Context -ErrorAction Stop if($null -ne $serviceMetricsProperty){ #Check For Retention day's if($serviceMetricsProperty.MetricsLevel -eq [MetricsLevel]::ServiceAndApi -and (($serviceMetricsProperty.RetentionDays -eq $this.ControlSettings.Diagnostics_RetentionPeriod_Min) -or ($serviceMetricsProperty.RetentionDays -eq $this.ControlSettings.Diagnostics_RetentionPeriod_Forever))) { return $True } else { $controlResult.AddMessage("Diagnostics settings($($serviceType) aggregate metrics,$($serviceType) per API metrics) is either disabled OR not retaining logs for at least $($this.ControlSettings.Diagnostics_RetentionPeriod_Min) days for service type - [$($serviceType)]") return $false } } else { $controlResult.AddMessage("Diagnostics settings($($serviceType) aggregate metrics,$($serviceType) per API metrics) is disabled for service type - [$($serviceType)]") return $false } } hidden [ControlResult] CheckStorageEncryptionInTransit([ControlResult] $controlResult) { if($null -ne $this.ResourceObject.EnableHttpsTrafficOnly){ if($this.ResourceObject.EnableHttpsTrafficOnly -eq $true){ $controlResult.VerificationResult = [VerificationResult]::Passed $controlResult.AddMessage([MessageData]::new("Storage secure transfer is enabled")) } else{ $controlResult.EnableFixControl = $true; $controlResult.VerificationResult = [VerificationResult]::Failed $controlResult.AddMessage([MessageData]::new("Storage secure transfer is not enabled")) } } else{ $controlResult.EnableFixControl = $true; $controlResult.AddMessage([MessageData]::new("Storage secure transfer is not enabled")) $controlResult.VerificationResult = [VerificationResult]::Failed } return $controlResult; } } # SIG # Begin signature block # MIIkAgYJKoZIhvcNAQcCoIIj8zCCI+8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBrvKUzARI58BCO # lyEigydlI4+2WIbLCqBzzBNChOVhmqCCDZMwggYRMIID+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 # xTCCFcECAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAA # AI6HkaRXGl/KPgAAAAAAjjANBglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMx # DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkq # hkiG9w0BCQQxIgQgyf9htyJyjpClduupFXWG6wNvP21VSPHh+Gko8x3TkvkwRAYK # KwYBBAGCNwIBDDE2MDSgEoAQAEEAegBTAEQASwAyADUAMqEegBxodHRwczovL2Fr # YS5tcy9henNka29zc2RvY3MgMA0GCSqGSIb3DQEBAQUABIIBAFeyH867OjlrN9DD # KgwVOOCTPKRQlUZDzrwwlaAAzys1yPctgnmdz/6rVtzn71y9mSrs/b0VBbN6nspY # +aqXTHu+/3OayNeb50aK7YGtncUIbL2NEQYWmKHrAY5TzFA7Hnp6GzJUHz6AkhEk # +L+VbV8bxrCcEBZV+tSJz8oTk1SwCZD8Xfoe8YiYU59rsc+mO2no70e1wpD8AC8N # xARjPc70WYh+K9FUKStpcWsNWs8crtMizTNPXdhfPXSB0dntRV6WVJT3kdQcsYcR # 3sbh+GxI8qNO1AL+kJ/HIxkoFrU/gChdjdszwttufqDDWvQnMNdMBny0OoER2PEN # CjPvxv+hghNNMIITSQYKKwYBBAGCNwMDATGCEzkwghM1BgkqhkiG9w0BBwKgghMm # MIITIgIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBPQYLKoZIhvcNAQkQAQSgggEsBIIB # KDCCASQCAQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQgtG2vDXf3iTUG # 4FSEG3TBRZ31Q9ZL77rzswGm5lVFWZ0CBlmSJmy8ThgTMjAxNzA5MDUwOTM3MTUu # NzI1WjAHAgEBgAIB9KCBuaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0Ug # RVNOOkMwRjQtMzA4Ni1ERUY4MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt # cCBTZXJ2aWNloIIO0DCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcN # 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 # EzMAAACj7x8iIIFj3KUAAAAAAKMwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTAwHhcNMTYwOTA3MTc1NjQ5WhcNMTgwOTA3MTc1NjQ5 # WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UE # CxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkMwRjQtMzA4Ni1ERUY4 # MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdEel8cTafg4OxUX5kgO+V+CrFSdMBqt # EF3Q8gX3P2iGN1rQAFPmnG0caPIpx9b/MZhSTRG69cFkhjo5CSdWSV6foSEZKRvM # Whbj830BVRcs6eGslvvHma8ocAB1IvoucpRUX7rRxawy1OXWHnnwgaMKvmO+eGln # 4o+F0cm+yH+Qi+S4fpiub74qZAgaSLc5Ichq9CRLYBDUcoByCDjpbvk7U+1Z2yTU # TWHIW9NpYwAyvcyxUT3rQLh/uL67ch3BOGzeCY5uLZk6bEUI3rNPW21tgJHZI5tI # mUwe5RF/sxeedpG94iYWHxEAHDrfmegs/+x1LFgpcKcXLSjuj7SjXwIDAQABo4IB # GzCCARcwHQYDVR0OBBYEFPqFumZm6EaZ2nCfuiElQNvg6LFwMB8GA1UdIwQYMBaA # FNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j # cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y # MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAt # MDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJ # KoZIhvcNAQELBQADggEBAB3RRbpbtL+K5oaNRc41iCYSRrAzg2phMcgWc/jmJHpq # wcAVNzyNxykNSMt0l6Wyh+EGeNVDjFM68OJRDni20/wcjSXlUxoV2T56vMe7wU5m # WFEYD2UlYSGhvuaRw2CO+Qm0PojCpnKBOxzyEBzVBa6IXTRVUqhDhozwDVS+S+RL # 7heVtpu8AmsWzbItbPWr3zXhBoO0WUHnHgHzaE332N4kLEZLQsCNF3NEUCuN3nbN # f3Rd3+ZkzDK4nsDPZVIRCAZ6l7aDZaNi2MODujmOR7hTqsNmGhy9SU703NQHrNK4 # 0WT54HfJ7HaAxKsXK+sjg7WWifHYS5aS3W+pwjvW85yhggN5MIICYQIBATCB46GB # uaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsG # A1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkMwRjQtMzA4Ni1E # RUY4MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiUKAQEw # CQYFKw4DAhoFAAMVADXko/tOP/8mDXH1bV4Se5GWOKaNoIHCMIG/pIG8MIG5MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BS # MScwJQYDVQQLEx5uQ2lwaGVyIE5UUyBFU046NTdGNi1DMUUwLTU1NEMxKzApBgNV # BAMTIk1pY3Jvc29mdCBUaW1lIFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcN # AQEFBQACBQDdWK09MCIYDzIwMTcwOTA1MDQ1NzMzWhgPMjAxNzA5MDYwNDU3MzNa # MHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAN1YrT0CAQAwCgIBAAICCK8CAf8wBwIB # AAICGAkwCgIFAN1Z/r0CAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoD # AaAKMAgCAQACAxbjYKEKMAgCAQACAwehIDANBgkqhkiG9w0BAQUFAAOCAQEAMYfi # 5I9zkyR80j3BPxZ8ymXjfpDzMwuSzutzFXOoENXkLYOBMI+wDSKQfCmrkES79KHm # Ihi5slKqvI/Rnr5YnQdRreDGw1uMERxhdv2x/zYplwbpYpmerI3mBGdcdNFrkYut # Em6DLmp29H1Xps2/aT4Phg/Ksqar5XVrMpiu2jJQiVWRDJroS6l7KkGHK6hugOZ3 # nLymAnfET3VKMifzcmnTLQxtm23rT/qkOaHvMR5YD0ObLB3MzWAdoUlZqhfUwvq0 # 74Sehyidxw5qFg4WM5Y7vozRy6E08winEFsMZRfXfmaqM4lpLOgCFyswgjyFN3Ip # DGGsbKuUyMlFsj1WQzGCAvUwggLxAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwAhMzAAAAo+8fIiCBY9ylAAAAAACjMA0GCWCGSAFlAwQCAQUAoIIB # MjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIBvA # ilHnx2x2BEvIzSI0bKFpDcKhgI2f68WOf9XJ84aeMIHiBgsqhkiG9w0BCRACDDGB # 0jCBzzCBzDCBsQQUNeSj+04//yYNcfVtXhJ7kZY4po0wgZgwgYCkfjB8MQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3Nv # ZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAKPvHyIggWPcpQAAAAAAozAWBBQH # C6BGmJxwjkd2fNRs75/46vRKnjANBgkqhkiG9w0BAQsFAASCAQB4BAb+/9e80+LS # ydMBHqxU5X36oj/vaOzqFmnMvx4bJWrOPJaaZQm2xsA/thjKnFG+fFyQ3l7oH6Rx # 7c/YLkBCBEUnyvgk36+EppR2NSRy4I48lEBroWWxe965aS98Jk0eBTBZMg47drWO # BgYFpKX+DRrGMPVGdtKorzG9O4DEjM4kYJfXek+CQPMpyg/nOt4PlGIUF6Cma6q/ # LxUvxe9Qn2/ClCfja0C92m9mQamA6wB7Am21eb0yVez+AY8jmWLMBqLRteHZXGwG # GE/OTQzfT0kCzV+zZ56KjT66lis4HfynWG1XIWLCDkg5OKEjHJqjKi5EDhEm3F9J # pAKafz6p # SIG # End signature block |