Framework/Helpers/RemoteReportHelper.ps1
Set-StrictMode -Version Latest class RemoteReportHelper { hidden static [string[]] $IgnoreScanParamList = "DoNotOpenOutputFolder"; hidden static [string[]] $AllowedServiceScanParamList = "organizationName", "ResourceGroupNames"; hidden static [string[]] $AllowedOrganizationScanParamList = "organizationName"; hidden static [int] $MaxServiceParamCount = [RemoteReportHelper]::IgnoreScanParamList.Count + [RemoteReportHelper]::AllowedServiceScanParamList.Count; hidden static [int] $MaxOrganizationParamCount = [RemoteReportHelper]::IgnoreScanParamList.Count + [RemoteReportHelper]::AllowedOrganizationScanParamList.Count; hidden static [System.Security.Cryptography.SHA256Managed] $sha256AlgForMasking = [System.Security.Cryptography.SHA256Managed]::new(); hidden static [AIOrgTelemetryStatus] $AIOrgTelemetryState = [AIOrgTelemetryStatus]::Undefined; hidden static [string] $TelemetryKey = ""; static [FeatureGroup] GetFeatureGroup([SVTEventContext[]] $SVTEventContexts) { if(($SVTEventContexts | Measure-Object).Count -eq 0 -or $null -eq $SVTEventContexts[0].FeatureName) { return [FeatureGroup]::Unknown } $feature = $SVTEventContexts[0].FeatureName.ToLower() if($feature.Contains("organization")){ return [FeatureGroup]::Organization } else{ return [FeatureGroup]::Service } } static [ServiceScanKind] GetServiceScanKind([string] $command, [hashtable] $parameters) { $parameterNames = [array] $parameters.Keys if($parameterNames.Count -gt [RemoteReportHelper]::MaxServiceParamCount) { return [ServiceScanKind]::Partial; } $validParamCounter = 0; foreach($parameterName in $parameterNames) { if ([RemoteReportHelper]::AllowedServiceScanParamList.Contains($parameterName)) { $validParamCounter += 1 } elseif ([RemoteReportHelper]::IgnoreScanParamList.Contains($parameterName)) { # Ignoring } else { return [ServiceScanKind]::Partial; } } if ($validParamCounter -eq 1) { return [ServiceScanKind]::Organization; } elseif ($validParamCounter -eq 2) { return [ServiceScanKind]::ResourceGroup; } else { return [ServiceScanKind]::Partial; } } static [OrganizationScanKind] GetOrganizationScanKind([string] $command, [hashtable] $parameters) { $parameterNames = [array] $parameters.Keys if($parameterNames.Count -gt [RemoteReportHelper]::MaxOrganizationParamCount) { return [OrganizationScanKind]::Partial; } $validParamCounter = 0; foreach($parameterName in $parameterNames) { if ([RemoteReportHelper]::AllowedOrganizationScanParamList.Contains($parameterName)) { $validParamCounter += 1 } elseif ([RemoteReportHelper]::IgnoreScanParamList.Contains($parameterName)) { # Ignoring } else { return [OrganizationScanKind]::Partial; } } if ($validParamCounter -eq 1) { return [OrganizationScanKind]::Complete; } else { return [OrganizationScanKind]::Partial; } } static [OrganizationControlResult] BuildOrganizationControlResult([ControlResult] $controlResult, [ControlItem] $control) { $result = [OrganizationControlResult]::new() $result.ControlId = $control.ControlId $result.ControlIntId = $control.Id $result.ControlSeverity = $control.ControlSeverity $result.ActualVerificationResult = $controlResult.ActualVerificationResult $result.AttestationStatus = $controlResult.AttestationStatus $result.VerificationResult = $controlResult.VerificationResult $result.HasRequiredAccess = $controlResult.CurrentSessionContext.Permissions.HasRequiredAccess $result.IsBaselineControl = $control.IsBaselineControl #add PreviewBaselineFlag $result.IsPreviewBaselineControl = $control.IsPreviewBaselineControl $result.MaximumAllowedGraceDays = $controlResult.MaximumAllowedGraceDays if($control.Tags.Contains("OwnerAccess") -or $control.Tags.Contains("GraphRead")) { $result.HasOwnerAccessTag = $true } $result.UserComments = $controlResult.UserComments if($null -ne $controlResult.StateManagement -and $null -ne $controlResult.StateManagement.AttestedStateData) { $result.AttestedBy = $controlResult.StateManagement.AttestedStateData.AttestedBy $result.Justification = $controlResult.StateManagement.AttestedStateData.Justification $result.AttestedState = [JsonHelper]::ConvertToJsonCustomCompressed($controlResult.StateManagement.AttestedStateData.DataObject) $result.AttestedDate = $controlResult.StateManagement.AttestedStateData.AttestedDate $result.AttestationExpiryDate = $controlResult.StateManagement.AttestedStateData.ExpiryDate } if($null -ne $controlResult.StateManagement -and $null -ne $controlResult.StateManagement.CurrentStateData) { $result.CurrentState = [JsonHelper]::ConvertToJsonCustomCompressed($controlResult.StateManagement.CurrentStateData.DataObject) } return $result; } static [ServiceControlResult] BuildServiceControlResult([ControlResult] $controlResult, [bool] $isNestedResource, [ControlItem] $control) { $result = [ServiceControlResult]::new() $result.IsNestedResource = $isNestedResource if ($isNestedResource) { $result.NestedResourceName = $controlResult.ChildResourceName } else { $result.NestedResourceName = $null } $result.ControlId = $control.ControlID $result.ControlIntId = $control.Id $result.ControlSeverity = $control.ControlSeverity $result.ActualVerificationResult = $controlResult.ActualVerificationResult $result.AttestationStatus = $controlResult.AttestationStatus $result.VerificationResult = $controlResult.VerificationResult $result.HasRequiredAccess = $controlResult.CurrentSessionContext.Permissions.HasRequiredAccess $result.IsBaselineControl = $control.IsBaselineControl #add PreviewBaselineFlag $result.IsPreviewBaselineControl = $control.IsPreviewBaselineControl $result.UserComments = $controlResult.UserComments $result.MaximumAllowedGraceDays = $controlResult.MaximumAllowedGraceDays if($control.Tags.Contains("OwnerAccess") -or $control.Tags.Contains("GraphRead")) { $result.HasOwnerAccessTag = $true } if($null -ne $controlResult.StateManagement -and $null -ne $controlResult.StateManagement.AttestedStateData) { $result.AttestedBy = $controlResult.StateManagement.AttestedStateData.AttestedBy $result.Justification = $controlResult.StateManagement.AttestedStateData.Justification $result.AttestedState = [JsonHelper]::ConvertToJsonCustomCompressed($controlResult.StateManagement.AttestedStateData.DataObject) $result.AttestedDate = $controlResult.StateManagement.AttestedStateData.AttestedDate $result.AttestationExpiryDate = $controlResult.StateManagement.AttestedStateData.ExpiryDate } if($null -ne $controlResult.StateManagement -and $null -ne $controlResult.StateManagement.CurrentStateData) { $result.CurrentState = [JsonHelper]::ConvertToJsonCustomCompressed($controlResult.StateManagement.CurrentStateData.DataObject) } return $result; } static [ScanSource] GetScanSource() { $settings = [ConfigurationManager]::GetAzSKSettings(); [string] $laSource = $settings.LASource; if([string]::IsNullOrWhiteSpace($laSource)){ return [ScanSource]::SpotCheck } if($laSource.Equals("CICD", [System.StringComparison]::OrdinalIgnoreCase)){ return [ScanSource]::VSO } if($laSource.Equals("CA", [System.StringComparison]::OrdinalIgnoreCase)){ return [ScanSource]::Runbook } return [ScanSource]::SpotCheck } static [string] GetAIOrgTelemetryKey() { if(-not [string]::IsNullOrEmpty([RemoteReportHelper]::TelemetryKey)) { return [RemoteReportHelper]::TelemetryKey } $settings = [ConfigurationManager]::GetAzSKConfigData(); [RemoteReportHelper]::TelemetryKey = $settings.ControlTelemetryKey [guid]$key = [guid]::Empty # Trying to parse [RemoteReportHelper]::TelemetryKey into $key and then checking that it is not empty if([guid]::TryParse([RemoteReportHelper]::TelemetryKey, [ref] $key) -and ![guid]::Empty.Equals($key)) { return [RemoteReportHelper]::TelemetryKey; } [RemoteReportHelper]::TelemetryKey = [ConfigurationManager]::GetAzSKSettings().LocalControlTelemetryKey return [RemoteReportHelper]::TelemetryKey; } static [bool] IsAIOrgTelemetryEnabled() { if([RemoteReportHelper]::AIOrgTelemetryState -eq [AIOrgTelemetryStatus]::Enabled) { return $true } elseif([RemoteReportHelper]::AIOrgTelemetryState -eq [AIOrgTelemetryStatus]::Disabled) { return $false } #If AIOrgTelemetryState is Undefined then evaluate $settings = [ConfigurationManager]::GetAzSKConfigData(); $orgTelemetryKey = $settings.ControlTelemetryKey [guid]$key = [guid]::Empty # Trying to parse [RemoteReportHelper]::TelemetryKey into $key and then checking that it is not empty if([guid]::TryParse($orgTelemetryKey, [ref] $key) -and ![guid]::Empty.Equals($key)) { if($settings.EnableControlTelemetry) { [RemoteReportHelper]::AIOrgTelemetryState = [AIOrgTelemetryStatus]::Enabled return $true } else { [RemoteReportHelper]::AIOrgTelemetryState = [AIOrgTelemetryStatus]::Disabled return $false } } if([ConfigurationManager]::GetAzSKSettings().LocalEnableControlTelemetry) { [RemoteReportHelper]::AIOrgTelemetryState = [AIOrgTelemetryStatus]::Enabled return $true } else { [RemoteReportHelper]::AIOrgTelemetryState = [AIOrgTelemetryStatus]::Disabled return $false } } static [string] Mask([psobject] $toMask) { $maskBytes = [System.Text.Encoding]::UTF8.GetBytes($toMask.ToString().ToLower()) $maskBytes = ([RemoteReportHelper]::sha256AlgForMasking).ComputeHash($maskBytes) $take = 16 $sb = [System.Text.StringBuilder]::new($take) for($i = 0; $i -lt ($take/2); $i++){ $x = $sb.Append($maskBytes[$i].ToString("x2")) } return $sb.ToString(); } } # SIG # Begin signature block # MIInkgYJKoZIhvcNAQcCoIIngzCCJ38CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCqVeKkA9mxosAS # gw6sBZWxLeP+3Svl4Qo27dqq5dmZhqCCDXYwggX0MIID3KADAgECAhMzAAACy7d1 # OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA # wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4 # 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5 # RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN # lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X # a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ # ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf # zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh # 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4 # EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j # 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck # 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd # jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N # mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1 # pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB # fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To # /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGXIwghluAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHlPx15KgcJa0sfeyq7rCA8P # o1l9thledKNP58nfe0DnMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAlTGHdj8BXtph0fkedHEWg8E9oXzBObVmXd36RKnmvyh5ARsxJsnyaTKZ # evesFbMtmpyrn2EdEXzk06HC9bOULV/ACvg27UfQaw2ifiqLSwgWj82piYdRfupy # lY/juNsYMYOi+NWqUrV6w6F+vpy/pVUfUT1yKKwqvL1xacE7xHUZR5a5z1JIUxoY # SyZ62Rk76IaBbPT2wD6S/agkMT2OcHHlNHCV+vVVSOLmg1illhR/A2Qe2b6qj1KH # jXATinqP5Y90i9XxJbS1L+UzuXm5EVA+K50mlxpFICiLuHTilRiPWfX5iJYL1BoN # LdY6UiucSlsHDOgavoSC5u+yNv1aWaGCFvwwghb4BgorBgEEAYI3AwMBMYIW6DCC # FuQGCSqGSIb3DQEHAqCCFtUwghbRAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFQBgsq # hkiG9w0BCRABBKCCAT8EggE7MIIBNwIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCAuG2On1qAYN5HL5kLxairlgnoSYDo8hUwwqfApcOiW0wIGZBN6KCxJ # GBIyMDIzMDQxMzEwNDY1OC4wNFowBIACAfSggdCkgc0wgcoxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVy # aWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkVBQ0UtRTMx # Ni1DOTFEMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIR # VDCCBwwwggT0oAMCAQICEzMAAAHDi2/TSL8OkV0AAQAAAcMwDQYJKoZIhvcNAQEL # BQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIxMTA0MTkwMTI5 # WhcNMjQwMjAyMTkwMTI5WjCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEm # MCQGA1UECxMdVGhhbGVzIFRTUyBFU046RUFDRS1FMzE2LUM5MUQxJTAjBgNVBAMT # HE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQC767zqzdH+r6KSizzRoPjZibbU0M5m2V01HEwVTGbij2RV # aRKHZzyM4LElfBXYoWh0JPGkZCz2PLmdQj4ur9u3Qda1Jg8w8+163jbSDPAzUSxH # bqRunCUEfEVjiGTfLcAf7Vgp/1uG8+zuQ9tdsfuB1pyK14H4XsWg5G317QP92wF4 # bzQZkAXbLotYCPoLaYyqVp9eTBt9PJBqe5frli77EynInV8BESm5Hvrqt4+uqUTQ # ppp4PSeo6AatORJl4IwM8fo60nTSNczBsgPIfuXh9hF4ixN/M3kZ/dRqKuyN5r4o # XLbaVTx6WcheOh7LHelx6wf6rlqtjVzoc995KeR4yiT+DGcHs/UyO3sj0Qj22FC0 # y/L/VJSYsbXasFH8N+F4T9Umlyb9Nh6hXXU19BCeX+MFs9tJEGnQcapMhxYOljoy # BJ0GhARPUO+kTg9fiyd00ZzXAbKDjmkfrZkx9QX8LMZnuJXrftG2dAVcPNPGhIQS # R1cx1YMkb6OPGgLXqVGTXEWd+QDi6iZriYqyjuq8Tp3bv4rrLMhJZDtOO61gsomd # LM29+I2K7K//THEIBJIBG85De/1x6C8z+me5T1zqz7iCYrf7mOFy+dYZCokTS2lg # eaTduaYEvWAeb1OMEnPmb/yu8czdHDc5SFXj/CYAvfYqY9HlRtvjDDkc0aK5jQID # AQABo4IBNjCCATIwHQYDVR0OBBYEFBwYvs3Y128BorxNwuvExOxrxoHWMB8GA1Ud # IwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRp # bWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYI # KwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMv # TWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1Ud # EwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggIB # AN3yplscGp0EVEPEYbAOiWWdHJ3RaZSeOqg/7lAIfi8w8G3i6YdWEm7J5GQMQuRN # Zm5aordTXPYecZq1ucRNwdSXLCUf7cjtHt9TTMpjDY8sD5VrAJyuewgKATfbjYSw # QL9nRhTvjQ0n/Fu7Osa1MS1QiJC+vYAI8nKGw+i17wi1N/i41bgxujVA/S2NwEoK # AR7MgLgNhQzQFgJYKZ5mY3ACXF+lOWI4UQoH1RpKodKznVwfwljSCovcvAj0th+M # Q7vv74dj+cypcIyL2KFQqginZN+N/N2bk2DlX7LDz7BeXb1FxbhDgK8ee018rFP2 # hDcntgFBAQdYk+DxM1H3DgHzYXOasN3ywvoRO8a7HmEVzCYX5DatPkxrx1hRJ0JK # D+KGgRhQYlmdkv2fIOnWyd+VJVfsWkvIAvMMOUcFbUImFhV98lGirPUPiRGiipEE # 1FowUw+KeDLDBsSCEyF4ko2h1rsAaCr7UcfVp9GUT72phb0Uox7PF5CZ/yBy4C6G # v0gBfJoX0MXQ8nl/i6HM5K8gLUGQm3MXqinjlRhojtX71fx1zBdtkmcggAfVyNU7 # woQKHEoiSmThCDLQ+hyBTBoZaqYtZG7WFDVYladBe+8Fh5gMZZuP8+1KXLC/qbya # 6Mt6l8y8lxTbkpaSVI/YW43Hpo5V96N76mBvAhAhVDWdMIIHcTCCBVmgAwIBAgIT # MwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv # b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcN # MzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIw # DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT # /e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYj # DLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/Y # JlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d # 9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVU # j9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFK # u75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231f # gLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C # 89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC # +hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2 # XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54W # cmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMG # CSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cV # XQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/ # BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2Nz # L1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcU # AgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8G # A1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeG # RWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jv # b0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUH # MAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2Vy # QXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9n # ATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP # +2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27Y # P0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8Z # thISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNh # cy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7G # dP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4J # vbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjo # iV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TO # PqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ # 1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NN # je6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAsswggI0AgEBMIH4oYHQpIHNMIHKMQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNy # b3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVT # TjpFQUNFLUUzMTYtQzkxRDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg # U2VydmljZaIjCgEBMAcGBSsOAwIaAxUA8R0v4+z6HTd75Itd0bO5ju0u7s6ggYMw # gYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD # VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUF # AAIFAOfiN6swIhgPMjAyMzA0MTMxNjExMjNaGA8yMDIzMDQxNDE2MTEyM1owdDA6 # BgorBgEEAYRZCgQBMSwwKjAKAgUA5+I3qwIBADAHAgEAAgIDkTAHAgEAAgITQTAK # AgUA5+OJKwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAJI2/PjGXDVG3W+W # BjvBhHg+U6NW6J8GHVc9sqSU9ptqPGZxXwffivtwzPzBavy7RUN8tyY454eFpo+V # SZ/HfXzW8hbqzKWNNc6yOCAvre1/uWs9fAYSsaUjzveWEHGr54bWZSOGM3mV0Cvs # f3FENlh+5xi/gtLjNszXWnqBkiFPMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAHDi2/TSL8OkV0AAQAAAcMwDQYJYIZIAWUD # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B # CQQxIgQglAD7ASQzRaq6n+qeMX4kCjPG6CPDy4G6pGFzYZ2I6RcwgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCDS+1Obb5JJ6uHUqICTCslMAvFN8mi2U9wNnZlK # fvwqSTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB # w4tv00i/DpFdAAEAAAHDMCIEIK/IHtAYauwdlZJ5CLc1t4VywdjPQPWzdIkHJAu9 # GyZsMA0GCSqGSIb3DQEBCwUABIICAGFPhOhTSaf9HnGEo2VRxxjQCkEbII4KnFor # 7CFWQaWAjCY7V7NT+eF/z4CfaYK95UCaQ6u++ujpq/rFxxjC0mVuuuLhm4uqlRgX # rDWRu0y680oyBH5TXlDblxvkAuY+h6y8a3j5a7mD6Ly9AIZ1o3tcqYqec/TQiSAb # XX6+nlrQiYmz/6fU2MU0ki3+s0GQNns4r6o25GVhElL/bmYeuia11RGLot+uzpH5 # OWuRW1huA3umICdtNZNxP3NcQAWCCYVxLu3NU4/E6EnUlbIvLmyLwJl2F1cH7cWW # CtGdolLE6cNhBBFdexAlDDu52IhkSM9YlJ/IMFm4kh/W+ouILGiCleuPbUCVso4O # qLHN3UDvBYxUu+XKjWLp+P6CHSKg41hY24QvKjeltqFXhFydI9znQd0M/FgaKOvo # +qDMQNq6RmokwMu4y8sZLEvwr3ouu0A5kp3t59bygKTGEm+NZflYhIP3Gtujdorz # /Bt2HLNNiWiB0pSqFZiAvRbbAhqOS2DkrmN2a29tIySy5Ff1y67PUqsiwI3hxBtD # P8CwkJK+UZvAaPs2FT6pSaykvhWNHvCKeFwTQJy21MiTJDSMBdWNTa2NUpXIurG5 # vsicI9dXKdUwBPVzXcng9bmWW7Te4mLjCHAFUm7sn4N0Ip+hgGpwhgb/2v7NQA0c # ltjiaBOO # SIG # End signature block |