Test-MsIdCBACertificateAuthorityConfiguration.ps1

<#
.SYNOPSIS
    Test & report for common mis-configuration issues with the Entra ID Certificate Trust Store

.INPUTS
    None
.NOTES
    This Powershell cmdlet require Windows command line utility Certutil. This cmdlet can only be run from Windows device.
    
    Since the CRL Distribution Point (CDP) needs to be accessible to Entra ID. It is best to run this script from outside
    a corporate network on an internet connected Windows device.
.EXAMPLE
    Test-MsIdEntraIDCertificateTrustStoreConfiguration
.LINK
    https://aka.ms/aadcba

#>

function Test-MsIdEntraIDCertificateTrustStoreConfiguration {

    begin {
            ## Due to Certutil Dependency will only run on Windows.
            Try
            {
            certutil /? | Out-Null
            }
            Catch
            {
            Write-Host Certutil not found. This cmdlet can only run on Windows -ForegroundColor Red
            Break
            }
        }

    process {
# Get Org Info
$OrgInfo = Get-MgOrganization

# Get the list of trusted certificate authorities
$trustedCAs = (Get-MgOrganizationCertificateBasedAuthConfiguration -OrganizationId $OrgInfo.Id).CertificateAuthorities

# Loop through each trusted CA
$CompletedResult = @()
foreach ($ca in $trustedCAs) {
    $crlDLTime = $null
    $crldump = $Null
    $crlAKI = $Null
    $crlTU = $Null
    $crlNU = $null    

    Write-Host "Processing $($ca.Issuer)"
    ### High Level Check for correctly formatted CDP URL
    Write-Host " CertificateRevocationListUrl Format Validation Test"
    If($ca.CertificateRevocationListUrl)
    {
    $pattern = '^http:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])\/[^\/]+\.[^\/]+$'
    $crlURLCheckPass = $false
    if ($ca.CertificateRevocationListUrl -match $pattern) {
        Write-Host " Passed" -ForegroundColor Green
        $crlURLCheckPass = $true
    } elseif ($ca.CertificateRevocationListUrl -match '^https:\/\/') {
        Write-Host " HTTPS is not allowed" -ForegroundColor Red
    } else {
        Write-Host " Invalid CDP URL" -ForegroundColor Red
    }
    If(!$crlURLCheckPass)
    {
     ## THis needs to be corrected before other checks
     Write-Host " This CA CDP needs to be corrected. Additional checks for this CA are not processed" -ForegroundColor Red
     Continue
    }
    }

    $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($ca.Certificate)

    $objresult = New-Object System.Object
    $objresult | Add-Member -type NoteProperty -name NotAfter -value $cert.NotAfter
    $objresult | Add-Member -type NoteProperty -name NotBefore -value $cert.NotBefore
    $objresult | Add-Member -type NoteProperty -name Subject -value $cert.Subject
    $objresult | Add-Member -type NoteProperty -name Issuer -value $cert.Issuer
    $objresult | Add-Member -type NoteProperty -name Thumbprint -value $cert.Thumbprint

    ForEach($Extension in $Cert.Extensions) {
        Switch($Extension.Oid.FriendlyName) {
            "Authority Key Identifier" {$objresult | Add-Member -type NoteProperty -name Authority-Key-Identifier -value ($Extension.Format($false)).trimstart("KeyID=")}
            "Subject Key Identifier"   {$objresult | Add-Member -type NoteProperty -name Subject-Key-Identifier -value $Extension.Format($false)}
        } ##Switch
    }## ForEach Extension

    $FullCert = $objresult
    $CompletedResult += $objresult

    # Check the Time validity of the certificate
    $now = Get-Date
    Write-Host " Certificate Time Validity Test"
    if ($now -lt $FullCert.NotBefore -or $now -gt $FullCert.NotAfter) {
        Write-Host " Certificate for $($cert.Subject) is not yet valid or expired" -ForegroundColor Red
        continue
    } Else {
        Write-Host " Passed" -ForegroundColor Green
    }

    # Download the CRL
    $TempDir = [System.IO.Path]::GetTempPath()
    
    If($ca.CertificateRevocationListUrl) {
       Try {
            $crlDLTime = Measure-Command {Invoke-WebRequest -Uri $ca.CertificateRevocationListUrl -OutFile ($TempDir + "crl.crl")}              
        } Catch {}    

        # Check if the CRL was downloaded successfully
        Write-Host " CRL Download & Latency Test"
        if ($null -eq $crlDLTime) {
            Write-Host " Failed to download CRL for $($cert.Subject)" -ForegroundColor Red
            continue
        } Else {     
            if($crlDLTime.TotalSeconds -gt 12) {
                Write-Host " Slow CRL Download (>12 Seconds) for $($cert.Subject)" -ForegroundColor Red
            } Else {
                Write-Host " CRL Download successful for $($cert.Subject)" -ForegroundColor Green
            }
        }
    } Else {
        Write-Host $cert.Subject is not configured with a CRL - Entra ID will not perform CRL check for this CA -ForegroundColor Yellow
        Continue
    }   

    ## Check CRL Size
    Write-Host " CRL Size Test"
    $File = Get-ChildItem ($TempDir + "crl.crl")
    $FileMB = [math]::Round($File.Length/1MB,0)
    if($FileMB -gt 44) {
        Write-Host " CRL is Large - $($FileMB) MB- Users may see intermittent Sign-in errors due to sizes above 45" MB -ForegroundColor Red
    } Else {
        If($FileMB -lt 1)
        {
         Write-Host " Passed - CRL is < 1MB" -ForegroundColor Green
        }
        Else
        {
         Write-Host " Passed - CRL is $($FileMB) MB" -ForegroundColor Green
        }
    }

# Validate CA Cert AKI--> SKI Mapping Logic
Write-Host " Certificate Trust Chain Test"
If($null -eq $FullCert.'Authority-Key-Identifier') {
    If($ca.IsRootAuthority) {
        Write-Host " CA is configured as a Root Authority --> No Parent Issuer expected in store"
    } Else {
        Write-Host " CA is not configured as a Root CA but certificate does not contain Authority Key Identifier(AKI) --> This is unexpected" -ForegroundColor Red
    }
} ## Close Without AKI
Else {
    Write-Host " Expected Issuer Subject Key Identifier (SKI) : $($FullCert.'Authority-Key-Identifier')"
    If(!$ca.IsRootAuthority) {
        If($FullCert.'Authority-Key-Identifier' -eq $FullCert.'Subject-Key-Identifier') {
            Write-Host " CA Authority Key Identifier (AKI) and Subject Key Identifier(SKI) are the same and Cert is not marked as isRootAuthority --> This is unexpected"
        } Else {
            If($trustedCAs.IssuerSKI -notcontains $FullCert.'Authority-Key-Identifier') {
                Write-Host " Certificate issuer $($FullCert.'Authority-Key-Identifier') is not present in the tenant certificate store" -ForegroundColor Red
            } Else {
                Write-Host " Passed" -ForegroundColor Green
            }
        }
    } Else {
        Write-Host " CA is configured as a Root Authority --> No Parent Issuer expected in store"
    }
    }## Close with AKI and the AKI --> SKI Validation Test

    # Dump the CRL file using certutil
    Write-Host " "Running Certutil commands and parsing output *** Can be Slow for Big CRL *** -ForegroundColor White
    $crldump = certutil -dump ($TempDir + "crl.crl")
    # Check for a Next Publish Date in CRLDump and grab before truncating the output for faster processing
        $i = 0
        $crlNP = $Null
    ForEach($Line in $crldump) {
        If ($Line -match "Next CRL Publish") {
            $crlNP = ($crldump[$i+1]).TrimStart(' ') | get-date
            break
        }
        $i++
    }

    ## Shorted CRLDump output for faster parsing
    $i = 0
    ForEach($Line in $crldump) {
        If ($Line -match "CRL Entries:") {
            $crldump = $crldump[0..$i]
            break
        }
        $i++
    }

    $crlAKI = $crldump -match 'KeyID='
    $crlAKI = $crlAKI -replace ' KeyID=',''
    $crlTU = $crldump -match ' ThisUpdate: '
    $crlTU = $crlTU -replace ' ThisUpdate: ','' | get-Date
    $crlNU = $crldump -match ' NextUpdate: '
    $crlNU = $crlNU -replace ' NextUpdate: ','' | get-Date

    # Verify CRL/CERT AKI Match
    If($crlAKI -ne $FullCert.'Subject-Key-Identifier') {
        # Downloaded CRL AKI does not match expected SKI of CA Certificate
        Write-Host " CRL Authority Key Identifier(AKI) Mismatch" -ForegroundColor Red
        Write-Host " CRL AKI : " $crlAKI -ForegroundColor Red
        Write-Host " Expected AKI : " $FullCert.'Subject-Key-Identifier' -ForegroundColor Red

        ## See if the CRL downloaded AKI matches other CA in Store
        If($trustedCAs.IssuerSKI -contains $crlAKI) {
            $MatchedCA = @()
            $MatchedCA = $trustedCAs | Where-Object {$crlAKI -eq $_.IssuerSki}
            If($MatchedCA) {
                Write-Host " Downloaded CRL AKI matches another CA certificate in the trusted store : $($MatchedCA.Issuer)" -ForegroundColor Red
            }
        }
    } Else {
        Write-Host " " Cert SKI matches CRL AKI -ForegroundColor Green
    }

    # Display CRL Lifetime Information
    Write-Host " Additional CRL Information"
    Write-Host " " CRL was Issued on $crlTU
    If($crlNP)
    {
     Write-Host " " CRL nextPublish is $crlNP
    }
    Else
    {
     Write-Host " " CRL does not contain nextPublish date
    }
    Write-Host " " CRL expires on $crlNU
    $TimeLeft = New-TimeSpan -Start $now -End $crlNU
    Write-Host " " CRL is valid for $TimeLeft.Days Days $TimeLeft.Hours Hours
    # TODO Verify the CRL signature
}##ForEach CA
    }
}

# SIG # Begin signature block
# MIIoOAYJKoZIhvcNAQcCoIIoKTCCKCUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDf05gIEB6FT+9N
# zbWocqp8rjiR2a/R733iSchj/+4yUqCCDYUwggYDMIID66ADAgECAhMzAAADTU6R
# phoosHiPAAAAAANNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI4WhcNMjQwMzE0MTg0MzI4WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDUKPcKGVa6cboGQU03ONbUKyl4WpH6Q2Xo9cP3RhXTOa6C6THltd2RfnjlUQG+
# Mwoy93iGmGKEMF/jyO2XdiwMP427j90C/PMY/d5vY31sx+udtbif7GCJ7jJ1vLzd
# j28zV4r0FGG6yEv+tUNelTIsFmmSb0FUiJtU4r5sfCThvg8dI/F9Hh6xMZoVti+k
# bVla+hlG8bf4s00VTw4uAZhjGTFCYFRytKJ3/mteg2qnwvHDOgV7QSdV5dWdd0+x
# zcuG0qgd3oCCAjH8ZmjmowkHUe4dUmbcZfXsgWlOfc6DG7JS+DeJak1DvabamYqH
# g1AUeZ0+skpkwrKwXTFwBRltAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUId2Img2Sp05U6XI04jli2KohL+8w
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMDUxNzAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# ACMET8WuzLrDwexuTUZe9v2xrW8WGUPRQVmyJ1b/BzKYBZ5aU4Qvh5LzZe9jOExD
# YUlKb/Y73lqIIfUcEO/6W3b+7t1P9m9M1xPrZv5cfnSCguooPDq4rQe/iCdNDwHT
# 6XYW6yetxTJMOo4tUDbSS0YiZr7Mab2wkjgNFa0jRFheS9daTS1oJ/z5bNlGinxq
# 2v8azSP/GcH/t8eTrHQfcax3WbPELoGHIbryrSUaOCphsnCNUqUN5FbEMlat5MuY
# 94rGMJnq1IEd6S8ngK6C8E9SWpGEO3NDa0NlAViorpGfI0NYIbdynyOB846aWAjN
# fgThIcdzdWFvAl/6ktWXLETn8u/lYQyWGmul3yz+w06puIPD9p4KPiWBkCesKDHv
# XLrT3BbLZ8dKqSOV8DtzLFAfc9qAsNiG8EoathluJBsbyFbpebadKlErFidAX8KE
# usk8htHqiSkNxydamL/tKfx3V/vDAoQE59ysv4r3pE+zdyfMairvkFNNw7cPn1kH
# Gcww9dFSY2QwAxhMzmoM0G+M+YvBnBu5wjfxNrMRilRbxM6Cj9hKFh0YTwba6M7z
# ntHHpX3d+nabjFm/TnMRROOgIXJzYbzKKaO2g1kWeyG2QtvIR147zlrbQD4X10Ab
# rRg9CpwW7xYxywezj+iNAc+QmFzR94dzJkEPUSCJPsTFMIIHejCCBWKgAwIBAgIK
# 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/Xmfwb1tbWrJUnMTDXpQzTGCGgkwghoFAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAANNTpGmGiiweI8AAAAA
# A00wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIP5k
# Pax0Axim9Er4ZaaWVLTkN10nz5LMoZutQujN/lMvMEIGCisGAQQBgjcCAQwxNDAy
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20wDQYJKoZIhvcNAQEBBQAEggEATdkefeNp2lQBuzCkGZSGwGYjdfvWTFx7dr/W
# pDlb1LbkmnAjtpXXWXEGgD5jZvTeBkL3nGb0WqcsRcjxCwjs4Tvt8l50RIsg/JNb
# ibmXn1i8WMKM8eNPqU4earcs9fU5LxTio69pGHRfAgCoNTd7xUl4zzEQvZF05caV
# JZHw/RPftzATtra5RW8uFETcCHNNhjMwE4yVr6pc+w+4lywaSVLm+v4CBlURoWYO
# PlK9VQs6CiTZmIN44D2JdKpX+Jo7k8o3KxCqUfqXF9QDAwAYo6fpyEdY1Z1JjTE+
# hZLTBLeWL72u3Dj56Lug/ALlNbBuvRQxW6VplV1/V1JZ6QotiqGCF5MwghePBgor
# BgEEAYI3AwMBMYIXfzCCF3sGCSqGSIb3DQEHAqCCF2wwghdoAgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCDQSEhlUHM7hZ3yPGZ72zH1SbHSPYLrT38Q
# 6Kp4jCjfkQIGZVbHQKMSGBMyMDIzMTExNzEwNTQ1NS4xNzNaMASAAgH0oIHRpIHO
# MIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL
# ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk
# IFRTUyBFU046OEQwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFNlcnZpY2WgghHpMIIHIDCCBQigAwIBAgITMwAAAc1VByrnysGZHQAB
# AAABzTANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MDAeFw0yMzA1MjUxOTEyMDVaFw0yNDAyMDExOTEyMDVaMIHLMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046OEQwMC0w
# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDTOCLVS2jmEWOqxzygW7s6
# YLmm29pjvA+Ch6VL7HlTL8yUt3Z0KIzTa2O/Hvr/aJza1qEVklq7NPiOrpBAIz65
# 7LVxwEc4BxJiv6B68a8DQiF6WAFFNaK3WHi7TfxRnqLohgNz7vZPylZQX795r8MQ
# vX56uwjj/R4hXnR7Na4Llu4mWsml/wp6VJqCuxZnu9jX4qaUxngcrfFT7+zvlXCl
# wLah2n0eGKna1dOjOgyK00jYq5vtzr5NZ+qVxqaw9DmEsj9vfqYkfQZry2JO5wmg
# XX79Ox7PLMUfqT4+8w5JkdSMoX32b1D6cDKWRUv5qjiYh4o/a9ehE/KAkUWlSPbb
# DR/aGnPJLAGPy2qA97YCBeeIJjRKURgdPlhE5O46kOju8nYJnIvxbuC2Qp2jxwc6
# rD9M6Pvc8sZIcQ10YKZVYKs94YPSlkhwXwttbRY+jZnQiDm2ZFjH8SPe1I6ERcfe
# YX1zCYjEzdwWcm+fFZmlJA9HQW7ZJAmOECONtfK28EREEE5yzq+T3QMVPhiEfEhg
# cYsh0DeoWiYGsDiKEuS+FElMMyT456+U2ZRa2hbRQ97QcbvaAd6OVQLp3TQqNEu0
# es5Zq0wg2CADf+QKQR/Y6+fGgk9qJNJW3Mu771KthuPlNfKss0B1zh0xa1yN4qC3
# zoE9Uq6T8r7G3/OtSFms4wIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFKGT+aY2aZrB
# AJVIZh5kicokfNWaMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8G
# A1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
# Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBs
# BggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
# MDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBSqG3ppKIU+i/E
# MwwtotoxnKfw0SX/3T16EPbjwsAImWOZ5nLAbatopl8zFY841gb5eiL1j81h4DiE
# iXt+BJgHIA2LIhKhSscd79oMbr631DiEqf9X5LZR3V3KIYstU3K7f5Dk7tbobuHu
# +6fYM/gOx44sgRU7YQ+YTYHvv8k4mMnuiahJRlU/F2vavcHU5uhXi078K4nSRAPn
# WyX7gVi6iVMBBUF4823oPFznEcHup7VNGRtGe1xvnlMd1CuyxctM8d/oqyTsxwlJ
# AM5F/lDxnEWoSzAkad1nWvkaAeMV7+39IpXhuf9G3xbffKiyBnj3cQeiA4SxSwCd
# nx00RBlXS6r9tGDa/o9RS01FOABzKkP5CBDpm4wpKdIU74KtBH2sE5QYYn7liYWZ
# r2f/U+ghTmdOEOPkXEcX81H4dRJU28Tj/gUZdwL81xah8Kn+cB7vM/Hs3/J8tF13
# ZPP+8NtX3vu4NrchHDJYgjOi+1JuSf+4jpF/pEEPXp9AusizmSmkBK4iVT7NwVtR
# nS1ts8qAGHGPg2HPa4b2u9meueUoqNVtMhbumI1y+d9ZkThNXBXz2aItT2C99DM3
# T3qYqAUmvKUryVSpMLVpse4je5WN6VVlCDFKWFRH202YxEVWsZ5baN9CaqCbCS0E
# a7s9OFLaEM5fNn9m5s69lD/ekcW2qTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKb
# SZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIy
# NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXI
# yjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjo
# YH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1y
# aa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v
# 3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pG
# ve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viS
# kR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYr
# bqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlM
# jgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSL
# W6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF
# emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIu
# rQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIE
# FgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWn
# G1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEW
# M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5
# Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi
# AEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV
# 9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js
# Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAx
# MC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2
# LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv
# 6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZn
# OlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1
# bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4
# rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU
# 6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDF
# NLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/
# HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdU
# CbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKi
# excdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTm
# dHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq
# ELQdVTNYs6FwZvKhggNMMIICNAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJp
# Y2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjhEMDAtMDVF
# MC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMK
# AQEwBwYFKw4DAhoDFQBoqfem2KKzuRZjISYifGolVOdyBKCBgzCBgKR+MHwxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
# c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6QFFuzAi
# GA8yMDIzMTExNzAxNTE1NVoYDzIwMjMxMTE4MDE1MTU1WjBzMDkGCisGAQQBhFkK
# BAExKzApMAoCBQDpAUW7AgEAMAYCAQACAQ4wBwIBAAICE10wCgIFAOkClzsCAQAw
# NgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgC
# AQACAwGGoDANBgkqhkiG9w0BAQsFAAOCAQEACUvOdMRwu+XNiUt3yZe98nTi1iHO
# IoNuCtD3I4bq3nEus+otdtQS8uID7A6zzo6uKJ1rYCPvqeQQI/TNk2/nQ2dwCYWC
# 2sXaL0BGHGQFxiW7sZFl+hYGtnpvBG98YubNCX7zU5UayOEYTtHNuMV++rAL+jyw
# jnfV95Zyb5lvGL08WP0JQQD6bmawZlkZNCd2JWXfHOMLEou/XZRokTRo3nzBkxWo
# SViZ27kko2dBYPfLp6CbNn5XQzmtUfo2n+A0sTyu6MWfGvcvluEBJdNvRcO0ZfBr
# L6MKGFCXBzPehWiOgdjYVLKH1vWZrBaUXShLhwbFk+/ZYkmBa0LHgYncsjGCBA0w
# ggQJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABzVUH
# KufKwZkdAAEAAAHNMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYL
# KoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIEyA3eqgVZTsPdu6DDLYNfNcE3N+
# irwpCYPzLj5x8v+oMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQg4mal+K1W
# vU9kaC9MR1OlK1RzoY2Hss2uhAErClRGmQowgZgwgYCkfjB8MQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBQQ0EgMjAxMAITMwAAAc1VByrnysGZHQABAAABzTAiBCApALaduXlp
# 61oXEr52Lo91QRjgiUCgz3t3qBViFZdAczANBgkqhkiG9w0BAQsFAASCAgC+wl4Y
# fI4X2/7glAJvZu+NpzEWXjxuGBNHAmiIQV5NLPq/mYnnCUZXaTi55QLOrm8b4/si
# Jvsg6pBSUoFIqhCs7uw2av6hV/u6W9rk/j5bHx+lwAqM9GG3fWYDRAHaJlniI8pi
# qzly301jAySScJUt2dwCnUOlXoNadxIcIi7riObBnY+FB6AuBs2Balvx3Ja/A5Kg
# yEeF2dontghkDO5y/rw3mfVNSv+bWgtsT2vlKhFqrzbVLZBXg1JyevM8SRke2EFN
# dqj/Apf2DHfiQfodtdPt0jM77WxbrLjKWJrzVZ5reTM2wrPBDOVq14hOtsF7Z6Tp
# +YHXjRAIcF38rylJr+I3NHsYm8sfoBwn2tK91PP3feFBWI6xX+en6TSVbtyJYGy+
# vZjmvDVsipUJCpjbJOqCr/cn0Zy3K2z98F/3V6UcfkxdbbWRf9E5vFz502Q6OpWf
# 54aHPScrHXM4OilRmEcKNinPb7paTqC6jFCg66rPMZ8VJu9gJZmQvOfT2KcMXd/u
# 8XW/ZgSYsqg8N4FdKPivdzVlcKPCUFxsODfKWjlkRS0FsEj2RcMlP/SHiDsI3Bo0
# bvZLA9YrCjfgU09muFvRd70qJXFQNCzUilgmSpxOR89wuovw8rQNakQkQ6DBw0GW
# HrsLIliOxYfhm0wCln9l9bVM4e12LehvNNu+Mg==
# SIG # End signature block