Framework/Listeners/RemoteReports/AIOrgTelemetry.ps1

Set-StrictMode -Version Latest

class AIOrgTelemetry: ListenerBase {
    [Microsoft.ApplicationInsights.TelemetryClient] $TelemetryClient;

    hidden AIOrgTelemetry() {
        $this.TelemetryClient = [Microsoft.ApplicationInsights.TelemetryClient]::new()
    }

    hidden static [AIOrgTelemetry] $Instance = $null;

    static [AIOrgTelemetry] GetInstance() {
        if ( $null  -eq [AIOrgTelemetry]::Instance -or  $null  -eq [AIOrgTelemetry]::Instance.TelemetryClient) {
            [AIOrgTelemetry]::Instance = [AIOrgTelemetry]::new();
        }
        return [AIOrgTelemetry]::Instance
    }

    [void] RegisterEvents() {
        $this.UnregisterEvents();

        $this.RegisterEvent([AzSKRootEvent]::GenerateRunIdentifier, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                $runIdentifier = [AzSKRootEventArgument] ($Event.SourceArgs | Select-Object -First 1)
                $currentInstance.SetRunIdentifier($runIdentifier);
            }
            catch
            {
                $currentInstance.PublishException($_);
            }
        });

        $this.RegisterEvent([SVTEvent]::EvaluationCompleted, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                $invocationContext = [System.Management.Automation.InvocationInfo] $currentInstance.InvocationContext
                $SVTEventContexts = [SVTEventContext[]] $Event.SourceArgs
                $featureGroup = [RemoteReportHelper]::GetFeatureGroup($SVTEventContexts)
                if($featureGroup -eq [FeatureGroup]::Organization){
                    $currentInstance.PushOrganizationScanResults($SVTEventContexts)
                }elseif($featureGroup -eq [FeatureGroup]::Service){
                    $currentInstance.PushServiceScanResults($SVTEventContexts)
                }else{
                }
            }
            catch
            {
                $currentInstance.PublishException($_);
            }
        });

        $this.RegisterEvent([AzSKGenericEvent]::Exception, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                [System.Management.Automation.ErrorRecord] $er = ($Event.SourceArgs | Select-Object -First 1)
                [AIOrgTelemetryHelper]::TrackException($er, $currentInstance.InvocationContext)
            }
            catch
            {
                # Handling error while registration of Exception event.
                # No need to break execution
            }
        });

        $this.RegisterEvent([AzSKRootEvent]::CommandError, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                [System.Management.Automation.ErrorRecord] $er = $Event.SourceArgs.ExceptionMessage
                [AIOrgTelemetryHelper]::TrackException($er, $currentInstance.InvocationContext)
            }
            catch
            {
                # Handling error while registration of CommandError event at AzSKRoot.
                # No need to break execution
            }
        });

        $this.RegisterEvent([SVTEvent]::CommandError, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                [System.Management.Automation.ErrorRecord] $er = $Event.SourceArgs.ExceptionMessage
                [AIOrgTelemetryHelper]::TrackException($er, $currentInstance.InvocationContext)
            }
            catch
            {
                # Handling error while registration of CommandError event at SVT.
                # No need to break execution
            }
        });

        $this.RegisterEvent([SVTEvent]::EvaluationError, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                [System.Management.Automation.ErrorRecord] $er = $Event.SourceArgs.ExceptionMessage
                [AIOrgTelemetryHelper]::TrackException($er, $currentInstance.InvocationContext)
            }
            catch
            {
                # Handling error while registration of EvaluationError event at SVT.
                # No need to break execution
            }
        });

        $this.RegisterEvent([SVTEvent]::ControlError, {
            $currentInstance = [AIOrgTelemetry]::GetInstance();
            try
            {
                if(![RemoteReportHelper]::IsAIOrgTelemetryEnabled()) { return; };
                [System.Management.Automation.ErrorRecord] $er = $Event.SourceArgs.ExceptionMessage
                [AIOrgTelemetryHelper]::TrackException($er, $currentInstance.InvocationContext)
            }
            catch
            {
                # Handling error while registration of ControlError event at SVT.
                # No need to break execution
            }
        });
        

    }

    hidden [void] PushOrganizationScanResults([SVTEventContext[]] $SVTEventContexts)
    {
        $SVTEventContextFirst = $SVTEventContexts[0]
        $baseProperties = @{
            "RunIdentifier" = $this.RunIdentifier;
            [TelemetryKeys]::FeatureGroup = [FeatureGroup]::Organization;
            "ScanKind" = [RemoteReportHelper]::GetOrganizationScanKind(
                $this.InvocationContext.MyCommand.Name,
                $this.InvocationContext.BoundParameters);
            "OrganizationMetadata" = [JsonHelper]::ConvertToJsonCustomCompressed($SVTEventContextFirst.OrganizationContext.OrganizationMetadata);
        }
        $this.PushControlResults($SVTEventContexts, $baseProperties)
    }

    hidden [void] PushServiceScanResults([SVTEventContext[]] $SVTEventContexts)
    {
        $SVTEventContextFirst = $SVTEventContexts[0]
        # PartialScanIdentifier for each control scanned event to get idea about all resources scanned for a subscription in case of partial run
        $PartialScanIdentifier = ""
        # try catch for cases if partial scan is not applicable
        try{
            $PartialScanIdentifier = $SVTEventContextFirst.PartialSCanIdentifier
        } 
        catch{
            $PartialScanIdentifier = ""
        }
        $baseProperties = @{
            "RunIdentifier" = $this.RunIdentifier;
            [TelemetryKeys]::FeatureGroup = [FeatureGroup]::Service;
            "ScanKind" = [RemoteReportHelper]::GetServiceScanKind(
                $this.InvocationContext.MyCommand.Name,
                $this.InvocationContext.BoundParameters);
            "Feature" = $SVTEventContextFirst.FeatureName;
            "ResourceGroup" = $SVTEventContextFirst.ResourceContext.ResourceGroupName;
            "ResourceName" = $SVTEventContextFirst.ResourceContext.ResourceName;
            "ResourceId" = $SVTEventContextFirst.ResourceContext.ResourceId;
            "ResourceMetadata" = [JsonHelper]::ConvertToJsonCustomCompressed($SVTEventContextFirst.ResourceContext.ResourceMetadata);
            "PartialScanIdentifier" = $PartialScanIdentifier 
        }
        $this.PushControlResults($SVTEventContexts, $baseProperties)
    }

    hidden [void] PushControlResults([SVTEventContext[]] $SVTEventContexts, [hashtable] $BaseProperties){
        $telemetryEvents = [System.Collections.ArrayList]::new()
        foreach($context in $SVTEventContexts){
            $propertiesCollection = $this.AttachControlProperties($BaseProperties, $context)
            foreach($properties in $propertiesCollection){
                $telemetryEvent = "" | Select-Object Name, Properties, Metrics
                $telemetryEvent.Name = "Control Scanned"
                $telemetryEvent.Properties = $properties
                $telemetryEvent = [AIOrgTelemetry]::SetCommonProperties($telemetryEvent);
                $telemetryEvents.Add($telemetryEvent) | Out-Null
            }
        }
        [AIOrgTelemetryHelper]::TrackEvents($telemetryEvents);
    }


    hidden [hashtable[]] AttachControlProperties([hashtable] $BaseProperties, [SVTEventContext] $context){
        if($null -eq $context) {return  ([hashtable[]]([System.Collections.ArrayList]::new()))}
        $properties = @{}
        if ($null -ne $BaseProperties) {
            $properties = $BaseProperties.Clone()
        }
        $propertiesArray = [System.Collections.ArrayList]::new()
        $properties.Add("ControlIntId", $context.ControlItem.Id);
        $properties.Add("ControlId", $context.ControlItem.ControlID);
        $properties.Add("ControlSeverity", $context.ControlItem.ControlSeverity);
        $properties.Add("IsBaselineControl", $context.ControlItem.IsBaselineControl)
        #add PreviewBaselineFlag
        $properties.Add("IsPreviewBaselineControl", $context.ControlItem.IsPreviewBaselineControl)
        
        if (!$context.ControlItem.Enabled) {
            $properties.Add("VerificationResult", [VerificationResult]::Disabled)
            $properties.Add("AttestationStatus", [AttestationStatus]::None)
            $propertiesArray.Add($properties) | Out-Null
        }else{
            $results = $context.ControlResults            
            if($results.Count -eq 1){
                $properties.Add("HasAttestationWritePermissions", $results[0].CurrentSessionContext.Permissions.HasAttestationWritePermissions)
                $properties.Add("HasAttestationReadPermissions", $results[0].CurrentSessionContext.Permissions.HasAttestationReadPermissions)
                $properties.Add("ActualVerificationResult", $results[0].ActualVerificationResult)
                $properties.Add("AttestationStatus", $results[0].AttestationStatus)
                $properties.Add("VerificationResult", $results[0].VerificationResult)
                $properties.Add("HasRequiredAccess", $results[0].CurrentSessionContext.Permissions.HasRequiredAccess)
                $properties.Add("TimeTakenInMs", $results[0].TimeTakenInMs)
                $properties.Add("ScanStartDateTime", $results[0].ScanStartDateTime)
                $properties.Add("ScanEndDateTime", $results[0].ScanEndDateTime)
                if($null -ne $context.ResourceContext){
                    if($context.ResourceContext.ResourceName -eq $results[0].ChildResourceName -or [string]::IsNullOrWhiteSpace($results[0].ChildResourceName)){
                        $properties.Add("IsNestedResource", 'No')
                        $properties.Add("NestedResourceName", "NA")
                    }else{
                        $properties.Add("IsNestedResource", 'Yes')
                        $properties.Add("NestedResourceName", $results[0].ChildResourceName)
                    }
                }
                if(($null -ne $results[0].StateManagement) -and ($null -ne $results[0].StateManagement.AttestedStateData)) {
                    $properties.Add("AttestedBy", $results[0].StateManagement.AttestedStateData.AttestedBy)
                    $properties.Add("Justification", $results[0].StateManagement.AttestedStateData.Justification)
                    $properties.Add("AttestedState", [JsonHelper]::ConvertToJsonCustomCompressed($results[0].StateManagement.AttestedStateData.DataObject))
                    $properties.Add("AttestedDate", ($results[0].StateManagement.AttestedStateData.AttestedDate).Tostring("yyyy_MM_dd_hh_mm"))
                    $properties.Add("ExpiryDate",  ([DateTime]$results[0].StateManagement.AttestedStateData.ExpiryDate).Tostring("yyyy_MM_dd_hh_mm"))
                }
                if(($null -ne $results[0].StateManagement) -and ($null -ne $results[0].StateManagement.CurrentStateData)) {
                    $properties.Add("CurrentState", [JsonHelper]::ConvertToJsonCustomCompressed($results[0].StateManagement.CurrentStateData.DataObject))
                }
                $propertiesArray.Add($properties) | Out-Null
            }elseif($results.Count -gt 1){
                $properties.Add("IsNestedResource", 'Yes')
                foreach($result in $results){
                    $propertiesIn = $properties.Clone()
                    $propertiesIn.Add("ActualVerificationResult", $result.ActualVerificationResult)
                    $propertiesIn.Add("AttestationStatus", $result.AttestationStatus)
                    $propertiesIn.Add("VerificationResult", $result.VerificationResult)
                    $propertiesIn.Add("NestedResourceName", $result.ChildResourceName)
                    $propertiesIn.Add("HasRequiredAccess", $result.CurrentSessionContext.Permissions.HasRequiredAccess)
                    if(($null -ne $result.StateManagement) -and ($null -ne $result.StateManagement.AttestedStateData)) {
                        $propertiesIn.Add("AttestedBy", $result.StateManagement.AttestedStateData.AttestedBy)
                        $propertiesIn.Add("Justification", $result.StateManagement.AttestedStateData.Justification)
                        $propertiesIn.Add("AttestedState", [JsonHelper]::ConvertToJsonCustomCompressed($result.StateManagement.AttestedStateData.DataObject))
                        $propertiesIn.Add("AttestedDate", ($result.StateManagement.AttestedStateData.AttestedDate).Tostring("yyyy_MM_dd_hh_mm"))
                        $propertiesIn.Add("ExpiryDate", ([DateTime]$result.StateManagement.AttestedStateData.ExpiryDate).Tostring("yyyy_MM_dd_hh_mm"))
                    }
                    if(($null -ne $result.StateManagement) -and ($null -ne $result.StateManagement.CurrentStateData)) {
                        $propertiesIn.Add("CurrentState", [JsonHelper]::ConvertToJsonCustomCompressed($result.StateManagement.CurrentStateData.DataObject))
                    }
                    $propertiesArray.Add($propertiesIn) | Out-Null
                }
            }
        }
        $returnObj = [hashtable[]] $propertiesArray
        return $returnObj;
    }

    static [psobject] SetCommonProperties([psobject] $telemetryEvent) 
    {
        try
        {
            $NA = "NA";
            try {
                $telemetryEvent.properties.Add("ScanSource", [RemoteReportHelper]::GetScanSource());
            }
            catch {
                # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                # No need to break execution
            }
            try {
                $module = Get-Module 'AzSK*' | Select-Object -First 1
                $telemetryEvent.properties.Add("ScannerModuleName", $module.Name);
                $telemetryEvent.properties.Add("ScannerVersion", $module.Version.ToString());
                $telemetryEvent.properties.Add("OrgVersion", [ConfigurationManager]::GetAzSKConfigData().GetLatestAzSKVersion($module.Name).ToString());    
                $telemetryEvent.properties.Add("PolicyOrgName", [ConfigurationManager]::GetAzSKConfigData().PolicyOrgName)
                $AzSKLatestVersion= [ConfigurationManager]::GetAzSKConfigData().GetAzSKLatestPSGalleryVersion($module.Name)        
                $telemetryEvent.properties.Add("LatestVersion", $AzSKLatestVersion);                
                
            }
            catch {
                # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                # No need to break execution
            }
            try {
                $organizationContext = [ContextHelper]::GetCurrentContext()
                try {
                    $telemetryEvent.properties.Add([TelemetryKeys]::OrganizationId, $organizationContext.Organization.Id)
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    $telemetryEvent.properties.Add([TelemetryKeys]::OrganizationName, $organizationContext.Organization.Name)
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    $telemetryEvent.properties.Add("ADOEnv", $organizationContext.Environment.Name)
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    $telemetryEvent.properties.Add("TenantId", $organizationContext.Tenant.Id)
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    $telemetryEvent.properties.Add("AccountId", $organizationContext.Account.Id)
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    if ($telemetryEvent.Properties.ContainsKey("RunIdentifier")) {
                        $actualRunId = $telemetryEvent.Properties["RunIdentifier"]
                        if ($telemetryEvent.Properties.ContainsKey("UniqueRunIdentifier")) {
                            $telemetryEvent.Properties["UniqueRunIdentifier"] = [RemoteReportHelper]::Mask($organizationContext.Account.Id + '##' + $actualRunId.ToString())
                        }
                        else
                        {
                            $telemetryEvent.properties.Add("UniqueRunIdentifier", [RemoteReportHelper]::Mask($organizationContext.Account.Id + '##' + $actualRunId.ToString()))
                        }
                    }
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
                try {
                    $telemetryEvent.properties.Add("AccountType", $organizationContext.Account.Type);
                }
                catch {
                    # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                    # No need to break execution
                }
            }
            catch {
                # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
                # No need to break execution
            }
        }
        catch {
            # Eat the current exception which typically happens when the property already exist in the object and try to add the same property again
            # No need to break execution
        }
        return $telemetryEvent;
    }
}

# SIG # Begin signature block
# MIInvAYJKoZIhvcNAQcCoIInrTCCJ6kCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD9f55MdS/g3QqT
# VrRD6jwwrM2oOf+4e/7GBRtndKZpSaCCDYEwggX/MIID56ADAgECAhMzAAACUosz
# qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I
# sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O
# L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA
# v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o
# RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8
# q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3
# uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp
# kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7
# l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u
# TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1
# o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti
# yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z
# 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf
# 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK
# WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW
# esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F
# 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZkTCCGY0CAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN
# BglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg/f7aVLZf
# dwK1LMUu+xasPDYMscjFOFrCF4S+sjkSF38wRAYKKwYBBAGCNwIBDDE2MDSgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRyAGmh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20g
# MA0GCSqGSIb3DQEBAQUABIIBAH0mSxPKNVJnat+WyR4aB/UpMDgEfqvQP8KD9Bqg
# ydxcwcPm3h2p0prIccjvfvqbQ3JPfN+eeeOQ+arfCvtqNRazPztXeCnqPd82AIIO
# 7u4sQgMru7jFVSFkGfCSubopxoZ+It5G8KVKkSlLY0/CALtU4s2g8dU2LecDFSUI
# MQY5Y6IR5rSyUMS6OlyQ3lcLqZuoIOqs+tXR4lQkN+ZrhEYWAr3jLVhlIMlL7n15
# ehIfw5yU+lu+goeXeOPAdtjRHdncZV7vTVQQAhbPN2ffOMkq20mawMj4JAvufJla
# cOFrWiHCXrd2It8tiVZnwvg4Aqeaq0bHWW1oD5LEGBG57zKhghcZMIIXFQYKKwYB
# BAGCNwMDATGCFwUwghcBBgkqhkiG9w0BBwKgghbyMIIW7gIBAzEPMA0GCWCGSAFl
# AwQCAQUAMIIBWQYLKoZIhvcNAQkQAQSgggFIBIIBRDCCAUACAQEGCisGAQQBhFkK
# AwEwMTANBglghkgBZQMEAgEFAAQghze9UCMbL39fT+TdWaMvhRshlCWIfNyvLpXt
# 8dHvL4UCBmH9VmkTLhgTMjAyMjAyMTUxMDIxMDAuNDkxWjAEgAIB9KCB2KSB1TCB
# 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk
# TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U
# aGFsZXMgVFNTIEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgU2VydmljZaCCEWgwggcUMIIE/KADAgECAhMzAAABj/NRqOta
# ct3MAAEAAAGPMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
# QSAyMDEwMB4XDTIxMTAyODE5Mjc0NloXDTIzMDEyNjE5Mjc0NlowgdIxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29m
# dCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT
# UyBFU046RDA4Mi00QkZELUVFQkExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0
# YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCZVz7+
# tc8XHoWTj4Kkuu5sOstNrdC4AdFVe7L7OzFfCSiCRPRr5da4FpvAfKqPxFGJlBC9
# 29s6rk1ETE54eJoK2RSxDTYRIB70LP6WgE22x8Krzjq7ei1YcImWqS8OtKvuYwGr
# BxFjtx+EAZ8u+WkxKiOgCeTtF6P6NwmdjEh43fgXeH0nAA1jfrSgZgIhLuks6ixZ
# X5vG6D26JNlgT9dyXJg0Xpd3Nn/MP/hTmnFPgxlCbMEa8Oz7xwN0D+y1l+P+vL6L
# RdRg0U+G6pz5QqTCb9c0cH4IOwZCX5lLQZxtRS6fhU9OEcmbqZEDAvnLzOm1YQih
# xtN5FJOZmdRraJgfYQ4FXt4KPHRJ1vqQtzXF0VFyQN5AZHgnXIXLJu5mxQ/zHR06
# wQSgtC46G4qUMtASDsPpnGZkmdLwHTd7CT9KlUuqxvrpTarIXgHAO3W5mSMRnt+K
# cihSBLPgHt9Ytgh47Y4JjEgTRe/CxWin0+9NdNm0Y/POYdTvncZqsrK4zqhr+ppP
# Ni+sB9RvspiG9VArEZQ+Qv354qIzsbSp6ckIWtfNk/BFahxwBHfc+E0S67PMpkUn
# gN5pMIuD/y4rRDhCMVF5/mfgf7YpAgSJtnvMh4FfeOCysgJvPNKbRBfdJFWZkf/8
# CqnxjGTBygjVYIGLO/zjP16rBEF1Dgdhw1tAwwIDAQABo4IBNjCCATIwHQYDVR0O
# BBYEFPMG5nRrrknO4qHOhZvbl/s3I3G8MB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl
# 0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAy
# MDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93
# d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1T
# dGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAww
# CgYIKwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggIBAM1/06j3PKELmfWMLyJTs0lj
# f0WLOOHFnAlslj9i3CfremUyVNJoGl6tqfnrp+5GiMYlK/cTBmz5Gu45TZP9lEPH
# hUd6wse1yUTwaYwzWpMxpk8vwjYWtGZ/k6ingapzE100QIEKVVmafQrMV08ypFrn
# /RHoKaComHSa68iaKSAe5u+iGxq88TLIdBr3gcPj8s0p39ghoIoo/P1IDl8BrimF
# DgS/PZq5j1JSW4h3kwr0flyNZXAHEK9gAP7UJb3PsayEmU2OoG9a0o7onQB6Z+Dr
# PbyDupzsb+0K2uUfj/LbvL6y27BZc2/B2xJ3WW8HgzrcC4yX1inpq79cWScbMk8X
# qf+5ZHomFC/OHjQguB5OEuZiF/zP5oNvivY4EsbU/YHpoJNbZhCS3tOlSfMjRwoa
# vbXcJsq0aT844gdKwM7FqyZ4Yn4WJQkKJXXnCHdplP9VP8+Qv0TiEMEDAa3j0bzy
# BII7TH2N90NlZ1YZsQteVKYDcQ/h5NirtGuiVjTgbx8a0XSnO5m7jcDb3Noj2Uiv
# m6UpHPwShAdTpy7Q/FTDQH0fxwCS9DFoy6ZFn/h8Juo1vhNw+Q9xY4jbhBiW+lu1
# P2nfV+VgSWZznCMamUCTL+eQlxPQdkQ1d6fFa0++3iByiqml4k8DdL/UPnsovfrr
# t6kivTJXb3QTai1lsBbwMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAA
# FTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0
# aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
# ADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9s
# SuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3
# po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2
# vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GP
# sjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3
# rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDP
# c31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8F
# A6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q
# 6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1f
# MHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLv
# jflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGj
# ggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+
# ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIw
# XAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMG
# A1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsG
# A1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJc
# YmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9z
# b2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIz
# LmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWlj
# cm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0
# MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5H
# ZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2
# HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1
# JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8
# F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99J
# o3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4K
# WN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZ
# kWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58
# oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w
# /ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+
# 7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1iz
# oXBm8qGCAtcwggJAAgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl
# cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpEMDgyLTRC
# RkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIj
# CgEBMAcGBSsOAwIaAxUAPk0vggR250gHB0agJpXRYFtBmmqggYMwgYCkfjB8MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOW1rBAw
# IhgPMjAyMjAyMTUxMjM1MjhaGA8yMDIyMDIxNjEyMzUyOFowdzA9BgorBgEEAYRZ
# CgQBMS8wLTAKAgUA5bWsEAIBADAKAgEAAgIKHwIB/zAHAgEAAgIRSTAKAgUA5bb9
# kAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6Eg
# oQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBABbsRXkKYNwDUD0MdQZeol6T
# hqQmBDzlXhQnNYUds/DT2BNiDmeaMs0xcEdPyQCvtytrmXnngKhJI4o+vANJXS/a
# 7rSHBaSQ6rROfBoRDBv6V8YMwMEZ5vYXZVHH9VJBQYqmZBoz3hE0sbR7UphNdzZV
# NseZvrwVpZV5MgxdiEdiMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgUENBIDIwMTACEzMAAAGP81Go61py3cwAAQAAAY8wDQYJYIZIAWUDBAIBBQCg
# ggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQg
# t/3FXHAv4EabtmP8sqiqNVyVJ6oc1D2fMot5OgMfOUAwgfoGCyqGSIb3DQEJEAIv
# MYHqMIHnMIHkMIG9BCCXcgVP4sbGC5WOIqbbYi2Y7p0UNZbydKG7o7qDzIXHHzCB
# mDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk
# BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABj/NRqOta
# ct3MAAEAAAGPMCIEIEVovGoO3hMtwk/Fq4VXrEIc5RMn1YsNS4nhJVGg/PXSMA0G
# CSqGSIb3DQEBCwUABIICAEFUAuR4D0a2qi8ANUutX7Zk3PKyWLr9SkV6wYl+pOkD
# Yn+cp19KmVH5ihDeYIPVI4PvSdwqUCOiQjV+jytYmnb842nTW8OdRbyotbwSrhJv
# BDSdFAYd3dIm3qaa8YHqMSDiC1Mk7AKapqYg2Az/bYHqhY7J2ZJOuSDIVKcj40ZO
# ouGCFinSVsPXclUc2QhG2teiX1xakID/mfyAo8FxzVr9T/lyfCbXRxJx5YjOJMMn
# YMdBT6RcE3w53Znfu+0dQ+Ked2WlU26lYMNlWfJsjwjf0bqTUhW061fKLRgDDX0T
# ej5x4Nu/BtWWCD3WL70zp4bWuCwXKo0r5qJE4bHc5dAJB9YejDB0a5CC39EnmzUN
# bBLN6qHjyJZHXgw8aDtzJvkiUI2tsT++S1s/vpFDDIzD2jH9KU0RnjBpfnIHHj81
# nL9oL1/ke9TuNC8Eu9BKDnBJ1m6jWYbJcuKpgZ9qryrynWZqcIq6/He8+tH+AWw1
# nShNaqMFuZxOjQEdzagzFQRuCynV5s8wvM5NLxt6ZHPF31kTzRQOkdvQFLIpH3Kr
# ktSeOk/iSWytEcTG8ZtPEeYBWMzlntFW/2LVyLyTeUxyW+bb6X7bNDSuHT+gtCv2
# w7gpMtWYoVmcE5ETTa1t5eAhkL45SimfWqUd6F3l4WpLGgsjoi+b7c53uZqa3uVl
# SIG # End signature block