Framework/Core/SVT/ADO/ADO.User.ps1

Set-StrictMode -Version Latest 
class User: ADOSVTBase {    

    User([string] $organizationName, [SVTResource] $svtResource): Base($organizationName, $svtResource) {

    }

    hidden [ControlResult] CheckPATAccessLevel([ControlResult] $controlResult) {
        $apiURL = "https://vssps.dev.azure.com/{0}/_apis/Token/SessionTokens?displayFilterOption=1&createdByOption=3&sortByOption=3&isSortAscending=false&startRowNumber=1&pageSize=100&api-version=5.0-preview.1" -f $($this.OrganizationContext.OrganizationName);
        $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL);
        $controlResult.AddMessage("Currently this control evaluates PATs for all the organizations the user has access to.")
        try {
            if ($responseObj.Count -gt 0) {
                $AccessPATList = $responseObj | Where-Object { $_.validto -gt $(Get-Date -Format "yyyy-MM-dd") }
                $AccessPATListCount = ($AccessPATList | Measure-Object).Count
                if ($AccessPATListCount -gt 0) {
                    $controlResult.AddMessage("Total number of active user PATs: $($AccessPATListCount)");
                    $controlResult.AdditionalInfo += "Total number of active user PATs: " + $AccessPATListCount;
                    $statusSet = $false # Use this variable to check whether scanStaus is already set

                    $fullAccessPATList = $AccessPATList | Where-Object { $_.scope -eq "app_token" }
                    $fullAccessPATListCount = ($fullAccessPATList | Measure-Object).Count 
                    if ($fullAccessPATListCount -gt 0) {
                        $controlResult.AddMessage("`nTotal number of PATs configured with full access: $($fullAccessPATListCount)");
                        $controlResult.AdditionalInfo += "Total number of PATs configured with full access: " + $fullAccessPATListCount;
                        $fullAccessPATNames = $fullAccessPATList | Select-Object displayName, scope 
                        $controlResult.AddMessage([VerificationResult]::Failed,
                            "The following PATs have been configured with full access: ", $fullAccessPATNames);
                        $statusSet = $true
                    }

                    $remainingPATList = $AccessPATList | Where-Object { $_.scope -ne "app_token" }
                    $remainingPATListCount = ($remainingPATList | Measure-Object).Count
                    if ($remainingPATListCount -gt 0){
                        $controlResult.AddMessage("`nTotal number of PATs configured with custom defined access: $remainingPATListCount");
                        $controlResult.AdditionalInfo += "Total number of PATs configured with custom defined access: " + $remainingPATListCount;
                        $remainingAccessPATNames = $remainingPATList | Select-Object displayName, scope 
                        if ($statusSet) {
                            $controlResult.AddMessage("The following PATs have been configured with custom defined access: ", $remainingAccessPATNames)
                        }   
                        else {
                            $controlResult.AddMessage([VerificationResult]::Verify, "Verify that the following PATs have minimum required permissions: ", $remainingAccessPATNames)                        
                        }
                    }
                }
                else {
                    $controlResult.AddMessage([VerificationResult]::Passed,
                        "No active PATs found");
                }
            }
            else {
                $controlResult.AddMessage([VerificationResult]::Passed,
                    "No PATs found");
            }
                    
        }
        catch {
            $controlResult.AddMessage([VerificationResult]::Error,
                "Could not fetch the list of PATs");
                $controlResult.LogException($_)
        }
        
        return $controlResult;
    }

    hidden [ControlResult] CheckAltCred([ControlResult] $controlResult) {

        $apiURL = "https://dev.azure.com/{0}/_apis/Contribution/dataProviders/query?api-version=5.1-preview.1" -f $($this.OrganizationContext.OrganizationName);
        $inputbody = '{"contributionIds": ["ms.vss-admin-web.alternate-credentials-data-provider","ms.vss-admin-web.action-url-data-provider"]}' | ConvertFrom-Json
        $responseObj = [WebRequestHelper]::InvokePostWebRequest($apiURL, $inputbody);

        if ([Helpers]::CheckMember($responseObj, "data"), $responseObj.data.'ms.vss-admin-web.alternate-credentials-data-provider') {
            if ((-not $responseObj.data.'ms.vss-admin-web.alternate-credentials-data-provider'.alternateCredentialsModel.basicAuthenticationDisabled) -or (-not $responseObj.data.'ms.vss-admin-web.alternate-credentials-data-provider'.alternateCredentialsModel.basicAuthenticationDisabledOnAccount)) {
                $controlResult.AddMessage([VerificationResult]::Passed,
                    "Alt credential is disabled");
            }
            else {
                $controlResult.AddMessage([VerificationResult]::Passed,
                    "Alt credential is enabled");
            }
        }
        else {
            $controlResult.AddMessage([VerificationResult]::Manual,
                "Alt credential not found");
        }
        return $controlResult
    }

    hidden [ControlResult] ValidatePATExpiryPeriod([ControlResult] $controlResult) {
        $controlResult.AddMessage("Currently this control evaluates PATs for all the organizations the user has access to.")  
        try {

            $apiURL = "https://vssps.dev.azure.com/{0}/_apis/Token/SessionTokens?displayFilterOption=1&createdByOption=3&sortByOption=3&isSortAscending=false&startRowNumber=1&pageSize=100&api-version=5.0-preview.1" -f $($this.OrganizationContext.OrganizationName);
            $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL);

            if ($responseObj.Count -gt 0) { 
                $AccessPATList = $responseObj | Where-Object { $_.validto -gt $(Get-Date -Format "yyyy-MM-dd") }
           
                if (($AccessPATList | Measure-Object).Count -gt 0) {
                    $res = $AccessPATList | Where-Object {(New-Timespan -Start $_.ValidFrom -End $_.ValidTo).Days -gt 180 }
                
                    if (($res | Measure-Object).Count -gt 0) {
                        $PATList = ($res | Select-Object -Property @{Name = "Name"; Expression = { $_.displayName } }, @{Name = "ValidFrom"; Expression = { $_.validfrom } }, @{Name = "ValidTo"; Expression = { $_.validto } }, @{Name = "ValidationPeriod"; Expression = { (New-Timespan -Start $_.ValidFrom -End $_.ValidTo).Days } });    
                        $controlResult.AddMessage([VerificationResult]::Failed, "The following PATs have validity period of more than 180 days: ", $PATList)
                        $PATListCount = ($PATList | Measure-Object).Count  
                        $controlResult.AdditionalInfo += "Total number of PATs that have validity period of more than 180 days: " + $PATListCount;
                        $controlResult.AdditionalInfo += "List of PATs that have validity period of more than 180 days: " + [JsonHelper]::ConvertToJsonCustomCompressed($PATList);
                    }
                    else {
                        $controlResult.AddMessage([VerificationResult]::Passed,
                            "No PATs have been found with validity period of more than 180 days.") 
                    }
                }
                else {
                    $controlResult.AddMessage([VerificationResult]::Passed,
                        "No active PATs have been found.")  
                }
            }
            else {
                $controlResult.AddMessage([VerificationResult]::Passed,
                    "No PATs have been found.");
            }
        }
        catch {
            $controlResult.AddMessage([VerificationResult]::Error,
                "Could not fetch the list of PATs.");
                $controlResult.LogException($_)
        }
        
        return $controlResult;
    }
    hidden [ControlResult] CheckPATExpiration([ControlResult] $controlResult) {
        $controlResult.AddMessage("Currently this control evaluates PATs for all the organizations the user has access to.")
        try {

            $apiURL = "https://vssps.dev.azure.com/{0}/_apis/Token/SessionTokens?displayFilterOption=1&createdByOption=3&sortByOption=3&isSortAscending=false&startRowNumber=1&pageSize=100&api-version=5.0-preview.1" -f $($this.OrganizationContext.OrganizationName);
            $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL);

            if ($responseObj.Count -gt 0) { 
                $date = Get-Date;
                $AccessPATList = $responseObj | Where-Object { $_.validto -gt $(Get-Date -Format "yyyy-MM-dd") }
           
                if (($AccessPATList | Measure-Object).Count -gt 0) {
                    $PATExpri7Days = $AccessPATList | Where-Object { (New-Timespan -Start $date -End $_.validto ).Days  -lt 8 };
                    $PATExpri30Days = $AccessPATList | Where-Object { ((New-Timespan -Start $date -End $_.validto).Days -gt 7) -and ((New-Timespan -Start $date -End $_.validto).Days -lt 31) };
                    $PATOther = $AccessPATList | Where-Object { ((New-Timespan -Start $date -End $_.validto).Days -gt 30) };

                    if (($PATExpri7Days | Measure-Object).Count -gt 0) {
                        $PAT7List = ($PATExpri7Days | Select-Object -Property @{Name = "Name"; Expression = { $_.displayName } }, @{Name = "ValidFrom"; Expression = { $_.validfrom } }, @{Name = "ValidTo"; Expression = { $_.validto } }, @{Name = "Remaining"; Expression = { (New-Timespan -Start $date -End $_.validto).Days } });    
                        $controlResult.AddMessage("The following PATs expire within 7 days: ", $PAT7List )
                        $controlResult.AdditionalInfo += "Total number of PATs that will expire within 7 days: " + ($PAT7List | Measure-Object).Count;
                    }
                    if (($PATExpri30Days | Measure-Object).Count -gt 0) {
                        $PAT30List = ($PATExpri30Days | Select-Object -Property @{Name = "Name"; Expression = { $_.displayName } }, @{Name = "ValidFrom"; Expression = { $_.validfrom } }, @{Name = "ValidTo"; Expression = { $_.validto } }, @{Name = "Remaining"; Expression = { (New-Timespan -Start $date -End $_.validto).Days } });    
                        $controlResult.AddMessage("The following PATs expire after 7 days but within 30 days: ", $PAT30List )
                        $controlResult.AdditionalInfo += "Total number of PATs that will expire after 7 days but within 30 days: " + ($PAT30List | Measure-Object).Count;
                    }
              
                    if (($PATOther | Measure-Object).Count -gt 0) {
                        $PATOList = ($PATOther | Select-Object -Property @{Name = "Name"; Expression = { $_.displayName } }, @{Name = "ValidFrom"; Expression = { $_.validfrom } }, @{Name = "ValidTo"; Expression = { $_.validto } }, @{Name = "Remaining"; Expression = { (New-Timespan -Start $date -End $_.validto).Days } });    
                        $controlResult.AddMessage("The following PATs expire after 30 days: ", $PATOList )
                        $controlResult.AdditionalInfo += "Total number of PATs that will expire after 30 days: " + ($PATOList | Measure-Object).Count;
                    }
                    if (($PATExpri7Days | Measure-Object).Count -gt 0) {
                        $controlResult.VerificationResult = [VerificationResult]::Failed
                    }
                    elseif (($PATExpri30Days | Measure-Object).Count -gt 0) {
                        $controlResult.VerificationResult = [VerificationResult]::Verify
                    }
                    else {
                        $controlResult.AddMessage([VerificationResult]::Passed, "No PATs have been found which expire within 30 days.")
                    }
                }
                else {
                    $controlResult.AddMessage([VerificationResult]::Passed,
                        "No active PATs have been found.")  
                }
            }
            else {
                $controlResult.AddMessage([VerificationResult]::Passed,
                    "No PATs have been found.");
            }
        }
        catch {
            $controlResult.AddMessage([VerificationResult]::Error,
                "Could not fetch the list of PATs.");
                $controlResult.LogException($_)
        }
        
        return $controlResult;
    }

    hidden [ControlResult] CheckPATOrgAccess([ControlResult] $controlResult) {
        $apiURL = "https://{0}.vssps.visualstudio.com/_apis/Token/SessionTokens?displayFilterOption=1&createdByOption=3&sortByOption=3&isSortAscending=false&startRowNumber=1&pageSize=100&api-version=5.0-preview.1" -f $($this.OrganizationContext.OrganizationName);
        $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL);
        $controlResult.AddMessage("Currently this control evaluates PATs for all the organizations the user has access to.")
        try {
            if ($responseObj.Count -gt 0) {
                $AccessPATList = $responseObj | Where-Object { $_.validto -gt $(Get-Date -Format "yyyy-MM-dd") }
                $AccessPATListCount = ($AccessPATList | Measure-Object).Count
                $allOrgPATCount = 0; #counter to store number of PATs that are accessible to all orgs.
                $allOrgPAT = @() #list to capture PAts accessible to all orgs.

                if ($AccessPATListCount -gt 0) {
                    $controlResult.AddMessage("Total number of active user PATs: $($AccessPATListCount)");
                    $AccessPATList | ForEach-Object{
                        if([string]::IsNullOrWhiteSpace($_.targetAccounts)) #if a PAT is tied to a single org, value of targetAccounts is equal to org id. If its accessible to all orgs, this value is null.
                        {
                            $allOrgPATCount ++;
                            $allOrgPAT += $_.DisplayName
                        }
                    }
                    if($allOrgPATCount -gt 0)
                    {   
                        $controlResult.AddMessage("Total number of active PATs accessible to all organizations: $($allOrgPATCount)");
                        $controlResult.AddMessage([VerificationResult]::Failed, "The below active PATs are accessible to all organizations: ", $allOrgPAT);
                        $controlResult.AdditionalInfo += "Total number of active PATs accessible to all organizations: " + $allOrgPATCount;
                        $controlResult.AdditionalInfo += "List of active PATs accessible to all organizations: " + [JsonHelper]::ConvertToJsonCustomCompressed($allOrgPAT);
                    }
                    else
                    {
                        $controlResult.AddMessage([VerificationResult]::Passed, "No active PATs are accessible to all organizations.");
                    }
                }
                else 
                {
                    $controlResult.AddMessage([VerificationResult]::Passed, "No active PATs found.");
                }
            }
            else 
            {
                $controlResult.AddMessage([VerificationResult]::Passed, "No PATs found.");
            }
                    
        }
        catch 
        {
            $controlResult.AddMessage([VerificationResult]::Error, "Could not fetch the list of PATs");
            $controlResult.LogException($_)
        }
        
        return $controlResult;
    }

    hidden [ControlResult] CheckPATCriticalPermissions([ControlResult] $controlResult) {
        $controlResult.AddMessage("Currently this control evaluates PATs for all the organizations the user has access to.")
        try
        {
            $apiURL = "https://vssps.dev.azure.com/{0}/_apis/Token/SessionTokens?displayFilterOption=1&createdByOption=3&sortByOption=3&isSortAscending=false&startRowNumber=1&pageSize=100&api-version=5.0-preview.1" -f $($this.OrganizationContext.OrganizationName);
            $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL);
            if(($null -ne $this.ControlSettings) -and [Helpers]::CheckMember($this.ControlSettings, "CriticalPATPermissions"))
            {
                $patterns = $this.ControlSettings.CriticalPATPermissions
                if ($responseObj.Count -gt 0)
                {
                    $AccessPATList = $responseObj | Where-Object { $_.validto -gt $(Get-Date -Format "yyyy-MM-dd") }
                    $AccessPATListCount = ($AccessPATList | Measure-Object).Count
                    if ($AccessPATListCount -gt 0)
                    {
                        $fullAccessPATList = $AccessPATList | Where-Object { $_.scope -eq "app_token" }
                        $customAccessPATList = $AccessPATList | Where-Object { $_.scope -ne "app_token" }
                        $fullAccessPATListCount = ($fullAccessPATList | Measure-Object).Count
                        $PATWithCriticalAccess = @();
                        if(($patterns | Measure-Object).Count -gt 0)
                        {
                            $controlResult.AddMessage("`nNote: The following permission scopes are considered as 'critical': `n`t[$($patterns -join ', ')]");
                            foreach ($pat in $customAccessPATList) 
                            {
                                foreach ($item in $patterns)
                                {
                                    if($pat.scope.contains($item))
                                    {
                                        $PATWithCriticalAccess += $pat
                                        break;
                                    }
                                }
                            }
                        }
                        $PATWithCriticalAccessCount = ($PATWithCriticalAccess | Measure-Object).Count
                        if (($PATWithCriticalAccessCount -gt 0) -or ($fullAccessPATListCount -gt 0))
                        {
                            $controlResult.AddMessage([VerificationResult]::Failed, "`nUser has PATs that are configured with critical permissions.");
                            if ($PATWithCriticalAccessCount -gt 0)
                            {
                                $controlResult.AddMessage("`nTotal number of PATs configured with critical permissions: $($PATWithCriticalAccessCount)");                        
                                $controlResult.AdditionalInfo += "Total number of PATs configured with critical permissions: " + $PATWithCriticalAccessCount;
                                $criticalPAT = $PATWithCriticalAccess | Select-Object displayName, scope 
                                $controlResult.AddMessage("List of PATs configured with critical permissions: ", $criticalPAT);
                            }
                            if ($fullAccessPATListCount -gt 0)
                            {
                                $controlResult.AddMessage([VerificationResult]::Failed, "`nTotal number of PATs configured with full access: $($fullAccessPATListCount)");                        
                                $controlResult.AdditionalInfo += "Total number of PATs configured with full access: " + $fullAccessPATListCount;
                                $fullAccessPAT = $fullAccessPATList | Select-Object displayName, scope 
                                $controlResult.AddMessage("List of PATs configured with full access: ", $fullAccessPAT);
                            }
                        }
                        else
                        {
                            $controlResult.AddMessage([VerificationResult]::Passed, "No PATs are configured with critical permissions.");
                            $controlResult.AdditionalInfo += "No PATs are configured with critical permissionss.";
                        }
                    }
                    else
                    {
                        $controlResult.AddMessage([VerificationResult]::Passed, "No active PATs found.");
                    }
                }
                else
                {
                    $controlResult.AddMessage([VerificationResult]::Passed, "No PATs found.");
                }
            }
            else {
                $controlResult.AddMessage([VerificationResult]::Manual, "Critical permission scopes for PAT are not defined in your organization.");
            }      
        }
        catch
        {
            $controlResult.AddMessage([VerificationResult]::Error, "Could not fetch the list of PATs.");
            $controlResult.LogException($_)
        }
        
        return $controlResult;
    }

}
# SIG # Begin signature block
# MIInoAYJKoZIhvcNAQcCoIInkTCCJ40CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCtWC76D9V/3Ecc
# DlIRztw4fp1oWQ9YtOxj35pNs54Cl6CCDYEwggX/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/BvW1taslScxMNelDNMYIZdTCCGXECAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgaDl7n3L8
# 1eP918lQTxbd+faUZ+mXwUVMANpGZojVm5kwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQAYTQYZg21LriKw92FoZqdq8Awfx9x+QieHlGp0hIWS
# PMVrbi6gioLEbSmJmHASby36Lye+QYGxf31S6xhC0pVfgd+UVxg5GWCXKXKKQEZ9
# NScEBFlq8/Jg7u1kPstaC+GRXvL33tHJteGgoirgPzTeWkzkzNR63pfxUyqNGVd/
# iTschqRqUCa+0U3UkyO76q460AjBGzGlN8FkQgmfDnbil0bDiHk2Xf3P0DEt+DA1
# R2Dla1/kjkeWFYu8CFf0ysK5SPcwKbGmbiPgzbmlS+3+EocLDM+1QYyRZCj1zHuy
# QGq5R7amUxTqPIjofchywcVU+joNI00RBfZKoeQaoDNjoYIW/zCCFvsGCisGAQQB
# gjcDAwExghbrMIIW5wYJKoZIhvcNAQcCoIIW2DCCFtQCAQMxDzANBglghkgBZQME
# AgEFADCCAVAGCyqGSIb3DQEJEAEEoIIBPwSCATswggE3AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIHQr5leYImj+JtkePQNYhPweshCfHlPSem/h2+C+
# dOfHAgZiFl9AyN0YEjIwMjIwMzE1MDgzNTE0LjQ4WjAEgAIB9KCB0KSBzTCByjEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWlj
# cm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBF
# U046RTVBNi1FMjdDLTU5MkUxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFNlcnZpY2WgghFXMIIHDDCCBPSgAwIBAgITMwAAAZW3/A3W4zcxJQABAAABlTAN
# BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0y
# MTEyMDIxOTA1MTJaFw0yMzAyMjgxOTA1MTJaMIHKMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP
# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpFNUE2LUUyN0MtNTky
# RTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ9tQQxntks7P1qhEJ4kviGFP1DwlkHb
# FpWUw0K3dvCFxMjkYs+u3Z73cMCyaWo7PDVwWI8+DpLmwsJfPstttRCkuFrxLi/a
# pxwy1OiQRoNBL5AkSucCyXpVKZG8DLSeWP4L89pm4tvc7NjQBHDtR4JkunJY88f6
# Tkx1iPo1QNM2hepvNAcK4+z5+AiiujnLcMeg7TvuDoivZMcjHXJ9UUS3nMNwU85g
# yDjIGLgDpdzeGb21nrDzj2cG9UrCblgAt8ffL9/efguc3rVvXDMDHdkJmN/XdQpu
# kTunoNgmsdEH/6nAWMb31PAcfq5fMN5lPr+vqofsAAHCfx+lhzVOaV4VjxhG5XPO
# On1WQ8dXxXO/MsvtAraS155csv9jiW+MvqHPI6YT7UtUPeURtiGjXMK34XttT4Wm
# PIF9MLiL/Aeym1vbXxiVuRC3WLUHqWWYnBUXAItfuDFDjxAgZRpwzLySnX7NzNj5
# LGWloSA2ZCR9zWto+H3Lmwxrpfjz7HQrsHw6oOhdxOIQIiMl63HC24GVCx4nTkdF
# +Kx+AWbT2Qbu90cSjc1tS4wwEWKRzhug31R+bSJSGr8m2pXQrCu/0K/drIOB03AR
# aIvZrrkicRZKlFNh+wJDTd6oSHkDevBX8p9QVyK34Os/71VwOmNZGwKiRm/i2Cfm
# oBc0y0drw2KpAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUq5fTYgIUV1eCtwIGYMl8
# fm/8qRcwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYDVR0fBFgw
# VjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWlj
# cm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwGCCsGAQUF
# BwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgx
# KS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG
# 9w0BAQsFAAOCAgEA4LM23h8n6M69C6rQi2ffshmtg0EazACL4gAUzdgYr/AZCUSd
# yCOY0G5pz3lbZ8AvrG0VV8x+R6pIswuqiJ1WxT0GbgMQGNpY05P25f+1xiIlJ8VA
# zSsNuuXxXiczzxFkXnob+olb2Dl0io5KiKbMpS39DtYfpUHJbSxqvnAa+Ci8reoV
# p3ApKHNFhwSpOQcfbOKnl7veN7M8fHb61piokbnEnN0MStnWcyLFGNoezcqlyyZl
# i7GwhF8Fg4m8AUbKZMZG/k+7Cw2mz0RyHUBqyrzgf9j/zE3cZCPg/cyIOfyLNQEM
# K5ch8diTf1uqdoCYVtSIJvL5Zam7N2TigMrP+xbCueyhDva4QZUQ3v6TLD34dKjm
# LyXxmDViaP21SAOlVQaMB26gvIdDteqScqZL2QlIEqTiiQQODQh3ot4otDAfV7hp
# V5PJRjBwFffCDukslBa9HudrZIau2X/bdgZBO52ZY6vKHH2WdTsoEZX9o2/PS1Ol
# yy5ywr5xkUoMSRYH+hQVWu3K6fo0Pmlhk2PQKBG6nmCtUAKr8CBv4Q4YsIP7MS0Y
# 2ini18q+xhvrjbns0n1esweCkKJvvpZPfhE+YIEHLEtSQfEernMLJg27QgVcC3UB
# WJzDXgz5zMtghUzs07JWkV1wHUH0yImKTul5KKLRdNF2Xn9X8qxxNoIEXPcwggdx
# MIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGI
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylN
# aWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5
# MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
# QSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciEL
# eaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa
# 4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxR
# MTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEByd
# Uv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi9
# 47SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJi
# ss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+
# /NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY
# 7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtco
# dgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH
# 29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94
# q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcV
# AQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0G
# A1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQB
# gjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v
# cGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgw
# GQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB
# /wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0f
# BE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJv
# ZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4w
# TDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0
# cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIB
# AJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRs
# fNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6
# Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveV
# tihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKB
# GUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoy
# GtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQE
# cb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFU
# a2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+
# k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0
# +CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cir
# Ooo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYICzjCCAjcCAQEwgfih
# gdCkgc0wgcoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAj
# BgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRo
# YWxlcyBUU1MgRVNOOkU1QTYtRTI3Qy01OTJFMSUwIwYDVQQDExxNaWNyb3NvZnQg
# VGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDRj4LIt7MaBUdYU2Yo
# jUu4T+Fjq6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0G
# CSqGSIb3DQEBBQUAAgUA5dqSeTAiGA8yMDIyMDMxNTEyMjAwOVoYDzIwMjIwMzE2
# MTIyMDA5WjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDl2pJ5AgEAMAoCAQACAhv9
# AgH/MAcCAQACAhHCMAoCBQDl2+P5AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisG
# AQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQAD
# gYEAcpBRRjTIUWrJf+lsarUIqNykfTCipRDxNeV4yBbVxv+TO445z089hV4RZNTB
# klMhqaEU4pyEmLat4TJfex5c2GYqzDj+euq11Nkw30tg06eOwnh/fLiAuW5YPhLg
# fs5xRPSQpPgM+zafNfqS1aH/AlL/DGgbV6nS1ozh23gLV4IxggQNMIIECQIBATCB
# kzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAZW3/A3W4zcxJQAB
# AAABlTANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJ
# EAEEMC8GCSqGSIb3DQEJBDEiBCDLRpi+LNvgm+I3xMudgGW8udA3FBwMnQ5+qB3L
# UArH1DCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIFzmS+GNkAt7aaEjP9B3
# uR5U6YD9wLV3MplPjJssSQLHMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTACEzMAAAGVt/wN1uM3MSUAAQAAAZUwIgQgJkaInWqDvjnyZKwUoUV6
# aCXh7Hqmjso6x/07EovrLtAwDQYJKoZIhvcNAQELBQAEggIAKBACGlE9B5VAKGON
# V98dvZ+lgts5N5a7iMLu2gBN1+cgMofnq/kxSX7TJrbZWE+TANJBrbL7cCznJb62
# f2y8vzEjiO0LZ6ntHnUkC4eu3uBO4FWNb8opLpgz3juwLuggFZF6eJLWKFovuNAC
# EzqnT/I+0Dy0s9AAaC5KnSETCd9ekkuHoHQ4pHmUGQDIxKWgVWpsQV0sRZl/ryZv
# evqw+X5HgsHIus3iT9ADu/DxMRc8J9vEO57nsipAYzTml2RY0CkkKclN2ZMeaqu1
# XwesGdemIDqqAZY2oahkVrHcTT3SwuU56AnLRFq3bkWmO5goWJu2eXdNBBXYtLLM
# d/7AmPCbQ4XugNxb53Ssc4qnDAdnqWibOdOq2VsqU4PzkBVAsrcRiA9mDuWPPin6
# Ii9Rlxr74jVcvwXTWxuhRiMJwU1a5VDoPyfpOZlFLnn7MEphFCp5xvAdxOyFNpKs
# 2iYS0tsCru2FZiBbNb1ooCRH30U08E07/tOVbnhMCsb9PdN2fmRVSnu5nIWQtX/7
# n0+SX/4KlWe+5CyRCySyGQf3am+vh8c0xdPxMDZzE4deaJHV0KxEPKpekXhKCgvn
# COZfsPgIgsBHujY0B6fGgQLUn90r1ZTbFHvA43uhS4LX2drZi5Vzp7WH+oNjzgfA
# sLcja+wC7AMqMNdtB9GhNC/Samc=
# SIG # End signature block