Public/New-ADFSTkInstitutionConfiguration.ps1

#Requires -Version 5.1

function New-ADFSTkInstitutionConfiguration {
[cmdletbinding()]
    Param (
    )


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

$CompatibleConfigVersion = "1.3"

    
    try {
        $mainConfiguration = Get-ADFSTkConfiguration
    }
    catch {
        #inform that we need a main config and that we will call that now
        Write-ADFSTkHost -WriteLine -AddSpaceAfter
        Write-ADFSTkHost confNeedMainConfigurationMessage -Style Info -AddSpaceAfter
        $mainConfiguration = New-ADFSTkConfiguration -Passthru
    }

    Write-ADFSTkHost confCreateNewConfigurationFile -Style Info -AddLinesOverAndUnder

    # Use a default template from to start with
    #$mainConfiguration.FederationConfig.Federation

    $federationName = $mainConfiguration.FederationConfig.Federation.FederationName
    if ([string]::IsNullOrEmpty($federationName))
    {
        $defaultConfigFile = $Global:ADFSTkPaths.defaultConfigFile
        #[xml]$config = Get-Content $Global:ADFSTkPaths.defaultConfigFile
    }
    else
    {
        $defaultFederationConfigDir = Join-Path $Global:ADFSTkPaths.federationDir $federationName
        
        #Check if the federation dir exists and if not, create it
        ADFSTk-TestAndCreateDir -Path $defaultFederationConfigDir -PathName "$federationName config directory"

        #Check if we already have any Federation defaults file(s)
        $defaultFederationConfigFiles = Get-ChildItem -Path $defaultFederationConfigDir -Filter "*_defaultConfigFile.xml"
        
        if ([string]::IsNullOrEmpty($defaultFederationConfigFiles))
        {
            Write-ADFSTkHost confCopyFederationDefaultFolderMessage -Style Info -AddSpaceAfter -f $Global:ADFSTkPaths.federationDir
            Read-Host (Get-ADFSTkLanguageText cPressEnterKey) | Out-Null
        
            $defaultFederationConfigFiles = Get-ChildItem -Path $defaultFederationConfigDir -Filter "*_defaultConfigFile.xml"
        }
        
        if ([string]::IsNullOrEmpty($defaultFederationConfigFiles))
        {
            $defaultConfigFile = $null
        }
        elseif ($defaultFederationConfigFiles -is [System.IO.FileSystemInfo])
        {
            $defaultConfigFile = $defaultFederationConfigFiles.FullName
            #[xml]$config = Get-Content $defaultFederationConfigFiles.FullName
        }
        elseif ($defaultFederationConfigFiles -is [System.Array])
        {
            $defaultConfigFile = $defaultFederationConfigFiles | Out-GridView -Title "Select the default federation configuration file you want to use" -OutputMode Single | Select -ExpandProperty FullName
        }
        else
        {
            #We should never be here...
        }

        if ([string]::IsNullOrEmpty($defaultConfigFile))
        {
            if (Get-ADFSTkAnswer (Get-ADFSTkLanguageText confFederationDefaultConfigNotFoundQuestion -f $federationName) -DefaultYes)
            {
                $defaultConfigFile = $Global:ADFSTkPaths.defaultConfigFile
                #[xml]$config = Get-Content $Global:ADFSTkPaths.defaultConfigFile
            }
            else
            {
                Write-ADFSTkLog (Get-ADFSTkLanguageText confFederationDefaultConfigNotFound) -MajorFault
            }
        }

    }

    try {
        [xml]$defaultConfig = Get-Content $defaultConfigFile

        if ($defaultConfig.configuration.ConfigVersion -ne $CompatibleConfigVersion)
        {
            Write-ADFSTkLog (Get-ADFSTkLanguageText confDefaultConfigIncorrectVersion -f $defaultConfigFile,$defaultConfig.configuration.ConfigVersion,$CompatibleConfigVersion) -MajorFault
        }
    }
    catch {
        Write-ADFSTkLog (Get-ADFSTkLanguageText confCouldNotOpenFederationDefaultConfig -f $defaultConfigFile,$_) -MajorFault
    }

    [xml]$newConfig = $defaultConfig.Clone()


    Write-ADFSTkHost confStartMessage -Style Info -AddSpaceAfter
    Write-ADFSTkHost -WriteLine
    
    Set-ADFSTkConfigItem -XPath "configuration/metadataURL" `
                         -ExampleValue 'https://metadata.federationOperator.org/path/to/metadata.xml' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig
                       
    Set-ADFSTkConfigItem -XPath "configuration/signCertFingerprint" `
                         -ExampleValue '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/MetadataPrefix" `
                         -ExampleValue 'ADFSTk/CANARIE/INCOMMON/SWAMID' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig
                  
    Set-ADFSTkConfigItem -XPath "configuration/staticValues/co" `
                         -ExampleValue 'Canada, Sweden, USA' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/staticValues/c" `
                         -ExampleValue 'CA, SE, US' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/staticValues/o" `
                         -ExampleValue 'University Of Example' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/staticValues/schacHomeOrganization" `
                         -ExampleValue 'universityofexample.edu' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/staticValues/norEduOrgAcronym" `
                         -ExampleValue 'UoE' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/staticValues/ADFSExternalDNS" `
                         -ExampleValue 'adfs.universityofexample.edu' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    Set-ADFSTkConfigItem -XPath "configuration/eduPersonPrincipalNameRessignable" `
                         -ExampleValue 'false' `
                         -DefaultConfig $defaultConfig `
                         -NewConfig $newConfig

    
    #Adding eduPersonScopedAffiliation based on eduPersonAffiliation added with @schackHomeOrganization
    $epa = $newConfig.configuration.attributes.attribute | ? type -eq "urn:mace:dir:attribute-def:eduPersonAffiliation" 
    $epsa = $newConfig.configuration.attributes.attribute | ? type -eq "urn:mace:dir:attribute-def:eduPersonScopedAffiliation"
    

    $epa.ChildNodes | % {
        $node = $_.Clone()    
        $node.InnerText += "@$($newConfig.configuration.staticValues.schacHomeOrganization)"

        $epsa.AppendChild($node) | Out-Null
    }

    # various useful items for minting our configuration

    # user entered
    $myPrefix = (Select-Xml -Xml $newConfig -XPath "configuration/MetadataPrefix").Node.InnerText

    # For the ADFSTk functionality, we desire to associate certain cache files to certain things and bake a certain default location
 
    #(Select-Xml -Xml $config -XPath "configuration/WorkingPath").Node.'#text' = "$myADFSTkInstallDir" #Do we really need this?
    (Select-Xml -Xml $newConfig -XPath "configuration/SPHashFile").Node.InnerText = "$myPrefix-SPHashfile.xml"
    (Select-Xml -Xml $newConfig -XPath "configuration/MetadataCacheFile").Node.InnerText = "$myPrefix-metadata.cached.xml"

    $newConfigFile = Join-Path $Global:ADFSTkPaths.institutionDir "config.$myPrefix.xml"

    if (Test-path $newConfigFile)
    {
        #Should we recommend to do an upgrade instead?
        if (Get-ADFSTkAnswer -Caption (Get-ADFSTkLanguageText confConfigurationAlreadyExistsCaption) `
                             -Message (Get-ADFSTkLanguageText confOverwriteConfiguration) `
                             -DefaultYes)
        {
            $newConfigFileObject = Get-ChildItem $newConfigFile
            $myConfigFileBkpName = Join-Path $Global:ADFSTkPaths.institutionBackupDir ("{0}.{1}{2}" -f $newConfigFileObject.BaseName, (get-date -Format o).Replace(':','.'), $newConfigFileObject.Extension)

            Write-ADFSTkHost confCreatingNewConfigHere -f $newConfigFile -Style Value
            Write-ADFSTkHost confOldConfigurationFile -f $myConfigFileBkpName -Style Value

            Move-Item -Path $newConfigFile -Destination $myConfigFileBkpName

            $newConfig.Save($newConfigFile)
        } 
        else 
        {
            Write-ADFSTkLog (Get-ADFSTkLanguageText confDontOverwriteFileExit) -MajorFault
        }
    }
    else
    {
        Write-ADFSTkHost confInstConfigCreated -f $newConfigFile -Style Value
        $newConfig.Save($newConfigFile)
    }


    
    #Add $configFile to Main Config File

    Write-ADFSTkHost confAddFileToMainConfigMessage -Style Info -AddLinesOverAndUnder

    Add-ADFSTkConfigurationItem -ConfigurationItem $newConfigFile

    Write-ADFSTkHost -WriteLine -AddSpaceAfter

    Write-ADFSTkHost confConfigurationFileSavedHere -f $newConfigFile -Style Value
    
#region get-ADFSTkLocalManualSpSettings.ps1

    Write-ADFSTkHost confLocalManualSettingsMessage -Style Info -AddLinesOverAndUnder

    # Prepare our template for ADFSTkManualSPSettings to be copied into place, safely of course, after directories are confirmed to be there.

    #$myADFSTkManualSpSettingsDistroTemplateFile = Join-Path $Global:ADFSTkPaths.modulePath -ChildPath "config\default\en-US\get-ADFSTkLocalManualSpSettings-dist.ps1"
    $myADFSTkManualSpSettingsInstallTemplateFile = Join-Path $Global:ADFSTkPaths.institutionDir -ChildPath "get-ADFSTkLocalManualSpSettings.ps1"

    if (Test-path $myADFSTkManualSpSettingsInstallTemplateFile ) 
    {
        if (Get-ADFSTkAnswer -Caption (Get-ADFSTkLanguageText confInstLocalSPFileExistsCaption) `
                             -Message (Get-ADFSTkLanguageText confOverwriteInstLocalSPFileMessage -f $myADFSTkManualSpSettingsInstallTemplateFile))
        {
            $myADFSTkManualSpSettingsInstallTemplateFileObject = Get-ChildItem $myADFSTkManualSpSettingsInstallTemplateFile
           
            Write-ADFSTkHost confOverwriteInstLocalSPFileConfirmed -f $myADFSTkManualSpSettingsInstallTemplateFile -Style Value

            $mySPFileBkpName = Join-Path $Global:ADFSTkPaths.institutionBackupDir ("{0}.{1}{2}" -f $myADFSTkManualSpSettingsInstallTemplateFileObject.BaseName, (get-date -Format o).Replace(':','.'), $myADFSTkManualSpSettingsInstallTemplateFileObject.Extension)

            Write-ADFSTkHost confCreateNewInstLocalSPFile -f $Global:ADFSTkPaths.defaultInstitutionLocalSPFile -Style Value
            Write-ADFSTkHost confOldInstLocalSPFile -f $mySPFileBkpName -Style Value

            # Make backup
            Move-Item -Path $myADFSTkManualSpSettingsInstallTemplateFile -Destination $mySPFileBkpName

            Copy-ADFSTkFile -Path $Global:ADFSTkPaths.defaultInstitutionLocalSPFile -Destination $myADFSTkManualSpSettingsInstallTemplateFile
        } 
        else 
        {
            Write-ADFSTkHost confDontOverwriteFileJustProceed -Style Info -AddSpaceAfter
        }
    }
    else
    {
        Write-ADFSTkHost confNoExistingFileSaveTo -f $myADFSTkManualSpSettingsInstallTemplateFile -Style Value -AddSpaceAfter
        Copy-ADFSTkFile -Path $Global:ADFSTkPaths.defaultInstitutionLocalSPFile -Destination $myADFSTkManualSpSettingsInstallTemplateFile
    }

#endregion

#region Get-ADFSTkLocalTransformRules.ps1

Write-ADFSTkHost confLocalTransformRulesMessage -Style Info -AddLinesOverAndUnder -f $Global:ADFSTkPaths.institutionLocalTransformRulesFile

# Prepare our template for ADFSTkLocalTransformRules to be copied into place, safely of course, after directories are confirmed to be there.

if (Test-path $Global:ADFSTkPaths.institutionLocalTransformRulesFile ) 
{
    if (Get-ADFSTkAnswer -Caption (Get-ADFSTkLanguageText confLocalTransformRulesFileExistsCaption) `
                         -Message (Get-ADFSTkLanguageText confOverwriteInstLocalSPFileMessage -f $Global:ADFSTkPaths.institutionLocalTransformRulesFile))
    {
        $myADFSTkLocalTransformRulesInstallTemplateFileObject = Get-ChildItem $Global:ADFSTkPaths.institutionLocalTransformRulesFile
        Write-ADFSTkHost confOverwriteLocalTransformRulesFileConfirmed -f $Global:ADFSTkPaths.institutionLocalTransformRulesFile -Style Value

        $myTRFileBkpName = Join-Path $Global:ADFSTkPaths.institutionBackupDir ("{0}.{1}{2}" -f $myADFSTkLocalTransformRulesInstallTemplateFileObject.BaseName, (get-date -Format o).Replace(':','.'), $myADFSTkLocalTransformRulesInstallTemplateFileObject.Extension)

        Write-ADFSTkHost confCreateNewInstLocalTransformRuleFile -f $Global:ADFSTkPaths.defaultInstitutionLocalTransformRulesFile -Style Value
        Write-ADFSTkHost confOldInstLocalSPFile -f $myTRFileBkpName -Style Value

        # Make backup
        Move-Item -Path $Global:ADFSTkPaths.institutionLocalTransformRulesFile -Destination $myTRFileBkpName
        # Copy dist file
        Copy-ADFSTkFile -Path $Global:ADFSTkPaths.defaultInstitutionLocalTransformRulesFile -Destination $Global:ADFSTkPaths.institutionLocalTransformRulesFile
    } 
    else 
    {
        Write-ADFSTkHost confDontOverwriteFileJustProceed -Style Info -AddSpaceAfter
    }
}
else
{
    Write-ADFSTkHost confNoExistingFileSaveTo -f $Global:ADFSTkPaths.institutionLocalTransformRulesFile -Style Value -AddSpaceAfter
    Copy-ADFSTkFile -Path $Global:ADFSTkPaths.defaultInstitutionLocalTransformRulesFile -Destination $Global:ADFSTkPaths.institutionLocalTransformRulesFile
}

#endregion
    
    Write-ADFSTkHost confHowToRunMetadataImport -Style Info -AddLinesOverAndUnder

    if (Get-ADFSTkAnswer (Get-ADFSTkLanguageText confCreateScheduledTask))
    {
        $stAction = New-ScheduledTaskAction -Execute 'Powershell.exe' `
                                            -Argument "-NoProfile -WindowStyle Hidden -Command &{Sync-ADFSTkAggregates}"

        $stTrigger =  New-ScheduledTaskTrigger -Daily -DaysInterval 1 -At (Get-Date)
        $stSettings = New-ScheduledTaskSettingsSet -Disable -MultipleInstances IgnoreNew -ExecutionTimeLimit ([timespan]::FromHours(12))

        Register-ScheduledTask -Action $stAction `
                               -Trigger $stTrigger `
                               -TaskName (Get-ADFSTkLanguageText confImportMetadata) `
                               -Description (Get-ADFSTkLanguageText confTHisSchedTaskWillDoTheImport) `
                               -RunLevel Highest `
                               -Settings $stSettings `
                               -TaskPath "\ADFSToolkit\"
    }

    Write-ADFSTkHost -WriteLine -AddSpaceAfter
    Write-ADFSTkHost cAllDone -Style Done

<#
.SYNOPSIS
Create or migrats an ADFSToolkit configuration file per aggregate.
 
.DESCRIPTION
 
This command creates a new or migrates an older configuration to a newer one when invoked.
 
How this Powershell Cmdlet works:
  
When loaded we:
   - seek out a template configuration in $Module-home/config/default/en/config.ADFSTk.default*.xml
   -- where * is the language designation, usually 'en'
   - if invoked with -MigrateConfig, the configuration attempts to detect the previous answers as defaults to the new ones where possible
 
    
.INPUTS
 
zero or more inputs of an array of string to command
 
.OUTPUTS
 
configuration file(s) for use with current ADFSToolkit that this command is associated with
 
.EXAMPLE
new-ADFSTkConfiguration
 
.EXAMPLE
 
"C:\ADFSToolkit\0.0.0.0\config\config.file.xml" | new-ADFSTkConfiguration
 
.EXAMPLE
 
"C:\ADFSToolkit\0.0.0.0\config\config.file.xml","C:\ADFSToolkit\0.0.0.0\config\config.file2.xml" | new-ADFSTkConfiguration
 
#>


}



# SIG # Begin signature block
# MIId2QYJKoZIhvcNAQcCoIIdyjCCHcYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUydRjdiJizispXcaKrwWoucHl
# jiWgghisMIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
# BAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNV
# BAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN
# MTQwMTAxMDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAO
# BgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdv
# RGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
# AQEAv3FiCPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjH
# MgGxBT4HTu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6
# or6KFWp/3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T
# 3UYH3go+6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6e
# MAo5zvGIgPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51ir
# uF9G/M7EGwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB
# /zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/e
# MB8GA1UdIwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgw
# JjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQr
# MCkwJ6AloCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNV
# HSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2Rh
# ZGR5LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEack
# e+1bMc8dH2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVn
# OQoWCcWgOJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYgg
# HFCJyNwq9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY
# 7NmuHDKOKHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzds
# yqUvMQg3qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcY
# QFHfjDCmrzCCBNAwggO4oAMCAQICAQcwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNV
# BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow
# GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9v
# dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjAeFw0xMTA1MDMwNzAwMDBaFw0z
# MTA1MDMwNzAwMDBaMIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTET
# MBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4x
# LTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEz
# MDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAt
# IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueDLENSvdr3Uk2Lr
# MGS4gQhswwTZYheOL/8+Zc+PzmLmPFIc2hZFS1WreGtjg2KQzg9pbJnIGhSLTMxF
# M+qI3J6jryv+gGGdeVfEzy70PzA8XUf8mha8wzeWQVGOEUtU+Ci+0Iy+8DA4HvOw
# JvhmR2Nt3nEmR484R1PRRh2049wA6kWsvbxx2apvANvbzTA6eU9fTEf4He9bwsSd
# YDuxskOR2KQzTuqz1idPrSWKpcb01dCmrnQFZFeItURV1C0qOj74uL3pMgoClGTE
# FjpQ8Uqu53kzrwwgB3/o3wQ5wmkCbGNS+nfBG8h0h8i5kxhQVDVLaU68O9NJLh/c
# wdJS+wIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
# AQYwHQYDVR0OBBYEFEDCvSeOzDSDMKIz1/tss/C0LIDOMB8GA1UdIwQYMBaAFDqa
# hQcQZyi27/a9BUFuIMGU2g/eMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6
# Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LWcyLmNybDBGBgNVHSAEPzA9MDsGBFUd
# IAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBv
# c2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEACH5skxDIOLiWqZBL/6FfTwTvbD6c
# iAbJUI+mc/dXMRu+vOQv2/i601vgtOfmeWIODKLXamNzMbX1qEikOwgtol2Q17R8
# JU8RVjDEtkSdeyyd5V7m7wxhqr/kKhvuhJ64g33BQ85EpxNwDZEf9MgTrYNg2dhy
# qHMkHrWsIg7KF4liWEQbq4klAQAPzcQbYttRtNMPUSqb9Lxz/HbONqTN2dgs6q6b
# 9SqykNFNdRiKP4pBkCN9W0v+pANYm0ayw2Bgg/h9UEHOwqGQw7vvAi/SFVTuRBXZ
# Cq6nijPtsS12NibcBOuf92EfFdyHb+5GliitoSZ9CgmnLgSjjbz4vAQwATCCBP4w
# ggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAwcjELMAkG
# A1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRp
# Z2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRp
# bWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAwMDBaMEgx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UEAxMX
# RGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
# ggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4dyG+RawyW
# 5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnHbQk9vmp2
# h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1LsVDmQTo3
# VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpKjIjF9zBa
# +RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756WwogL0sJyZWn
# jbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNVHQ8BAf8E
# BAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBBBgNV
# HSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRp
# Z2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIlssgXNW4w
# HQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgwMqAwoC6G
# LGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMuY3JsMDKg
# MKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNy
# bDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQwDQYJKoZI
# hvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIlxHBZvhSg
# 5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie38+dSn5On
# 7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTzZTlwS/Oc
# 1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0yOIHa9GCi
# urRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4TrweOjSaH6
# zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUcMIIEBKADAgECAghlwdCS
# Sbw71zANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Fy
# aXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29t
# LCBJbmMuMS0wKwYDVQQLEyRodHRwOi8vY2VydHMuZ29kYWRkeS5jb20vcmVwb3Np
# dG9yeS8xMzAxBgNVBAMTKkdvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgLSBHMjAeFw0yMTAxMTkxODM3MzZaFw0yMjAzMDgxODU4MDBaMF4xCzAJ
# BgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExFTAT
# BgNVBAoTDENBTkFSSUUgSW5jLjEVMBMGA1UEAxMMQ0FOQVJJRSBJbmMuMIIBIjAN
# BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2YXwoxaok5jdbi6MkosZ8Gjo3/2Q
# C/T+kr45QmgQNprraKKxIJ81D/B5ziHLzEYBDD5qWmfHoDPdwZsfXeNcaGq7EKQj
# dw4WDqPm931pz7nFbacW7pdjhXj7+t5sP7r6/napL+G/3904PopUG6bDaJ274fTC
# hBb/D5/ZKI9Mklfqsc9+D8U1QHuoP/6Xpd/94vX6opQpyBHMeM4P/jSgXjlkTkrO
# KF6NyLwY1a7p5s/mLonkq+/E6iBOoQ/CRdqtcCsHzAd/se3RF2QLrPVrSFP6iEwE
# 7RHzvUAIK62C+BdTCzfqLEqfJsuXgjo5y00HOO6ue+Fd80IbCB1u8gVy3QIDAQAB
# o4IBhTCCAYEwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNV
# HQ8BAf8EBAMCB4AwNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5nb2RhZGR5
# LmNvbS9nZGlnMnM1LTYuY3JsMF0GA1UdIARWMFQwSAYLYIZIAYb9bQEHFwIwOTA3
# BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
# c2l0b3J5LzAIBgZngQwBBAEwdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhho
# dHRwOi8vb2NzcC5nb2RhZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0
# aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0j
# BBgwFoAUQMK9J47MNIMwojPX+2yz8LQsgM4wHQYDVR0OBBYEFFD5zINp5mEvJe65
# msd8HlZK4M+QMA0GCSqGSIb3DQEBCwUAA4IBAQBmmyS7tPYHWB7e2TG6SeNOPGSI
# l8FSxPxzXJwKU4ITWh50kojCNsU7Jm6zP5WLJqcBbsLNXNnzAb8g0YJM0f+PkSI6
# ECaS6x8tUAAWJVgCCjKnRZn6rctEAKYCJBjdvrHDMSjFiRjQ/KqdyjPuQvEzU7Dt
# ID1X3Wmq19k5izOsiEHIMQ/GGTHdJqnUe63Anm4DHgHRy2D0LvxzNAo96rcxcfwm
# c8/dwgJYfA8ecKKnjSYsUDCytvDIVPMujUjeaCpw//BBErnUc18qKMGdjeGCc8sn
# uVC/acYZ4gyrOOOMNa+V3I0GA6NdRvGOLqeF1tXBbSzbpR2HCoQJ0O1x7MMTMIIF
# MTCCBBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkqhkiG9w0BAQsFADBlMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
# Q0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAwWjByMQswCQYDVQQGEwJV
# UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
# Y29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1w
# aW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/d
# qbqCmcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+
# CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+wKL1oODeIj8O/36V+/Oj
# uiI+GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91z3FyTgqt30A6XLdR4aF5
# FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66
# mA+Ef58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9olMqT4UdxB08r8/arBD1
# 3ays6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS24SAd/imu0uRhpbKiJbLI
# FzVuMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQI
# MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkG
# CCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu
# Y29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln
# aUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRw
# Oi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3Js
# MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
# SURSb290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUF
# BwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAsGCWCGSAGG/WwHATAN
# BgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpjerN4zwY3QITvS4S/ys8D
# Av3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg33akOpMP+LLR2HwZYuhe
# giUexLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIs
# rymJ5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuWwPRYaQ18yAGxuSh1t5lj
# hSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO2
# 4XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaOUjGCBJcwggSTAgEBMIHB
# MIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv
# dHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0
# dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28g
# RGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyAghlwdCSSbw7
# 1zAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG
# 9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIB
# FTAjBgkqhkiG9w0BCQQxFgQUKGnf8oGsjf0UnYvHk6kFZDwQU38wDQYJKoZIhvcN
# AQEBBQAEggEAqbunhBpoYFKKr1uCsrL0iySvlZGzZHb1V56iwubjdNyFE2lxVyb+
# aK91T25HVpgi5OX5T2IIoi9nUctfrhxj8oygikBcpzvFu7fUbRH5F4G67apf7opW
# hOr0WaPMxmbnT57vo3WL1XQ8nOH2xveYIIEvfxJ0VBE3AHAanIsgeIsTrB3rOPOn
# hI4Ss50+QClJ9kq39xs0kM0u6VlteyHvCX+L1dMJMaxWoZ8yOKo5edz+ygbY3Eeh
# PyD4xgQefmk4mzMzgdJjfVM+9KPdX+uuiYrlfzka19hZc6a827A8UMXTrs5LH0qX
# GNmwE4Bo2MY8F0QseTG0C9L3xmGl+FgblqGCAjAwggIsBgkqhkiG9w0BCQYxggId
# MIICGQIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT
# SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBAhANQkrgvjqI/2BAIc4UAPDd
# MA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq
# hkiG9w0BCQUxDxcNMjEwMzEwMjIyMzUwWjAvBgkqhkiG9w0BCQQxIgQgibNKze18
# 4CnG2rZDW21L+YKqz5zJYh0jCbCDhiTJEIUwDQYJKoZIhvcNAQEBBQAEggEATU84
# P7D6J5pFW9GryFsaxrVdzvxlrjcX+j2fSCvqD0etqNJajho/kZbg/VPLYk9N5e8s
# XKEnA8q/v6JyJBUbOU3scJr+aVJtvbESVISbGXDK1+9DfkBNF6vYLp+t3U9Y/PJD
# ztRoKaPMdJReluCdKNzpQS8k4XjIGIAC5rpUpvM03CbeeJyaJobC7A9k0lla994f
# PglTXdi8e/E0JBVUAslmgeS68TjnTnWj1N3Od5wVfJW00zT/L/il3WIcBszLiVIB
# jrfZkZPZtpXz7iUysxnpmizcThHN3YAappubKRJeEqiVcVLFTSzNIYU6j/RfSmPr
# ylvZ1ps/g04WU2Aqhg==
# SIG # End signature block