Get-AADAssessAppCredentialExpirationReport.ps1

<#
.SYNOPSIS
    Provides a report to show all the keys expiration date accross application and service principals
.DESCRIPTION
    Provides a report to show all the keys expiration date accross application and service principals
.EXAMPLE
    PS C:\> Get-AADAssessAppCredentialExpirationReport | Export-Csv -Path ".\AppCredentialsReport.csv"
#>

function Get-AADAssessAppCredentialExpirationReport {
    [CmdletBinding()]
    param (
        # Application Data
        [Parameter(Mandatory = $false)]
        [psobject] $ApplicationData,
        # Service Principal Data
        [Parameter(Mandatory = $false)]
        [psobject] $ServicePrincipalData,
        # Generate Report Offline, only using the data passed in parameters
        [Parameter(Mandatory = $false)]
        [switch] $Offline
    )

    Start-AppInsightsRequest $MyInvocation.MyCommand.Name
    try {

        if ($Offline -and (!$PSBoundParameters['ApplicationData'] -or !$PSBoundParameters['ServicePrincipalData'])) {
            Write-Error -Exception (New-Object System.Management.Automation.ItemNotFoundException -ArgumentList 'Use of the offline parameter requires that all data be provided using the data parameters.') -ErrorId 'DataParametersRequired' -Category ObjectNotFound
            return
        }

        function Process-AppCredentials {
            param (
                #
                [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
                [psobject] $InputObject,
                #
                [Parameter(Mandatory = $true)]
                [string] $ObjectType
            )

            process {
                Write-Verbose "Processing $($ObjectType): $($InputObject.displayName) ($($InputObject.id)) "
                foreach ($credential in $InputObject.keyCredentials) {
                    # check for hasExtensionAttribute
                    $hasExtendedValue = $null
                    if ( [bool]($credential.PSobject.Properties.name -match "hasExtendedValue") ) {
                        $hasExtendedValue = $credential.hasExtendedValue
                    }
                    if ($credential.type -eq "AsymmetricX509Cert" -and ![string]::IsNullOrEmpty($credential.key)) {
                        # credential is a cert and has a key
                        $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([System.Convert]::FromBase64String($credential.key))
                        $certSignatureAlgorithm = $cert.SignatureAlgorithm.FriendlyName
                        $certKeySize = $null
                        if ($cert.PublicKey.Key) {
                            $certKeySize = $cert.PublicKey.Key.KeySize
                        }
                        elseif (!$certKeySize -and $certSignatureAlgorithm -match "RSA") {
                            try  {
                                $certKeySize = $cert.PublicKey.GetRSAPublicKey().KeySize
                            } catch {}
                        }
                        elseif (!$certKeySize -and $certSignatureAlgorithm -match "ECDSA") {
                            try {
                                $certKeySize = $cert.PublicKey.GetECDsaPublicKey().KeySize
                            } catch {}
                        }
                        [PSCustomObject]@{
                            displayName                 = $InputObject.displayName
                            objectType                  = $ObjectType
                            credentialType              = $credential.type
                            credentialStartDateTime     = $credential.startDateTime
                            credentialEndDateTime       = $credential.endDateTime
                            credentialUsage             = $credential.usage
                            certSubject                 = $cert.Subject
                            certIssuer                  = $cert.Issuer
                            certIsSelfSigned            = ($cert.Subject -eq $cert.Issuer)
                            certSignatureAlgorithm      = $certSignatureAlgorithm
                            certKeySize                 = $certKeySize
                            credentialHasExtendedValue  = $hasExtendedValue
                        }
                    }
                    else {
                        [PSCustomObject]@{
                            displayName                 = $InputObject.displayName
                            objectType                  = $ObjectType
                            credentialType              = $credential.type
                            credentialStartDateTime     = $credential.startDateTime
                            credentialEndDateTime       = $credential.endDateTime
                            credentialUsage             = $credential.usage
                            certSubject                 = $null
                            certIssuer                  = $null
                            certIsSelfSigned            = $null
                            certSignatureAlgorithm      = $null
                            certKeySize                 = $null
                            credentialHasExtendedValue  = $hasExtendedValue
                        }
                    }
                }

                foreach ($credential in $InputObject.passwordCredentials) {
                    [PSCustomObject]@{
                        displayName                 = $InputObject.displayName
                        objectType                  = $ObjectType
                        credentialType              = "Password"
                        credentialStartDateTime     = $credential.startDateTime
                        credentialEndDateTime       = $credential.endDateTime
                        credentialUsage             = $null
                        certSubject                 = $null
                        certIssuer                  = $null
                        certIsSelfSigned            = $null
                        certSignatureAlgorithm      = $null
                        certKeySize                 = $null
                        credentialHasExtendedValue  = $null
                    }
                }
            }
        }

        ## Get Applications
        if ($ApplicationData) {
            if ($ApplicationData -is [System.Collections.Generic.Dictionary[guid, pscustomobject]]) {
                $ApplicationData.Values | Process-AppCredentials -ObjectType 'Application'
            }
            else {
                $ApplicationData | Process-AppCredentials -ObjectType 'Application'
            }
        }
        else {
            Write-Verbose "Getting applications..."
            Get-MsGraphResults 'applications?$select=id,displayName,keyCredentials,passwordCredentials' -Top 999 `
            | Process-AppCredentials -ObjectType 'Application'
        }

        ## Get Service Principals
        if ($ServicePrincipalData) {
            if ($ServicePrincipalData -is [System.Collections.Generic.Dictionary[guid, pscustomobject]]) {
                $ServicePrincipalData.Values | Process-AppCredentials -ObjectType 'Service Principal'
            }
            else {
                $ServicePrincipalData | Process-AppCredentials -ObjectType 'Service Principal'
            }
        }
        else {
            Write-Verbose "Getting serviceprincipals..."
            Get-MsGraphResults 'servicePrincipals?$select=id,displayName,keyCredentials,passwordCredentials' -Top 999 `
            | Process-AppCredentials -ObjectType 'Service Principal'
        }

    }
    catch { if ($MyInvocation.CommandOrigin -eq 'Runspace') { Write-AppInsightsException $_.Exception }; throw }
    finally { Complete-AppInsightsRequest $MyInvocation.MyCommand.Name -Success $? }
}

# SIG # Begin signature block
# MIInlgYJKoZIhvcNAQcCoIInhzCCJ4MCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA3e4e1npygTbyg
# Kk6K1bcFEyxTuLZ35VCvvAzCCW2xf6CCDXYwggX0MIID3KADAgECAhMzAAACURR2
# zMWFg24LAAAAAAJRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDBIpXR3b1IYAMunV9ZYBVYsaA7S64mqacKy/OJUf0Lr/LW/tWlJDzJH9nFAhs0
# zzSdQQcLhShOSTUxtlwZD9dnfIcx4pZgu0VHkqQw2dVc8Ob21GBo5sVrXgEAQxZo
# rlEuAl20KpSIFLUBwoZFGFSQNSMcqPudXOw+Mhvn6rXYv/pjXIjgBntn6p1f+0+C
# 2NXuFrIwjJIJd0erGefwMg//VqUTcRaj6SiCXSY6kjO1J9P8oaRQBHIOFEfLlXQ3
# a1ATlM7evCUvg3iBprpL+j1JMAUVv+87NRApprPyV75U/FKLlO2ioDbb69e3S725
# XQLW+/nJM4ihVQ0BHadh74/lAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUMLgM7NX5EnpPfK5uU6FPvn2g/Ekw
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzQ2NzU5NjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIVJlff+Fp0ylEJhmvap
# NVv1bYLSWf58OqRRIDnXbHQ+FobsOwL83/ncPC3xl8ySR5uK/af4ZDy7DcDw0yEd
# mKbRLzHIfcztZVSrlsg0GKwZuaB2MEI1VizNCoZlN+HlFZa4DNm3J0LhTWrZjVR0
# M6V57cFW0GsV4NlqmtelT9JFEae7PomwgAV9xOScz8HzvbZeERcoSRp9eRsQwOw7
# 8XeCLeglqjUnz9gFM7RliCYP58Fgphtkht9LNEcErLOVW17m6/Dj75zg/IS+//6G
# FEK2oXnw5EIIWZraFHqSaee+NMgOw/R6bwB8qLv5ClOJEpGKA3XPJvS9YgOpF920
# Vu4Afqa5Rv5UJKrsxA7HOiuH4TwpkP3XQ801YLMp4LavXnvqNkX5lhFcITvb01GQ
# lcC5h+XfCv0L4hUum/QrFLavQXJ/vtirCnte5Bediqmjx3lswaTRbr/j+KX833A1
# l9NIJmdGFcVLXp1en3IWG/fjLIuP7BqPPaN7A1tzhWxL+xx9yw5vQiT1Yn14YGmw
# OzBYYLX0H9dKRLWMxMXGvo0PWEuXzYyrdDQExPf66Fq/EiRpZv2EYl2gbl9fxc3s
# qoIkyNlL1BCrvmzunkwt4cwvqWremUtqTJ2B53MbBHlf4RfvKz9NVuh5KHdr82AS
# MMjU4C8KNTqzgisqQdCy8unTMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
# /Xmfwb1tbWrJUnMTDXpQzTGCGXYwghlyAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAJRFHbMxYWDbgsAAAAAAlEwDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHMpDK9Vib4NmoJ8k5QNCXA5
# LV5bqICeWSwTu61kb4QJMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEAhKACnVIM3Lc1b0GaCMFDZSa1OJ24crJpkirmw6+CxbKeBLJfp0rq0wSZ
# YEkIA6uUl/ZuSHD8x2ys2KsAK/hKZjq/sriAs/xiqCeZSaYffHup6xWIxsXQkzha
# jKNOuZ+bhpCslvgxDX8bg2QZiXCcD5foNAhXmHOmuBBHJcmfm9klZNLHOvARF0m0
# ClpAVq1Sip/slgJkBaezSv3SBx4nxB28q9LggVhMjX0FtS1Ic2bglHORTCFx70R7
# 11E0x33vp8ilhTiCz7NeUWRD0SRgNLVtjcI7QfNkxG6bbSPDfsOXF7oFqOF/V7W+
# l5FBgxwUdsVVuwZrZdiq7qeCZ47Ho6GCFwAwghb8BgorBgEEAYI3AwMBMYIW7DCC
# FugGCSqGSIb3DQEHAqCCFtkwghbVAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFRBgsq
# hkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCDYacbaPw1jAmR5FwQpN7fziiGd95ncSTw4n3wLkFAaeQIGYoJdUe78
# GBMyMDIyMDYxNTE3MzczNS40NzdaMASAAgH0oIHQpIHNMIHKMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozRTdBLUUz
# NTktQTI1RDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCC
# EVcwggcMMIIE9KADAgECAhMzAAABoOm7jLsOotF6AAEAAAGgMA0GCSqGSIb3DQEB
# CwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV
# BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTIxMTIwMjE5MDUy
# M1oXDTIzMDIyODE5MDUyM1owgcoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMx
# JjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjNFN0EtRTM1OS1BMjVEMSUwIwYDVQQD
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEAv9riDmhxnQDo9mL4YSOgvIhQKu8K5f+VqT449HxBwoui
# L8fyNNibLPx1YZHxkzBrbUeY0YYayV8nVg5zps0VNweBuduU+6cJBTRQV7pjP/fJ
# eZNFNl4mmfm7pVx3ueMero/+r+VRhb/tB4dXcoxlEz2kRMEu8ffE3ubRRxIpj2vg
# LBtpjPp/TcH0EY3dS4hAm3AmRZIMG5YkP2pIjK9bWZo5A28bbtmkHF4xHw52vCR/
# sGZn3btF+5OnSeVhkRcM2YiziVuEIQBKXodnNZpm7QHwZ4UjzfhOclC36X009sF/
# EWx+l3wIOrGcfPPesatPoFA/Zh8vGbaXRHhNWQNB4Acg1tqyQm0wCQIbe9Qe0c9q
# T0JoOUd/r0gq4vAXnEgfmfJsGC97jkt0em3lASe4hOKz0vVgtcNX2UeyuOGUpntn
# SPjvf54YG9zC2IJus8dx4bS6BoRlTy/lqA5DJ7fdyBqDupDQQjNl/grNtqpdrT45
# CEcscMRekbF4f0B54SiYAc3zvnvOCN02GyNItvcwEy+shzr+bBLNc2jTIoduyMH1
# oOEO/uNC+3uvLgusg/BFBKWg9rNk+fTYUmrk8whJwKeWK0rHHPTEFSIu4PuRgHQv
# KQr/tIkWu0CL2pVPvZVoJMgAVP54hR1j48hqAeMdys6N7Vwemgt8mf3U0V6SZ2kC
# AwEAAaOCATYwggEyMB0GA1UdDgQWBBRyuS5Q2ClOkbiRbBQvRM8LYYzQ6DAfBgNV
# HSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5o
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU
# aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG
# CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRz
# L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNV
# HRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IC
# AQAxfcYCq/jfrJQJpW3BKkAZaS+T3wTKnC5EusknhiYxviyl91qL+acoK4Sn7V2f
# dDWFlH7SGac3WLOHoUeUZWhN3mLm1pXDZcLCpHKxkgySmsG2wxn7zuIf9S9d7IOu
# oT4m+u5hveggKkVRdHOTANcIio45f+YH623TSx4LUREPMwqWyuPuupdRXdLqfZsX
# DhBKYYSa/FN8IcBcKCvkCf5MVqIBrXw4mqukcqBVoT/Liki1Q1fjExEx2W96djsJ
# wVhNVutO9VwyncUZDf6QBGdeRNSyTb/YmKNZdT/0XRfiM6TCxgwH/z5Vb01MN1ax
# /bmqm2K/q0cbYvmzN2m9cL/b98US3PsD6J4ksVtqevQzeFqPeiAxWSJC0fh3Fgoq
# h1cBV54JAlH3THt8ZrziF2EZEytD+sDy3wvjrO6HlUXjI9kwNUDDJIGfq4TztO4l
# uzee8wAbzIhyUHR0THitxQYEeH2hL041AHSkUJChVfNrhO8NFDJ7HiX1+xCw2PU+
# GlsdqsBKmpvZexh1+ANmZtJ59aGmv2MXMye4CFREUhkjli8BDMXBagRj5vUEkO6I
# DAZ+Vh8JHU05JmpwW/2dnA6cQcXdbzo8iJuAThZS4weKYrwpTtmZLFih+6gWJaGG
# tO1NTtwvI7W8xlHR8iwmlRgVfA3w+YfHjp8o62gRuzzTWTCCB3EwggVZoAMCAQIC
# EzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoX
# DTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC
# 0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VG
# Iwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP
# 2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/P
# XfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361
# VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwB
# Sru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9
# X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269e
# wvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDw
# wvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr
# 9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+e
# FnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAj
# BgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+n
# FV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEw
# PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j
# cy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3
# FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAf
# BgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBH
# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNS
# b29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl
# ckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4Swf
# ZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTC
# j/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu
# 2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/
# GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3D
# YXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbO
# xnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqO
# Cb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I
# 6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0
# zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaM
# mdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNT
# TY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggLOMIICNwIBATCB+KGB0KSBzTCByjEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWlj
# cm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBF
# U046M0U3QS1FMzU5LUEyNUQxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVABMGuI1o2nGzmFPvvecnSe4UgouYoIGD
# MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEF
# BQACBQDmVGbpMCIYDzIwMjIwNjE1MjIxMDQ5WhgPMjAyMjA2MTYyMjEwNDlaMHcw
# PQYKKwYBBAGEWQoEATEvMC0wCgIFAOZUZukCAQAwCgIBAAICGboCAf8wBwIBAAIC
# EbIwCgIFAOZVuGkCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAK
# MAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQAS36p/jnKZ
# zBDf/5fwwz5RhcF0+tCnZmByLCnV05AE9qxm6DTrEp1OAAuG7fIxKAaYRIn/a25s
# h+gjnO5VkI0vbN3hLTA514Dvo/DIHiH2WoOM2V9wBhawo0T4J152a99bNYvPtGcG
# t6hS3TDtBz+FajN41stLrBTaBgVtQTKApDGCBA0wggQJAgEBMIGTMHwxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABoOm7jLsOotF6AAEAAAGgMA0GCWCG
# SAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI
# hvcNAQkEMSIEIEKPughcqOYBgZsnwlwu69ErjGUQvF3xZ8/R96++exuvMIH6Bgsq
# hkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgL0eKPGhlBCISLd0RL7MdPrL5zOlomoGu
# Uj2iuIOvtNMwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT
# MwAAAaDpu4y7DqLRegABAAABoDAiBCCfiotYVp1RHc7UDfT2KSG8Ff5K4UlSjFy4
# epeCQVWNtTANBgkqhkiG9w0BAQsFAASCAgAfd4U6Twaa0CZfa7rcmufeFjG385wZ
# dyhcMSyZMPM60IX0xjB9mcmoPilJGRFHAd7mh010/1lqwo+/aB7/wAbi2ee5K1aa
# qoOtQidr+EC6KbxQA/Trxhn/w2yjApvFdOxrF6tcy9zWLtyy8HxSSN9EWJQUr/LC
# 0PinNx/3XfCse3TsTIbuzLNUhkimdo+6ndvvkgqeAvJB7i/D9ff/yCIvMJZiitXZ
# +LkL0vpjFKarcsChswNpS2L16L9SwjPQSAXttKF+YvsPNsr5u5ynvyM0tmY/bnxg
# 4dPIV/EMCZncDU4GY8WcKZsHvQWyx3Ou7kGYZHpuzf9ClLBr0LRdgzlYYFfM8/tJ
# 8GNxbpblVdm3xRQmphIrdamMhAInudnKIPRSIkbuMKl1rRd754NxFCwiMKoqfafn
# fdhkTurrI2yyX7nDzfUaFC577LxPBgE3edIeZJ8cIqqXkoAXo2iTn42Qjmt+jmfl
# W0hAIOc6FineT7qAwIIDV7OCmqVF3AUZWPiP8hU3V6cZV7xKVH+ptvZbVUdq2uEd
# CcQppo3lf3alqdEiEfmZ0kaXyPujPPp5ATsoVQkFVSrsFxfaSjeM0mUA+FH9BbeH
# IPFY2+nLMrR/+JKq1DZSFKcabvJI+HMsF7KB4wt5Ru9j9kN150+9uKrVoBD2H2K0
# s1py6j/hNVylmg==
# SIG # End signature block