Public/get-ADFSTkFederationDefaults.ps1

function get-ADFSTkFederationDefaults
{
 [CmdletBinding()]
    param (
        $URL,
        [switch]$InstallDefaults,
        $ExtractionFilter ="ADFSToolkit/config/federation",
        [switch]$ClearCache,
        [switch]$Silent
    )

process 
{
    #Prepare to be able to use zip files
    Add-Type -assembly "system.io.compression.filesystem"

    #Get All paths and assert they exist
       
       if ([string]::IsNullOrEmpty($Global:ADFSTkPaths))
        {
         $Global:ADFSTkPaths = Get-ADFSTKPaths
        
        }   

    # setup our files
    $nowStamp=[DateTime]::Now.ToString("yyyyMMdd-HHmmss")
    $fedCacheFile="federationdefaults.zip"
    $fedCacheFileBackup="federationdefaults" +$nowStamp +".zip"
    $federationDirNameBackup="federation"+$nowStamp
 
    $federationConfigCacheFile=         Join-Path $Global:ADFSTkPaths.cacheDir $fedCacheFile
    $federationConfigCacheFileBackup=   Join-Path $Global:ADFSTkPaths.cacheDir $fedCacheFileBackup
    $federationConfigDirFullBackupPath= Join-Path $Global:ADFSTkPaths.mainBackupDir $federationDirNameBackup

# Begin processing the various states for default handling
#
#

if  ($PSBoundParameters.ContainsKey('ClearCache') -and ($ClearCache -ne $null) )
{

    If  ( ($PSBoundParameters.ContainsKey('InstallDefaults')) -or ($PSBoundParameters.ContainsKey('URL'))    )
    {
        #("ADFSToolkit: When used, ClearCache flag must be the only flag used. Nothing done, exiting ")
        Write-ADFSTkHost feddefaultsErrorFlags -Style Info
        return

    }else
    {
        #Write-Output ("ADFSToolkit: Removing cache file $federationConfigCacheFile")
        Write-ADFSTkHost feddefaultsErrorFlagsElse -f $federationConfigCacheFile -Style Info

        remove-item  $federationConfigCacheFile
        return

    }
}

# Use case A: no url, no config cache available
if ( ( $PSBoundParameters.ContainsKey('URL') -and ($URL -eq  $null) ) -and !(Test-Path ( $federationConfigCacheFile )  ) )
   
    {
        
            #Write-Output ("ADFSToolkit: Federation default behaviour expected with no extra federation settings.")
            Write-ADFSTkHost feddefaultsCaseNoURLNoCacheFile -Style info

        
            if ($InstallDefaults)
            {
             #Write-Output ("ADFSToolkit: InstallDefaults flag found but no defaults to apply, nothing changed, exiting.")
             Write-ADFSTkHost feddefaultsCaseInstallDefNothing -Style Info
            }


            return
        }
# Use case B: no url, config cache detected, tell user about it
elseif ( (  $PSBoundParameters.ContainsKey('URL') -and ($URL -eq  $null) ) -and (Test-Path ( $federationConfigCacheFile )  ) )
     {
        #Write-Output ("ADFSToolkit: Federation defaults in the cache are:")
        Write-ADFSTkHost feddefaultsCaseNoURLConfigCacheYesHeader -Style info

        Get-ChildItem $federationConfigCacheFile -Force | Select-Object FullName, CreationTime, LastAccessTime, LastWriteTime, Mode, Length

    }
#Use case C: URL is not null, and we have a file. If InstallDefaults specified make backup and deploy.
#
# Note that we are now using if statements for presence as the defaults could be on disk if fetched but not installed
#

if ( $PSBoundParameters.ContainsKey('URL') -and ($URL -ne $null)  )
{

    #Write-Output ("ADFSToolkit: Updating federation defaults on disk from: $URL")
    Write-ADFSTkHost feddefaultsCaseNoURLConfigCacheYesHeaderURLOK -f $URL -Style info

    # make backup
    If (Test-Path ( $federationConfigCacheFile ) )
    {
        #Write-Output ("ADFSToolkit: Backing up $fedConfigCacheFile to $fedConfigCacheFileBackup")
        Write-ADFSTkHost feddefaultsCaseNoURLConfigCacheYesHeaderBackingUp -f $fedConfigCacheFile,$fedConfigCacheFileBackup -Style Info
        Copy-item $federationConfigCacheFile -Destination $federationConfigCacheFileBackup
    }

    # Begin fetch file
    $start_time = Get-Date

    #Write-Output ("ADFSToolkit: Fetching $URL to $federationConfigCacheFile")
    Write-ADFSTkHost feddefaultsFetchBegin -f $URL, $federationConfigCacheFilev -Style info
    [System.Net.WebClient]::New().DownloadFile($URL, $federationConfigCacheFile)

    #Write-Output "ADFSToolkit: Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
    Write-ADFSTkHost feddefaultsTimeTaken -f $((Get-Date).Subtract($start_time).Seconds) -Style info

    Get-ChildItem $federationConfigCacheFile -Force | Select-Object FullName, CreationTime, LastAccessTime, LastWriteTime, Mode, Length

    # interrogate the file we just fetched
    #Write-Output ("ADFSToolkit: contents of Federation Cache file: $federationConfigCacheFile :")
      Write-ADFSTkHost feddefaultsContents  -f $federationConfigCacheFile -Style Info
    

    $zip = [io.compression.zipfile]::OpenRead($federationConfigCacheFile)
    
    $zip.Entries|where-object {$_.FullName -match $ExtractionFilter }|Select-object FullName -ExpandProperty "FullName"
    $zip.Dispose()

}

    # deploy configuration that's on disk
    if ( ( $PSBoundParameters.ContainsKey('InstallDefaults')  -and ($InstallDefaults -ne $null) )   -and (Test-Path ( $federationConfigCacheFile ) )  )
    {

        #Write-Output ("ADFSToolkit: Installing federation defaults from: $federationConfigCacheFile ...")
        Write-ADFSTkHost feddefaultsInstalling -f $federationConfigCacheFile -style info

        $zip = [io.compression.zipfile]::OpenRead($federationConfigCacheFile)
        $unzippedDirName=($zip.Entries[0]).FullName
        $unzippedFullNameDir=Join-Path (Join-path $Global:ADFSTkPaths.cacheDir $unzippedDirName) $ExtractionFilter

        #backup previous federation-settings
        move-item  -Path $Global:ADFSTkPaths.federationDir -Destination $federationConfigDirFullBackupPath
        # Get-ChildItem $Global:ADFSTkPaths.federationDir -Exclude backup,federations.xml | Move-Item $_.fullName $Global:ADFSTkPaths.federationBackupDir

        Expand-Archive -Path $federationConfigCacheFile -DestinationPath $Global:ADFSTkPaths.cacheDir -Force

        copy-item $unzippedFullNameDir  $Global:ADFSTkPaths.federationDir -Recurse

        $zip.Dispose()

        # persist url in ADFSTkFederationSettings
        # verify URL exists, then persist
        if ( ( $PSBoundParameters.ContainsKey('URL') -and ($URL -ne $null) ) -and ($Global:ADFSTkPaths.mainConfigFile -ne $null) )
        {

            [xml]$config = Get-Content $Global:ADFSTkPaths.mainConfigFile
            $config.Configuration.FederationConfig.Federation.URL= $URL
            $config.Save( $Global:ADFSTkPaths.mainConfigFile)
        }


        #Write-Output ("ADFSToolkit: Done. Next time a new aggregate is configured, defaults will be used. Existing configurations should remain unchanged")
        Write-ADFSTkHost     feddefaultsUnchanged -Style Info
    }
     else
    {
        Write-Output " "
        #Write-Output "ADFSToolkit: Federation defaults not installed into ADFSToolkit. Specify -InstallDefaults to apply them."
        Write-ADFSTkHost     feddefaultsNotInstalled -Style Info
    }


    return

    

    Write-ADFSTkHost feddefaultsAllDone -Style Info


}


}

<#
.SYNOPSIS
   show,fetch, and install federation defaults zip bundle to augment ADFSToolkit behaviour
    
.DESCRIPTION
   show,fetch, and install federation defaults zip bundle.
   ADFSToolkit will use default behaviour otherwise
.EXAMPLE
get-ADFSTkFederationDefaults
.EXAMPLE
get-ADFSTkFederationDefaults -URL https://someurl/fed.zip
.EXAMPLE
get-ADFSTkFederationDefaults -InstallDefaults -URL https://someurl/fed.zip
 
#>

# SIG # Begin signature block
# MIIczwYJKoZIhvcNAQcCoIIcwDCCHLwCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUOOBN7vIUwfsUbYU7r7Zdj/M1
# GiegghcwMIIEFDCCAvygAwIBAgILBAAAAAABL07hUtcwDQYJKoZIhvcNAQEFBQAw
# VzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNV
# BAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0
# MTMxMDAwMDBaFw0yODAxMjgxMjAwMDBaMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQK
# ExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9HbG9iYWxTaWduIFRpbWVzdGFt
# cGluZyBDQSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlO9l
# +LVXn6BTDTQG6wkft0cYasvwW+T/J6U00feJGr+esc0SQW5m1IGghYtkWkYvmaCN
# d7HivFzdItdqZ9C76Mp03otPDbBS5ZBb60cO8eefnAuQZT4XljBFcm05oRc2yrmg
# jBtPCBn2gTGtYRakYua0QJ7D/PuV9vu1LpWBmODvxevYAll4d/eq41JrUJEpxfz3
# zZNl0mBhIvIG+zLdFlH6Dv2KMPAXCae78wSuq5DnbN96qfTvxGInX2+ZbTh0qhGL
# 2t/HFEzphbLswn1KJo/nVrqm4M+SU4B09APsaLJgvIQgAIMboe60dAXBKY5i0Eex
# +vBTzBj5Ljv5cH60JQIDAQABo4HlMIHiMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB
# Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTBHBgNV
# HSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFs
# c2lnbi5jb20vcmVwb3NpdG9yeS8wMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny
# bC5nbG9iYWxzaWduLm5ldC9yb290LmNybDAfBgNVHSMEGDAWgBRge2YaRQ2XyolQ
# L30EzTSo//z9SzANBgkqhkiG9w0BAQUFAAOCAQEATl5WkB5GtNlJMfO7FzkoG8IW
# 3f1B3AkFBJtvsqKa1pkuQJkAVbXqP6UgdtOGNNQXzFU6x4Lu76i6vNgGnxVQ380W
# e1I6AtcZGv2v8Hhc4EvFGN86JB7arLipWAQCBzDbsBJe/jG+8ARI9PBw+DpeVoPP
# PfsNvPTF7ZedudTbpSeE4zibi6c1hkQgpDttpGoLoYP9KOva7yj2zIhd+wo7AKvg
# IeviLzVsD440RZfroveZMzV+y5qKu0VN5z+fwtmK+mWybsd+Zf/okuEsMaL3sCc2
# SI8mbzvuTXYfecPlf5Y1vC0OzAGwjn//UYCAp5LUs0RGZIyHTxZjBzFLY7Df8zCC
# BH0wggNloAMCAQICAxvnFTANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEh
# MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
# YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE0MDEwMTA3
# MDAwMFoXDTMxMDUzMDA3MDAwMFowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdB
# cml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNv
# bSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx
# +lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u
# 9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94L
# w7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
# fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7
# S13MMuyFYkMlNAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsD
# PAnrSTFcaUaz4EcCAwEAAaOCARcwggETMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
# AQH/BAQDAgEGMB0GA1UdDgQWBBQ6moUHEGcotu/2vQVBbiDBlNoP3jAfBgNVHSME
# GDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zA0BggrBgEFBQcBAQQoMCYwJAYIKwYB
# BQUHMAGGGGh0dHA6Ly9vY3NwLmdvZGFkZHkuY29tLzAyBgNVHR8EKzApMCegJaAj
# hiFodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkcm9vdC5jcmwwRgYDVR0gBD8wPTA7
# BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHBzOi8vY2VydHMuZ29kYWRkeS5jb20v
# cmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBAFkLU72ShhGnJHvtWzHPHR9s
# cMW4br5Ou/a+l1DhMH+6KFxilMLjfjP3+0J2hduVHIwiWHUJDIhlZzkKFgnFoDiX
# pMUjkz+0GKYBBkSR46dpJ7RaJX86tzLN3YT/KjgpM6TdZ7KF/qGIIBxQicjcKvZC
# AzdM5ojf1a8k8rHD38y17OCZXrdJVCA8lBgMxxxSGEmkbeGzWAvJ2OzZrhwyjihw
# DeL+pheehA+9V3CzWukfoIZTu+98/2kL4EjDt5MLyApUxKxdFGc3bMqlLzEIN6pu
# b4y8m+JXXSSBr5eXnIStbKw3TGbzYZERIOS+MJ96pCkJsOE0X2R3GEBR34wwpq8w
# ggSfMIIDh6ADAgECAhIRIdaZp2SXPvH4Qn7pGcxTQRQwDQYJKoZIhvcNAQEFBQAw
# UjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKDAmBgNV
# BAMTH0dsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gRzIwHhcNMTYwNTI0MDAw
# MDAwWhcNMjcwNjI0MDAwMDAwWjBgMQswCQYDVQQGEwJTRzEfMB0GA1UEChMWR01P
# IEdsb2JhbFNpZ24gUHRlIEx0ZDEwMC4GA1UEAxMnR2xvYmFsU2lnbiBUU0EgZm9y
# IE1TIEF1dGhlbnRpY29kZSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
# CgKCAQEAsBeuotO2BDBWHlgPse1VpNZUy9j2czrsXV6rJf02pfqEw2FAxUa1WVI7
# QqIuXxNiEKlb5nPWkiWxfSPjBrOHOg5D8NcAiVOiETFSKG5dQHI88gl3p0mSl9Rs
# kKB2p/243LOd8gdgLE9YmABr0xVU4Prd/4AsXximmP/Uq+yhRVmyLm9iXeDZGayL
# V5yoJivZF6UQ0kcIGnAsM4t/aIAqtaFda92NAgIpA6p8N7u7KU49U5OzpvqP0liT
# FUy5LauAo6Ml+6/3CGSwekQPXBDXX2E3qk5r09JTJZ2Cc/os+XKwqRk5KlD6qdA8
# OsroW+/1X1H0+QrZlzXeaoXmIwRCrwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQD
# AgeAMEwGA1UdIARFMEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYBBQUHAgEWJmh0dHBz
# Oi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAkGA1UdEwQCMAAwFgYD
# VR0lAQH/BAwwCgYIKwYBBQUHAwgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny
# bC5nbG9iYWxzaWduLmNvbS9ncy9nc3RpbWVzdGFtcGluZ2cyLmNybDBUBggrBgEF
# BQcBAQRIMEYwRAYIKwYBBQUHMAKGOGh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5j
# b20vY2FjZXJ0L2dzdGltZXN0YW1waW5nZzIuY3J0MB0GA1UdDgQWBBTUooRKOFoY
# f7pPMFC9ndV6h9YJ9zAfBgNVHSMEGDAWgBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTAN
# BgkqhkiG9w0BAQUFAAOCAQEAj6kakW0EpjcgDoOW3iPTa24fbt1kPWghIrX4RzZp
# juGlRcckoiK3KQnMVFquxrzNY46zPVBI5bTMrs2SjZ4oixNKEaq9o+/Tsjb8tKFy
# v22XY3mMRLxwL37zvN2CU6sa9uv6HJe8tjecpBwwvKu8LUc235IgA+hxxlj2dQWa
# NPALWVqCRDSqgOQvhPZHXZbJtsrKnbemuuRQ09Q3uLogDtDTkipbxFm7oW3bPM5E
# ncE4Kq3jjb3NCXcaEL5nCgI2ZIi5sxsm7ueeYMRGqLxhM2zPTrmcuWrwnzf+tT1P
# mtNN/94gjk6Xpv2fCbxNyhh2ybBNhVDygNIdBvVYBAexGDCCBNAwggO4oAMCAQIC
# AQcwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
# b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwg
# SW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp
# dHkgLSBHMjAeFw0xMTA1MDMwNzAwMDBaFw0zMTA1MDMwNzAwMDBaMIG0MQswCQYD
# VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEa
# MBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0dHA6Ly9jZXJ0
# cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28gRGFkZHkgU2Vj
# dXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEF
# AAOCAQ8AMIIBCgKCAQEAueDLENSvdr3Uk2LrMGS4gQhswwTZYheOL/8+Zc+PzmLm
# PFIc2hZFS1WreGtjg2KQzg9pbJnIGhSLTMxFM+qI3J6jryv+gGGdeVfEzy70PzA8
# XUf8mha8wzeWQVGOEUtU+Ci+0Iy+8DA4HvOwJvhmR2Nt3nEmR484R1PRRh2049wA
# 6kWsvbxx2apvANvbzTA6eU9fTEf4He9bwsSdYDuxskOR2KQzTuqz1idPrSWKpcb0
# 1dCmrnQFZFeItURV1C0qOj74uL3pMgoClGTEFjpQ8Uqu53kzrwwgB3/o3wQ5wmkC
# bGNS+nfBG8h0h8i5kxhQVDVLaU68O9NJLh/cwdJS+wIDAQABo4IBGjCCARYwDwYD
# VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFEDCvSeOzDSD
# MKIz1/tss/C0LIDOMB8GA1UdIwQYMBaAFDqahQcQZyi27/a9BUFuIMGU2g/eMDQG
# CCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5j
# b20vMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ry
# b290LWcyLmNybDBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0
# cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsF
# AAOCAQEACH5skxDIOLiWqZBL/6FfTwTvbD6ciAbJUI+mc/dXMRu+vOQv2/i601vg
# tOfmeWIODKLXamNzMbX1qEikOwgtol2Q17R8JU8RVjDEtkSdeyyd5V7m7wxhqr/k
# KhvuhJ64g33BQ85EpxNwDZEf9MgTrYNg2dhyqHMkHrWsIg7KF4liWEQbq4klAQAP
# zcQbYttRtNMPUSqb9Lxz/HbONqTN2dgs6q6b9SqykNFNdRiKP4pBkCN9W0v+pANY
# m0ayw2Bgg/h9UEHOwqGQw7vvAi/SFVTuRBXZCq6nijPtsS12NibcBOuf92EfFdyH
# b+5GliitoSZ9CgmnLgSjjbz4vAQwATCCBRwwggQEoAMCAQICCDeMqUwECkf0MA0G
# CSqGSIb3DQEBCwUAMIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTET
# MBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4x
# LTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEz
# MDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAt
# IEcyMB4XDTIwMDEwODExMjIyNFoXDTIxMDMwODE4NTgwMFowXjELMAkGA1UEBhMC
# Q0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTEVMBMGA1UEChMM
# Q0FOQVJJRSBJbmMuMRUwEwYDVQQDEwxDQU5BUklFIEluYy4wggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQDZhfCjFqiTmN1uLoySixnwaOjf/ZAL9P6SvjlC
# aBA2mutoorEgnzUP8HnOIcvMRgEMPmpaZ8egM93Bmx9d41xoarsQpCN3DhYOo+b3
# fWnPucVtpxbul2OFePv63mw/uvr+dqkv4b/f3Tg+ilQbpsNonbvh9MKEFv8Pn9ko
# j0ySV+qxz34PxTVAe6g//pel3/3i9fqilCnIEcx4zg/+NKBeOWROSs4oXo3IvBjV
# runmz+YuieSr78TqIE6hD8JF2q1wKwfMB3+x7dEXZAus9WtIU/qITATtEfO9QAgr
# rYL4F1MLN+osSp8my5eCOjnLTQc47q574V3zQhsIHW7yBXLdAgMBAAGjggGFMIIB
# gTAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQE
# AwIHgDA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dk
# aWcyczUtNS5jcmwwXQYDVR0gBFYwVDBIBgtghkgBhv1tAQcXAjA5MDcGCCsGAQUF
# BwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv
# MAgGBmeBDAEEATB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
# Y3NwLmdvZGFkZHkuY29tLzBABggrBgEFBQcwAoY0aHR0cDovL2NlcnRpZmljYXRl
# cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkaWcyLmNydDAfBgNVHSMEGDAWgBRA
# wr0njsw0gzCiM9f7bLPwtCyAzjAdBgNVHQ4EFgQUUPnMg2nmYS8l7rmax3weVkrg
# z5AwDQYJKoZIhvcNAQELBQADggEBAIYabiARaY4KhO6oWgNHPOBjoHuqUH7NwRGN
# /ztYJznRBZbdD50smoK5GR0FvUZ8TXhYoZOazXe4NlFM4e6YcudU+EA/OF+sZHFB
# Wziz1VS6U3sS+cGyJcxvelSoid0q3W3i9/Zy6Nv2kk/DEJp49O47mPNovpL15yyk
# X3Vo26GwC9peo4s/cKMzthmgrcF2uLkT+LW44xKhaL7nBTGDMhjno+a3t00SWCId
# 7wzgQadIJ1QlFOKm0xgmuiW3LIqCG0apvaOfvWKTPKq68q+FbDPOO48oKrvw1c9K
# /m8gcnBLz6PX1REVIs5u3pvdOYBCz6uXyKxnt+Q5jDEK0NskLu0xggUJMIIFBQIB
# ATCBwTCBtDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcT
# ClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMS0wKwYDVQQL
# EyRodHRwOi8vY2VydHMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8xMzAxBgNVBAMT
# KkdvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMgIIN4yp
# TAQKR/QwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJ
# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB
# gjcCARUwIwYJKoZIhvcNAQkEMRYEFA4FRXe76gN1XleQM2wNxi4nlfjlMA0GCSqG
# SIb3DQEBAQUABIIBALW5gCoJ5rPvrmXSk9WG6V2mxpAeK9SEG73zChLYq0GQGB2P
# ZrB6ukNIKoPw5bLCeskARx1dPqy4w8+hUSofB/TtdDsehecEUv2EdnKkwRHy4SBc
# ih9RiEo775bIHKwWSw/80LB9QdWLZpMKjbzjEhJ4YKTl08KWHjSherTnn0qnI8NJ
# Q9KyQ14ndawwf3+DekPDBgHT/Y0yBYL8hr8W+i5rNaOpE5TufGK2krrUUKDWS2We
# JVlx02Ria82PCSfyu2GvBnTCyUX0IGy97vLQtHQnaeJHrOLdHaYCPww3GKxeODB2
# hYPkVFXXf5c73LEjdYruGYV64DaTG54zfKJZsd6hggKiMIICngYJKoZIhvcNAQkG
# MYICjzCCAosCAQEwaDBSMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2ln
# biBudi1zYTEoMCYGA1UEAxMfR2xvYmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBH
# MgISESHWmadklz7x+EJ+6RnMU0EUMAkGBSsOAwIaBQCggf0wGAYJKoZIhvcNAQkD
# MQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAxMTE2MjI0MTQ1WjAjBgkq
# hkiG9w0BCQQxFgQU8d6T//SFlvMpv4OwKxHB1pPnDB8wgZ0GCyqGSIb3DQEJEAIM
# MYGNMIGKMIGHMIGEBBRjuC+rYfWDkJaVBQsAJJxQKTPseTBsMFakVDBSMQswCQYD
# VQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEoMCYGA1UEAxMfR2xv
# YmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBHMgISESHWmadklz7x+EJ+6RnMU0EU
# MA0GCSqGSIb3DQEBAQUABIIBAIbc9SoHzkjwLGhSaKfslYI0zT6tHwI8xTtKLlI6
# YIUorom+Qv5aEr8PzSOfEnfVyjsFdX71aWO0J3BV2sVDWV58gqexAPuQ1H8SiaHB
# n/CpSYwZk+Zcc82kfnySKYkOfRCt7bZsTf0/oJAY00uz+b6+RjQ8ybgn20yUvqu/
# 7xlcYWrw302jqQMtQsApT8p1wHq9s78KFEOHihEDaLzjoUdL43mVPwwWGt6idIhC
# HkK8jyRr8tJMOm5zCEefx7nIgeMFFECnt4UtON8cwr+qleTasG7+83ehtuHHqB7m
# W4kSOx/Ki50ADyOZKdrjm9g3iLK/RTZSBUXtoVm417/1si4=
# SIG # End signature block