Framework/Models/AzSKConfig.ps1

Set-StrictMode -Version Latest
class AzSKConfig
{
    [string] $MaintenanceMessage
    [string] $AzSKRGName
    [string] $AzSKRepoURL
    [string] $AzSKServerVersion
    [string[]] $SubscriptionMandatoryTags = @()
    [string] $ERvNetResourceGroupNames
    [string] $UpdateCompatibleCCVersion
    [string] $AzSKApiBaseURL;
    [bool] $PublishVulnDataToApi;
    [string] $ControlTelemetryKey;
    [bool] $EnableControlTelemetry;
    [string] $PolicyMessage;
    [string] $AzSKLocation;
    [string] $InstallationCommand;
    [string] $PublicPSGalleryUrl;
    [string] $AzSKCARunbookVersion;
    [string] $AzSKCAMinReqdRunbookVersion;
    [string] $AzSKAlertsMinReqdVersion;
    [string] $AzSKARMPolMinReqdVersion;
    [string[]] $PrivacyAcceptedSources = @();
    [string] $OutputFolderPath;
    [int] $BackwardCompatibleVersionCount;
    [string[]] $DefaultControlExculdeTags = @()
    [string[]] $DefaultControlFiltersTags = @()
    [System.Version[]] $AzSKVersionList = @()
    [int] $CAScanIntervalInHours;
    [string] $ConfigSchemaBaseVersion;
    [string] $AzSKASCMinReqdVersion;
    #Bool flag to check selfsigned cert to avoid break of current configurations
    [bool] $AllowSelfSignedWebhookCertificate;
    [bool] $EnableDevOpsKitSetupCheck;
    [bool] $UpdateToLatestVersion;
    [string] $CASetupRunbookURL;
    [string] $AzSKConfigURL;
    [bool] $IsAlertMonitoringEnabled;
    [string] $SupportDL;
    [string] $RunbookScanAgentBaseVersion;
    [string] $PolicyOrgName;
    [bool] $StoreComplianceSummaryInUserSubscriptions;
    [string] $LatestPSGalleryVersion;
    [string] $SchemaTemplateURL;
    [bool] $EnableAzurePolicyBasedScan;
    [string] $AzSKInitiativeName;
    hidden static [AzSKConfig] $Instance = $null;
    
    static [AzSKConfig] GetInstance([bool] $useOnlinePolicyStore, [string] $onlineStoreUri, [bool] $enableAADAuthForOnlinePolicyStore)
    {
        if ( $null -eq  [AzSKConfig]::Instance)
        {
            [AzSKConfig]::Instance = [AzSKConfig]::LoadRootConfiguration($useOnlinePolicyStore,$onlineStoreUri,$enableAADAuthForOnlinePolicyStore)
        }
        if(-not ([string]::IsNullOrWhiteSpace([AzSKConfig]::Instance.AzSKServerVersion)))
        {
            [AzSKConfig]::Instance.MaintenanceMessage = ([AzSKConfig]::Instance.MaintenanceMessage -f [AzSKConfig]::Instance.AzSKServerVersion);       
        }
        return [AzSKConfig]::Instance
    }

    hidden static [AzSKConfig] LoadRootConfiguration([bool] $useOnlinePolicyStore, [string] $onlineStoreUri, [bool] $enableAADAuthForOnlinePolicyStore)
    {
        #Config filename will be static constant
        return [AzSKConfig] ([ConfigurationHelper]::LoadServerConfigFile("AzSK.json", $useOnlinePolicyStore, $onlineStoreUri, $enableAADAuthForOnlinePolicyStore));
    }

    hidden  [string] GetLatestAzSKVersion([string] $moduleName)
    {
        if([string]::IsNullOrWhiteSpace($this.AzSKServerVersion))
        {
            $this.AzSKServerVersion = "0.0.0.0";
            try
            {
                    
                if((-not [string]::IsNullOrWhiteSpace($this.AzSKConfigURL)) -and (-not $this.UpdateToLatestVersion))
                {
                    try
                    {
                        $serverFileContent = [ConfigurationHelper]::InvokeControlsAPI($this.AzSKConfigURL, '', '', '');
                        if($null -ne $serverFileContent)
                        {
                            if(-not [string]::IsNullOrWhiteSpace($serverFileContent.CurrentVersionForOrg))
                            {
                                $this.AzSKServerVersion = $serverFileContent.CurrentVersionForOrg
                            }
                        }
                    }
                    catch
                    {
                        # If unable to fetch server config file or module version property then continue and download latest version module.
                    }
                }

                if($this.AzSKServerVersion -eq '0.0.0.0')
                {
                    $repoUrl = $this.AzSKRepoURL;
                    #Searching for the module in the repo
                    $Url = "$repoUrl/api/v2/Search()?`$filter=IsLatestVersion&searchTerm=%27$moduleName%27&includePrerelease=false" 
                    [System.Uri] $validatedUri = $null;
                    if([System.Uri]::TryCreate($Url, [System.UriKind]::Absolute, [ref] $validatedUri))
                    {
                        $SearchResult = @()
                        $SearchResult += Invoke-RestMethod -Method Get -Uri $validatedUri -UseBasicParsing
                        if($SearchResult.Length -and $SearchResult.Length -gt 0) 
                        {
                                #filter latest module
                                $SearchResult = $SearchResult | Where-Object -FilterScript {
                                    return $_.title.'#text' -eq $moduleName
                                } 
                                $moduleName = $SearchResult.title.'#text' # get correct casing for the module name
                                $PackageDetails = Invoke-RestMethod -Method Get -UseBasicParsing -Uri $SearchResult.id 
                                $this.AzSKServerVersion = $PackageDetails.entry.properties.version
                        }
                    }
                }
            }
            catch
            {
                $this.AzSKServerVersion = "0.0.0.0";
            }
        }
        return $this.AzSKServerVersion;
    }

    #Function to get list of AzSK version using API
    hidden [System.Version[]] GetAzSKVersionList([string] $moduleName)
    {
        if(($this.AzSKVersionList | Measure-Object).Count -eq 0)
        {
            try
            {
                $repoUrl = $this.AzSKRepoURL;
                #Searching for the module in the repo
                $Url = "$repoUrl/api/v2/FindPackagesById()?id='$moduleName'&`$skip=0&`$top=40&`$orderby=Version desc" 
                [System.Uri] $validatedUri = $null;
                if([System.Uri]::TryCreate($Url, [System.UriKind]::Absolute, [ref] $validatedUri))
                {                    
                    $searchResult = Invoke-RestMethod -Method Get -Uri $validatedUri -UseBasicParsing
                    $versionList =@()
                    if($searchResult.Length -and $searchResult.Length -gt 0) 
                    {
                        $versionList += $SearchResult | Where-Object {$_.title.'#text' -eq $ModuleName
                        } | ForEach-Object {[System.Version] $_.properties.version }                                            
                        $this.AzSKVersionList = $versionList
                    }
                }
            }
            catch
            {
                $this.AzSKVersionList = @();
            }
        }
        return $this.AzSKVersionList;
    }
    
    hidden [string] GetAzSKLatestPSGalleryVersion([string] $moduleName)
    {
        if([string]::IsNullOrWhiteSpace($this.LatestPSGalleryVersion))
        {
            $this.LatestPSGalleryVersion = "0.0.0.0";
            try
            {
                if($this.LatestPSGalleryVersion -eq '0.0.0.0')
                {
                    $repoUrl = $this.AzSKRepoURL;
                    #Searching for the module in the repo
                    $Url = "$repoUrl/api/v2/Search()?`$filter=IsLatestVersion&searchTerm=%27$moduleName%27&includePrerelease=false" 
                    [System.Uri] $validatedUri = $null;
                    if([System.Uri]::TryCreate($Url, [System.UriKind]::Absolute, [ref] $validatedUri))
                    {
                        $SearchResult = @()
                        $SearchResult += Invoke-RestMethod -Method Get -Uri $validatedUri -UseBasicParsing
                        if($SearchResult.Length -and $SearchResult.Length -gt 0) 
                        {
                                #filter latest module
                                $SearchResult = $SearchResult | Where-Object -FilterScript {
                                    return $_.title.'#text' -eq $moduleName
                                } 
                                $moduleName = $SearchResult.title.'#text' # get correct casing for the module name
                                $PackageDetails = Invoke-RestMethod -Method Get -UseBasicParsing -Uri $SearchResult.id 
                                $this.LatestPSGalleryVersion = $PackageDetails.entry.properties.version
                        }
                    }
                }
            }
            catch
            {
                $this.LatestPSGalleryVersion = "0.0.0.0";
            }
        }
        return $this.LatestPSGalleryVersion;

    }
}

# SIG # Begin signature block
# MIIjiQYJKoZIhvcNAQcCoIIjejCCI3YCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAA3mYHqOiDnJ7w
# 24+fxa+6qHDLj31OAUhdlyn9V9WD26CCDYUwggYDMIID66ADAgECAhMzAAABiK9S
# 1rmSbej5AAAAAAGIMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ4WhcNMjEwMzAzMTgzOTQ4WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQCSCNryE+Cewy2m4t/a74wZ7C9YTwv1PyC4BvM/kSWPNs8n0RTe+FvYfU+E9uf0
# t7nYlAzHjK+plif2BhD+NgdhIUQ8sVwWO39tjvQRHjP2//vSvIfmmkRoML1Ihnjs
# 9kQiZQzYRDYYRp9xSQYmRwQjk5hl8/U7RgOiQDitVHaU7BT1MI92lfZRuIIDDYBd
# vXtbclYJMVOwqZtv0O9zQCret6R+fRSGaDNfEEpcILL+D7RV3M4uaJE4Ta6KAOdv
# V+MVaJp1YXFTZPKtpjHO6d9pHQPZiG7NdC6QbnRGmsa48uNQrb6AfmLKDI1Lp31W
# MogTaX5tZf+CZT9PSuvjOCLNAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUj9RJL9zNrPcL10RZdMQIXZN7MG8w
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ1ODM4NjAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# ACnXo8hjp7FeT+H6iQlV3CcGnkSbFvIpKYafgzYCFo3UHY1VHYJVb5jHEO8oG26Q
# qBELmak6MTI+ra3WKMTGhE1sEIlowTcp4IAs8a5wpCh6Vf4Z/bAtIppP3p3gXk2X
# 8UXTc+WxjQYsDkFiSzo/OBa5hkdW1g4EpO43l9mjToBdqEPtIXsZ7Hi1/6y4gK0P
# mMiwG8LMpSn0n/oSHGjrUNBgHJPxgs63Slf58QGBznuXiRaXmfTUDdrvhRocdxIM
# i8nXQwWACMiQzJSRzBP5S2wUq7nMAqjaTbeXhJqD2SFVHdUYlKruvtPSwbnqSRWT
# GI8s4FEXt+TL3w5JnwVZmZkUFoioQDMMjFyaKurdJ6pnzbr1h6QW0R97fWc8xEIz
# LIOiU2rjwWAtlQqFO8KNiykjYGyEf5LyAJKAO+rJd9fsYR+VBauIEQoYmjnUbTXM
# SY2Lf5KMluWlDOGVh8q6XjmBccpaT+8tCfxpaVYPi1ncnwTwaPQvVq8RjWDRB7Pa
# 8ruHgj2HJFi69+hcq7mWx5nTUtzzFa7RSZfE5a1a5AuBmGNRr7f8cNfa01+tiWjV
# Kk1a+gJUBSP0sIxecFbVSXTZ7bqeal45XSDIisZBkWb+83TbXdTGMDSUFKTAdtC+
# r35GfsN8QVy59Hb5ZYzAXczhgRmk7NyE6jD0Ym5TKiW5MIIHejCCBWKgAwIBAgIK
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCFVowghVWAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAGIr1LWuZJt6PkAAAAA
# AYgwDQYJYIZIAWUDBAIBBQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIPzV
# z2Y8EVaNt10WS9SIs8NDVzQ1+JtovctHRtVBsm12MEQGCisGAQQBgjcCAQwxNjA0
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQu
# Y29tIDANBgkqhkiG9w0BAQEFAASCAQAlvH8Vd2VESTi+skNXlg0s5nYOtFw4G0fh
# RzncL4qtZkTYOZTUgqQjQbKPtGiSRYq3VKUfqSwAI/Htj1wtnxtPViue/dBL63IC
# omyMPbuzZJ9FexAtfYcK951exHgULkSFlkfc49gP9Uq8RQ2o8MtW+b8gOqMP5Bar
# X7nXy+/m12Gu4OFK3QNc6AIULQQYnMBxaUYJnbzUzra0HCmL2G2XdCAOWnJmLibn
# IXMkWEqCizdn5vPdYykwkkS3Cz/DWE3/29EkVixnBF99xB/GERMOEWgFQWiJFC58
# DAmBcmERZAie1V0/ReKjdAj/F3kF5RCs+KvC62y4IUX4wXXRoUVJoYIS4jCCEt4G
# CisGAQQBgjcDAwExghLOMIISygYJKoZIhvcNAQcCoIISuzCCErcCAQMxDzANBglg
# hkgBZQMEAgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEE
# AYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIGdk4cRPbFIs+3CtJFmTXubTNxDeXD4T
# JO6VlY6L7es3AgZf2MfB4CEYEzIwMjEwMTE1MDkxNDE2LjQxNlowBIACAfSggdCk
# gc0wgcoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNV
# BAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxl
# cyBUU1MgRVNOOkQ2QkQtRTNFNy0xNjg1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBTZXJ2aWNloIIOOTCCBPEwggPZoAMCAQICEzMAAAFQWKLUp5sLMOsA
# AAAAAVAwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTAwHhcNMjAxMTEyMTgyNjAzWhcNMjIwMjExMTgyNjAzWjCByjELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFt
# ZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046RDZCRC1F
# M0U3LTE2ODUxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw
# ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnen+UeypZwycbVpoN8zNS
# AqnZl40+RjRTx17gsPvVYNxvPe6PzruS/J5X2mON6BRt+XaJATJJvkCgHvViJqrU
# 7Q39T0qTf02fOTTzkBR1zhB2ihL3XSaEpRE/L2wSa7vgL8jhPFi0dZ8nnqcj96bV
# LaRvPs7ANXeDF3xpZNgUSKL2EegBcmRUse+92uWk/NYsj8Y3ECv2qPnSCNESqdQ9
# 7JS4K3R5PzHSCG2xYvRRLp+b90FVI2JCQr1IAj92UNke2wKHbQs5VdyJE+/vgg6t
# yZdaxW7AVojIq5KcfM3+QahNKpsdOHm37IwYmD1LfTsb0tVhXLjbh7o4T6cCKiWb
# AgMBAAGjggEbMIIBFzAdBgNVHQ4EFgQUglUZHxlF261kL0PBAEM7t+ufRX4wHwYD
# VR0jBBgwFoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZF
# aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGlt
# U3RhUENBXzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcw
# AoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQ
# Q0FfMjAxMC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEF
# BQcDCDANBgkqhkiG9w0BAQsFAAOCAQEAUT9odHKO/uPj08AeL5P2HixMOqHK3oPk
# 9JAdmlgf2Xt8xF7Y9BHiFQNWYMKd/HI2ryYOu3SAAs3txZaRpalvY0R16WWIQzC9
# G9oqSD7QNN0RMxsiiCMM65/nq9xSPIrmYh6aTXFgIMuh4GLNk7gMQFybUbg2ZlLZ
# sn9r5RzxX/x8aK17ggEWKmiij1lgb/6AE+bAPUuEyy50ua6U9Zs0+bi8/HvnZs6P
# iMwGhtXz/sRrZaAYjbLvaCXOk+DbRvHBoYHQQm35QrPUIfiNcw30giIMRy7xYHji
# ml/IxakMFUJ56mLE3SvnbSGxaKwppPlkIsw5HhemdSGHs5SlrQTbXjCCBnEwggRZ
# oAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290
# IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1
# MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0G
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ
# 1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP
# 8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRh
# Z5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39
# dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2
# iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGj
# ggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xG
# G8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGG
# MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186a
# GMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsG
# AQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB
# /wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUF
# BwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0A
# ZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFv
# s+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5
# U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFS
# AK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1V
# ry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6
# f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35j
# WSUPei45V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHa
# sFAeb73x4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLN
# HfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4
# sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHX
# odLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUe
# CLraNtvTX4/edIhJEqGCAsswggI0AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpENkJELUUz
# RTctMTY4NTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIj
# CgEBMAcGBSsOAwIaAxUAIw17n3LxNWtGEZtallmkMZYeoBKggYMwgYCkfjB8MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOOre4Qw
# IhgPMjAyMTAxMTUxMDI1MDhaGA8yMDIxMDExNjEwMjUwOFowdDA6BgorBgEEAYRZ
# CgQBMSwwKjAKAgUA46t7hAIBADAHAgEAAgISgjAHAgEAAgIRoDAKAgUA46zNBAIB
# ADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQow
# CAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAIsCRVtyFXjhpkkNQBVnzYYy+ESd
# bQ4gQMyMOhy30vv+S8UwCwvgPbkOrPd7ULrjg5o2TImM+3RVUkTbhQLGXlfYF6pC
# VK+NxaTFOHXo7aRdS7wUkdsnRtAHensTKh/mMI22fb1vV17Key0Sq+fTqt0TKNHH
# I6Iwa7+tgx05ntikMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTACEzMAAAFQWKLUp5sLMOsAAAAAAVAwDQYJYIZIAWUDBAIBBQCgggFK
# MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgTT2t
# 59ojLGFGdG9wOxlRPGwBz24LfM5wGEO/7ampzyswgfoGCyqGSIb3DQEJEAIvMYHq
# MIHnMIHkMIG9BCBs9D6fL5rCThgXJmGIhdXS6IY1Zg6op47dkKJ8L/Kj9jCBmDCB
# gKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV
# BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABUFii1KebCzDr
# AAAAAAFQMCIEIBTBWX29areo5ixUMOm4i/bgfj2dEjbQJ8gdP5OkDWddMA0GCSqG
# SIb3DQEBCwUABIIBAMDebXBBiZ0NR05bYAAAEjdkd23aipJiTEuCqCAZBV89h5uQ
# rmSOzK9LWsLSxgdhSezLwFPJaE9VIvcW7veOUBXQ9kmST9QPxdJN1/JskJX+r7mF
# V0TsvU85CQaq9fgp9D9M2SgNuUdYCjlKhzGa4d1GxAdVqcwYpATLhzaE9HE/V0R0
# fYqGNtrJjuXGbDIwkeQ4hqLnpQtSQqksMkjCdt42Vx+TUYylNHaSzAqUEIc4LI5p
# nNNuG7YuiryD62vKTyPWUIYeTiu2FgCqDGARttRD7iGzaak3v8jOH12484KVP/nl
# biVfju43QI4+SaS9cyYs8DgkmeQP12oGnHBh4b0=
# SIG # End signature block