ADLAB PowerShell source file: buildup-mim.ps1

(C) Ondrej Sevecek, 2019 - www.sevecek.com, ondrej@sevecek.com



$libDir = Split-Path -parent $MyInvocation.MyCommand.Definition
& "$libDir\lib-common.ps1" -defaultConfig -rootDir $libDir -outFile mimLib
& "$libDir\lib-modifyActions.ps1"
& "$libDir\lib-buildup.ps1"

$vmName = $args[0]

DBG ('MIM/FIM installation library')
Redirect-TempToOutput
Load-VMConfig

Find-MarkedVolumes
$installSourceMediaMIM = '!sevecek-installation-source-media-ExchangeSharePoint.txt'
$installMediaVolumeMIM = Find-MarkedVolume $installSourceMediaMIM 3
DBG ('FIM/MIM install media volume: {0}' -f $installMediaVolumeMIM)


$appTag = 'mim'
$appConfig = $vmConfig.$appTag
$firstAppHost = Get-FirstAppHostInInstance $appTag $appConfig.instance 'waitParams'
$firstAppConfig = (Get-FirstAppHostInInstance $appTag $appConfig.instance 'vmConfig').$appTag
$firstAppHostInInstance = Check-FirstAppHostInInstance $appTag $appConfig.instance
$firstAppHostFQDN = Get-FirstAppHostInInstance $appTag $appConfig.instance 'fqdn'

if (-not $firstAppHostInInstance) {

  $allPreviousAppHosts = Get-AllAppHostsOfInstance $appTag $appConfig.instance 'waitParams' -onlyBeforeMyHostName $vmConfig.hostName
}



if (Is-Null $appConfig) { DBG ('Invalid appCofnig, exiting'); exit }
#====================
#====================


#
#

DBG ('Backup IIS site/apppool state before buildup')
$iisSitesBackup = Get-IISSites -structured $true
$iisAppPoolBackup = Get-IISAppPools -structured $true

#
#



################
#
# Note: Main code
#

if ($global:thisOSVersionNumber -lt 6.1) { 

  DBGIF $MyInvocation.MyCommand.Name { $global:thisOSVersionNumber -lt 6.3 }
  exit
}

DBG ('Get the roles required')

$roleSyncNode = $firstAppConfig.SelectSingleNode('./svc[@appTag="sync"]')
DBG ('We should install synchronization service: {0}' -f (Is-NonNull $roleSyncNode))

$roleServiceNode = $firstAppConfig.SelectSingleNode('./svc[@appTag="service"]')
DBG ('We should install service and portal service: {0}' -f (Is-NonNull $roleServiceNode))

$roleMANode = $firstAppConfig.SelectSingleNode('./svc[@appTag="ma"]')
DBG ('We should counfigure MIM MA: {0}' -f (Is-NonNull $roleMANode))

$rolePwdRegNode = $firstAppConfig.SelectSingleNode('./svc[@appTag="pwdreg"]')
DBG ('We should install password registration (pwdreg) portal: {0}' -f (Is-NonNull $rolePwdRegNode))

$rolePwdRstNode = $firstAppConfig.SelectSingleNode('./svc[@appTag="pwdrst"]')
DBG ('We should install password reset (pwdrst) portal: {0}' -f (Is-NonNull $rolePwdRstNode))


DBG ('Determine the DB server')
$dbInstance = $firstAppConfig.sql.instance
DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $dbInstance }
$dbServerFQDN = Get-FirstAppHostInInstance 'sql' $dbInstance 'fqdn'
$dbServer = '{0}\{1}' -f $dbServerFQDN, $dbInstance
DBG ('DB server determined as: {0}' -f $dbServer)

DBG ('Determine already installed services')
$isInstalledSyncSvc = Get-WmiQuerySingleObject '.' 'SELECT * FROM Win32_Product WHERE Name = "Microsoft Identity Manager Synchronization Service"'
$isInstalledServiceSvc = Get-WmiQuerySingleObject '.' 'SELECT * FROM Win32_Product WHERE Name = "Microsoft Identity Manager Service"'
DBG ('Installed services: sync = {0} | svc = {1}' -f (Is-NonNull $isInstalledSyncSvc), (Is-NonNull $isInstalledServiceSvc))

#
#

if ((Is-NonNull $roleSyncNode) -and (Is-Null $isInstalledSyncSvc)) {

  DBG ('Going to prepare sync service installation')
  $syncSvcMSI = Join-Path $installMediaVolumeMIM 'MIM2016-SP1\Synchronization Service\Synchronization Service.msi'
  DBG ('Sync service MSI path determined: {0}' -f $syncSvcMSI)
  DBGIF $MyInvocation.MyCommand.Name { -not (Test-Path $syncSvcMSI) }

  if (Test-Path $syncSvcMSI) {

    $syncSvcLog = Get-DataFileApp 'mim-sync-service-install' $null '.log'

    $syncSvcSAM = Get-SAMLogin $roleSyncNode.login $roleSyncNode.domain

    $syncGroupAdmSAM = Get-SAMLogin $firstAppConfig.app.aGroup $firstAppConfig.app.iDomain

    $syncGroupOp = $firstAppConfig.SelectSingleNode('./group[@appTag="op"]')
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $syncGroupOp }
    $syncGroupOpSAM = Get-SAMLogin $syncGroupOp.login $syncGroupOp.domain

    $syncGroupJoin = $firstAppConfig.SelectSingleNode('./group[@appTag="join"]')
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $syncGroupJoin }
    $syncGroupJoinSAM = Get-SAMLogin $syncGroupJoin.login $syncGroupJoin.domain

    $syncGroupBwse = $firstAppConfig.SelectSingleNode('./group[@appTag="bwse"]')
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $syncGroupBwse }
    $syncGroupBwseSAM = Get-SAMLogin $syncGroupBwse.login $syncGroupBwse.domain

    $syncGroupPwd = $firstAppConfig.SelectSingleNode('./group[@appTag="pwd"]')
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $syncGroupPwd }
    $syncGroupPwdSAM = Get-SAMLogin $syncGroupPwd.login $syncGroupPwd.domain

    DBG ('We are going to install the sync service MSI')
    Run-Process msiexec ('/i "{0}" /qn /norestart /l*v "{1}" STORESERVER="{2}" SQLINSTANCE="{3}" SQLDB="MIM_Sync_{4}" SERVICEACCOUNT="{5}" SERVICEDOMAIN="{6}" SERVICEPASSWORD="{7}" GROUPADMINS="{8}" GROUPOPERATORS="{9}" GROUPACCOUNTJOINERS="{10}" GROUPBROWSE="{11}" GROUPPASSWORDSET="{12}" FIREWALL_CONF=1' -f $syncSvcMSI, $syncSvcLog, $dbServerFQDN, $dbInstance, $appConfig.instance, $syncSvcSAM.Split('\')[1], $syncSvcSAM.Split('\')[0], $roleSyncNode.pwd, $syncGroupAdmSAM, $syncGroupOpSAM, $syncGroupJoinSAM, $syncGroupBwseSAM, $syncGroupPwdSAM)

    $fimSyncService = Get-WmiQuerySingleObject '.' 'SELECT * FROM Win32_Service WHERE Name = "FIMSynchronizationService"'
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $fimSyncService }

    if (Is-NonNull $fimSyncService) {

      DBGIF ('Weird service start mode: {0}' -f $fimSyncService.StartMode) { $fimSyncService.StartMode -ne 'Auto' }
      DBGIF ('Weird service state: {0}' -f $fimSyncService.State) { $fimSyncService.State -ne 'Running' }
      DBGIF ('Weird service path: {0}' -f $fimSyncService.PathName) { $fimSyncService.PathName -ne ('"{0}"' -f (Join-Path $env:ProgramFiles 'Microsoft Forefront Identity Manager\2010\Synchronization Service\Bin\miiserver.exe')) }

      $miisClientEXE = Join-Path $env:ProgramFiles 'Microsoft Forefront Identity Manager\2010\Synchronization Service\UIShell\miisclient.exe'
      DBG ('Create links to the sync service: {0}' -f $miisClientEXE)
      DBGIF ('The sync UI exe does not exist: {0}' -f $miisClientEXE) { -not (Test-Path -Literal $miisClientEXE) }

      if (Test-Path -Literal $miisClientEXE) {

        $miisClientLINK = Join-Path $env:PUBLIC 'Desktop\MIM Sync.lnk'
        DBG ('Create the sync UI link: {0} | {1}' -f $miisClientEXE, $miisClientLINK)
        DBGSTART
        $shell = New-Object -Com WScript.Shell
        $shortcut = $shell.CreateShortcut($miisClientLINK)
        $shortcut.TargetPath = $miisClientEXE
        $shortcut.Save()
        DBGER $MyInvocation.MyCommand.Name $error
        DBGEND
      }

      $miisKeyMgmtUtility = Join-Path $env:ProgramFiles 'Microsoft Forefront Identity Manager\2010\Synchronization Service\Bin\miiskmu.exe'
      DBG ('Backup the database encryption key: {0}' -f $miisKeyMgmtUtility)
      DBGIF $MyInvocation.MyCommand.Name { -not (Test-Path $miisKeyMgmtUtility) }

      if (Test-Path $miisKeyMgmtUtility) {

        $miisKeyMgmtUtilityBackup = Get-DataFileApp 'miis-sync-service-encryption-key-backup' $null '.bin'
        Run-Process $miisKeyMgmtUtility ('/e "{0}" "/u:{1}" "{2}" /q' -f $miisKeyMgmtUtilityBackup, $syncSvcSAM, $roleSyncNode.pwd)
      }
    }
  }
}

#
#

$msiPwdRegAddLocal = ''
$msiPwdRegParams = 'REQUIRE_REGISTRATION_INFO=0'

if (Is-NonNull $rolePwdRegNode) {

  DBG ('Preparing installation for the Password Reset Registration Portal')
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $rolePwdRegNode.mimSvc }
  DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $rolePwdRegNode.mimSvc.addr }
  
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $roleServiceNode.mimSvc }
  DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $roleServiceNode.mimSvc.addr }

  $msiPwdRegAddLocal = ',RegistrationPortal'
  
  $msiPwdRegSAM = Get-SAMLogin $rolePwdRegNode.login $rolePwdRegNode.domain
  $msiPwdRegParams = 'REQUIRE_REGISTRATION_INFO=1 REGISTRATION_HOSTNAME="{0}" REGISTRATION_PORTAL_URL="https://{0}" REGISTRATION_PORT=80 IS_REGISTRATION_EXTRANET=Extranet REGISTRATION_FIREWALL_CONF=0 REGISTRATION_ACCOUNT="{1}" REGISTRATION_ACCOUNT_PASSWORD="{2}" REGISTRATION_SERVERNAME="{3}"' -f $rolePwdRegNode.mimSvc.addr, $msiPwdRegSAM, $rolePwdRegNode.pwd, $roleServiceNode.mimSvc.addr

  DBG ('PWD REG params defined: {0}' -f $msiPwdRegAddLocal)
}

#
#

$msiPwdRstAddLocal = ''
$msiPwdRstParams = 'REQUIRE_RESET_INFO=0'

if ((Is-NonNull $rolePwdRstNode) -and (Is-Null $isInstalledServiceSvc)) {

  DBG ('Preparing installation for the Password Reset Portal')
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $rolePwdRstNode.mimSvc }
  DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $rolePwdRstNode.mimSvc.addr }
  
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $roleServiceNode.mimSvc }
  DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $roleServiceNode.mimSvc.addr }

  $msiPwdRstAddLocal = ',ResetPortal'

  $msiPwdRstSAM = Get-SAMLogin $rolePwdRstNode.login $rolePwdRstNode.domain
  $msiPwdRstParams = 'REQUIRE_RESET_INFO=1 IS_RESET_EXTRANET=Extranet RESET_FIREWALL_CONF=0 RESET_HOSTNAME="{0}" RESET_PORT=80 RESET_ACCOUNT="{1}" RESET_ACCOUNT_PASSWORD="{2}" RESET_SERVERNAME="{3}"' -f $rolePwdRstNode.mimSvc.addr, $msiPwdRstSAM, $rolePwdRstNode.pwd, $roleServiceNode.mimSvc.addr

  DBG ('PWD RST params defined: {0}' -f $msiPwdRstParams)
}

#
#

if (Is-NonNull $roleServiceNode) {

  DBG ('Going to prepare MIM service installation')
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $roleServiceNode.mimSvc }
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $roleMANode }

  $serviceSvcMSI = Join-Path $installMediaVolumeMIM 'MIM2016-SP1\Service and Portal\Service and Portal.msi'
  DBG ('MIM Service MSI path determined: {0}' -f $serviceSvcMSI)
  DBGIF $MyInvocation.MyCommand.Name { -not (Test-Path $serviceSvcMSI) }

  if (Test-Path $serviceSvcMSI) {

    $serviceSvcLog = Get-DataFileApp 'mim-service-install' $null '.log'

    $serviceSvcSAM = Get-SAMLogin $roleServiceNode.login $roleServiceNode.domain
    $serviceSvcMASAM = Get-SAMLogin $roleMANode.login $roleMANode.domain

    DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $roleServiceNode.mimSvc.addr }
    DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $roleServiceNode.mimSvc.spSite }


    Define-DnsHostAliases -dnsAliases $roleServiceNode.mimSvc.addr -addHosts $true -disableLoopbackCheck $true

    if (Is-ValidString $rolePwdRegNode.mimSvc.addr) {

      Define-DnsHostAliases -dnsAliases $rolePwdRegNode.mimSvc.addr -addHosts $true -disableLoopbackCheck $true
    }

    if (Is-ValidString $rolePwdRstNode.mimSvc.addr) {

      Define-DnsHostAliases -dnsAliases $rolePwdRstNode.mimSvc.addr -addHosts $true -disableLoopbackCheck $false
    }


    DBG ('Ensure the SP Timer service is running')
    DBGSTART
    Get-Service sptimer* | ? { $_.Status -ne 'Running' } | % { DBGIF ('The SharePoint Timer service is not running before going to install MIM Service and Portal: {0} | {1}' -f $_.Name, $_.Status) { $true } ; Start-Service $_.Name -Confirm:$false }
    DBGER $MyInvocation.MyCommand.Name $error
    DBGEND

    DBG ('We are going to install the Service MSI')
    DBGIF ('As it seems the certificate subject must be ForefrontIdentityManager even for MIM 2016 SP1') { $roleServiceNode.mimSvc.certSubject -ne 'ForefrontIdentityManager' }
    Run-Process msiexec ('/i "{0}" /qb /norestart /l*v "{1}" ADDLOCAL="ConfigurationBackup,CommonServices,WebPortals{13}{14}" SQLSERVER_SERVER="{2}" SQLSERVER_DATABASE="MIM_Service_{3}" EXISTINGDATABASE=0 SERVICE_ACCOUNT_NAME="{4}" SERVICE_ACCOUNT_DOMAIN="{5}" SERVICE_ACCOUNT_PASSWORD="{6}" SERVICE_ACCOUNT_EMAIL="{7}" CERTIFICATE_NAME="{8}" SERVICEADDRESS="{9}" SYNCHRONIZATION_SERVER="{10}" SYNCHRONIZATION_SERVER_ACCOUNT="{11}" SHAREPOINT_URL="{12}" SHAREPOINTUSERS_CONF=1 SHAREPOINTTIMEOUT=660 FIREWALL_CONF=1 SQMOPTINSETTING=0 MAIL_SERVER=localhost MAIL_SERVER_IS_EXCHANGE=0 MAIL_SERVER_USE_SSL=0 POLL_EXCHANGE_ENABLED=0 {15} {16}' -f $serviceSvcMSI, $serviceSvcLog, $dbServer, $appConfig.instance, $serviceSvcSAM.Split('\')[1], $serviceSvcSAM.Split('\')[0], $roleServiceNode.pwd, $roleServiceNode.mail, $roleServiceNode.mimSvc.certSubject, $roleServiceNode.mimSvc.addr, $global:thisComputerFQDN, $serviceSvcMASAM, $roleServiceNode.mimSvc.spSite, $msiPwdRegAddLocal, $msiPwdRstAddLocal, $msiPwdRegParams, $msiPwdRstParams)

    $fimService = Get-WmiQuerySingleObject '.' 'SELECT * FROM Win32_Service WHERE Name = "FIMService"'
    DBGIF $MyInvocation.MyCommand.Name { Is-Null $fimService }

    if (Is-NonNull $fimService) {

      DBGIF ('Weird service start mode: {0}' -f $fimService.StartMode) { $fimService.StartMode -ne 'Auto' }
      DBGIF ('Weird service state: {0}' -f $fimService.State) { $fimService.State -ne 'Running' }
      DBGIF ('Weird service path: {0}' -f $fimService.PathName) { $fimService.PathName -ne ('"{0}"' -f (Join-Path $env:ProgramFiles 'Microsoft Forefront Identity Manager\2010\Service\Microsoft.ResourceManagement.Service.exe')) }

      $mimPortalIcon = Join-Path $env:SystemRoot 'System32\shell32.dll,17'
      $mimPortalURL = '{0}/IdentityManagement' -f $roleServiceNode.mimSvc.spSite.Trim('/')
      $mimPortalLINK = Join-Path $env:PUBLIC 'Desktop\MIM Portal.lnk'

      DBG ('Create the MIM Portal link: {0} | {1} | {2}' -f $mimPortalURL, $mimPortalLINK, $mimPortalIcon)
      DBGSTART
      $shell = New-Object -Com WScript.Shell
      $shortcut = $shell.CreateShortcut($mimPortalLINK)
      $shortcut.TargetPath = $mimPortalURL
      $shortcut.IconLocation = $mimPortalIcon
      $shortcut.Save()
      DBGER $MyInvocation.MyCommand.Name $error
      DBGEND
    }

    if (Is-NonNull $rolePwdRegNode) {

      DBG ('Disabling Kernel Mode authentication for the PWD REG web site')
      Run-Process (Join-Path $env:SystemRoot 'System32\inetsrv\appcmd') 'set config "MIM Password Registration Site" /section:windowsAuthentication /useKernelMode:false /commit:appHost'
    }
  }
}


#
#

Restore-IISSiteAndPoolState -iisSitesBackup $iisSitesBackup -iisAppPoolBackup $iisAppPoolBackup

#
#


DBG ('Throw up any remaining errors')
DBGSTART; DBGEND




# SIG # Begin signature block
# MIIc/QYJKoZIhvcNAQcCoIIc7jCCHOoCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDHDyo/DHbHI+zu
# g1HH2wC3b3hvLmMvWurGP+hFcyGK3aCCGAQwggTlMIIDzaADAgECAhA5vUKe0oFu
# utW8yQO0umXnMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNVBAYTAklMMRYwFAYDVQQK
# Ew1TdGFydENvbSBMdGQuMSkwJwYDVQQLEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9u
# IEF1dGhvcml0eTEjMCEGA1UEAxMaU3RhcnRDb20gQ2xhc3MgMiBPYmplY3QgQ0Ew
# HhcNMTYxMjAxMTU1MTEzWhcNMTgxMjAxMTU1MTEzWjBRMQswCQYDVQQGEwJDWjEa
# MBgGA1UECAwRSmlob21vcmF2c2t5IEtyYWoxDTALBgNVBAcMBEJybm8xFzAVBgNV
# BAMMDk9uZHJlaiBTZXZlY2VrMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
# AQEAr9E9hNj06bash9JX97kpsqK9Z/ciOBC6trI4nvlW9CPwhKBTb5wArhxLYZBG
# 9jWPWrdy1nL/cm5qMqBb/mogYwMwvEYWMvsIOOVn6HD9lVhNAovD6PHz0ziBBKIs
# zXTjyUPQaoIlIELovz967m78HJdUZJGxqhluAsS9o9/fEzA7XXUhUuqRKsetuZV/
# Asfh5sOveeoRsbeW4daTWvtz3TJuULL0w43LNVYJkd6LL8cegvLPVZUe1N7skvid
# EvntdlowQsJlqFdrH3SGKIPKA6ObcY8SZWkEQSbVBF8Kum1UT+jN0gm+84FwOg5W
# qKx+VvTK2ljVWnPrCD0Zzu2oIQIDAQABo4IBkzCCAY8wDgYDVR0PAQH/BAQDAgeA
# MBMGA1UdJQQMMAoGCCsGAQUFBwMDMAkGA1UdEwQCMAAwHQYDVR0OBBYEFG2vSo3N
# hQWILeUs0oN9XzHTejcfMB8GA1UdIwQYMBaAFD5ik5rXxxnuPo9JEIVVFSDjlIQc
# MG0GCCsGAQUFBwEBBGEwXzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Auc3RhcnRz
# c2wuY29tMDcGCCsGAQUFBzAChitodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0
# cy9zY2EuY29kZTIuY3J0MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuc3Rh
# cnRzc2wuY29tL3NjYS1jb2RlMi5jcmwwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5z
# dGFydHNzbC5jb20vMFEGA1UdIARKMEgwCAYGZ4EMAQQBMDwGCysGAQQBgbU3AQIF
# MC0wKwYIKwYBBQUHAgEWH2h0dHBzOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kw
# DQYJKoZIhvcNAQELBQADggEBAJuRiEvHtIYSpsmMkPhTz4QOOShN3p5KWdf8vm71
# A33CR9fds10d8D2B2aE+vjmHJ69GY0bbfg5oZY2Lsq2euL7Da5/hS8+6T3MEtD4h
# njfHV7mxmoSfFuy/KDipoV6uwhI+ksqchXYdUH+5uCQO0MOO8ITjAgzUQsnZ4UIB
# HBGeP+e+3ljxSYSXWdPIrgxdR971P/HhWSVfKNlmBgEKMQM5Jy0aAd4jxSl/AzdY
# t0+6pliFJ1peGhdFni2Fm8fu5oN68aTIrNtc5WY7Lzgf+sRTVeWORWS37+1zAD0m
# jzd8gyfBLxRuaRSfjYxny0rLXelAwfiA3ze2DU2Bfg9/rfcwggXYMIIDwKADAgEC
# AhBsO9J+3TyUnpWOKKmzx1egMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAklM
# MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRh
# bCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZp
# Y2F0aW9uIEF1dGhvcml0eTAeFw0xNTEyMTYwMTAwMDVaFw0zMDEyMTYwMTAwMDVa
# MHUxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSkwJwYDVQQL
# EyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEjMCEGA1UEAxMaU3Rh
# cnRDb20gQ2xhc3MgMiBPYmplY3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
# ggEKAoIBAQC5FARY97LFhiwIMmCtCCbAgXe5aBnZFSsdGGnk2hqWBZcuZHkaqT1R
# M1rQd2r0ApNBw466cBur2Ht0b5jo17mpPmh2pImgIqwX1in4u7hhn9IH0GYOMEcg
# K3ACHv5zCRxxNLXifqmsqKfxjjpABnaSyvd4bO9YBXN9f4NQ6aJVAuMArpanxsJk
# e+P4WECVLk17v92CAN5JVaczI+baT/lgo5NVcTEkloCViSbIfU6ILeyhOSQZvpom
# MYk8eJqI0nimOTJJfmXangNDsrX8np+3lXD0+6rCZisXRWIaeffyTMHZ31Qj1D50
# WYdRtX5yev4WgaXoKJQN3lkgXUcytvyHAgMBAAGjggFaMIIBVjAOBgNVHQ8BAf8E
# BAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAy
# BgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0c3NsLmNvbS9zZnNjYS5j
# cmwwZgYIKwYBBQUHAQEEWjBYMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5zdGFy
# dHNzbC5jb20wMAYIKwYBBQUHMAKGJGh0dHA6Ly9haWEuc3RhcnRzc2wuY29tL2Nl
# cnRzL2NhLmNydDAdBgNVHQ4EFgQUPmKTmtfHGe4+j0kQhVUVIOOUhBwwHwYDVR0j
# BBgwFoAUTgvvGqRAW6UXaYcwyjRoQ9BBrvIwPwYDVR0gBDgwNjA0BgRVHSAAMCww
# KgYIKwYBBQUHAgEWHmh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeTANBgkq
# hkiG9w0BAQsFAAOCAgEAY6U81bNtJyjY67pTrzAL6kpdEtX5mspw+kxjjNdNVH5G
# 6lLnhaEkIxqdpvY/Wdw+UdNtExs+N8efKPSwh2m/BxXj2fSeLMwXcwHFookScEER
# 8ez0quCNzioqNHac7LCXPEnQzbtG2FHlePKNDWh8eU6KxiAzNzIrIxPthinHGgLT
# BOACHQM2YTlD8YoU5oN3dLmBOqtH0BDMZoLcjEIoEW1zC+TnVb3yU1G0xub6gnN7
# lP50vbAiHJYrnywQiXaloBV8B9YYfe6ZgvjqxwufwFcMVyE3UmCuDTsOpjqDEKpJ
# 25s+FUdkie5VqCS1aaudLo31X+9UvP45pfgyRqzyfUnVEhH4ZXxlBWZMzj2Xov5+
# m/+H3kxYuFA5xdqdshj/Zx00S7PkCSF+8M1NCcvFgQwjIw61bZAjDBl3P3a8xNTX
# sb2CjFdiNKbT3LD6IGeIf0b/EbPf0FXdvBrxm0ofMOhnngdPolPYCtoOGtZPAVe/
# xeu+/ZyKv6TSHlshaUO0iYfsmbXnZ51vvt/kkjwms9/qPFxSuE0fjEfF7aQazwRE
# Df2hiVPR0pAhvShtM3oU4XreEFEUWEYHs25fYV4WMmxkUKSgmSmwRq45tvtGH4LT
# b5+cd+iLqK8rBQL0E6xaUjjGfsYx7bueIvqTvCkrQvoxMbn/qDHCiypowDVq6TAw
# ggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/BmMA0GCSqGSIb3DQEBBQUAMGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0Et
# MTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAwMDBaMEcxCzAJBgNVBAYTAlVT
# MREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMcRGlnaUNlcnQgVGltZXN0YW1w
# IFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKNkXfx8
# s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V+JLjntVaY1sCSVDZg85vZu7d
# y4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnMXij0ZLZQt/USs3OWCmejvmGf
# rvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oOjafeTl/iqLYtWQJhiGFyGGi5
# uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZh6h+z+yMDDZbesF6uHjHyQYu
# RhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZFQlXmVYwk/PJYczQCMxr7GJC
# kawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIIBvwYDVR0gBIIBtjCCAbIw
# ggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdp
# Y2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4AeQAgAHUAcwBl
# ACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBu
# AHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0
# AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAAYQBuAGQAIAB0
# AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcAcgBlAGUAbQBl
# AG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5
# ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAaABl
# AHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMAsGCWCGSAGG/WwD
# FTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcNK2cCzTAdBgNVHQ4EFgQUYVpN
# JLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4oDagNIYyaHR0cDovL2NybDMu
# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcmwwOKA2oDSGMmh0
# dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEuY3Js
# MHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
# cnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAnSV+
# GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEXzakbvFoWOQCd42yE5FpA+94G
# AYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gwg5QZBWs1kBCge5fH9j/n4hFB
# pr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x2C/jbRcTBu7kA7YUq/OPQ6dx
# nSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYoFenYk+VVFvC7Cqsc21xIJ2bI
# o4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VUQAOSK2vCUcIKSK+w1G7g9BQK
# Ohvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9+QOWA63qAArrPye7uhswDQYJ
# KoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu
# YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQg
# QXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTIxMTExMDAwMDAw
# MFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE
# CxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNzdXJlZCBJ
# RCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6IItmfnKwkKV
# pYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgWWd+etSQVwpi5tHdJ3InECtqv
# y15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+x8cxSIB8HqIPkg5QycaH6zY/
# 2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32jx0PdAug7Pe2xQaPtP77blUjE
# 7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSNvtLOBq6thG9IhJtPQLnxTPKv
# mPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0XEK4aH631XcKJ1Z8D2KkPzIU
# YJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/BAQDAgGGMDsGA1UdJQQ0MDIG
# CCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcD
# CDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9bAABBDCCAaQwOgYIKwYBBQUH
# AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
# dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
# AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
# AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
# AGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
# AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
# AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
# AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
# AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9bAMVMBIGA1UdEwEB
# /wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8v
# b2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6
# MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYDVR0OBBYEFBUAEisTmLKZB+0e
# 36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqG
# SIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LPUukxR6tWXHvVDQtBs+/sdR90
# OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJHhZRW0eu7NoR3zCSl8wQZVann
# 4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFiqKgz5Js5p8T1zh14dpQlc+Qq
# q8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwCXaj++wc4Tw3GXZG5D2dFzdaD
# 7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7PkdcntxbuD8O9fAqg7iwIVYUiuOsYGk38
# KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAmMYIETzCCBEsCAQEwgYkwdTEL
# MAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKTAnBgNVBAsTIFN0
# YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSMwIQYDVQQDExpTdGFydENv
# bSBDbGFzcyAyIE9iamVjdCBDQQIQOb1CntKBbrrVvMkDtLpl5zANBglghkgBZQME
# AgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEM
# BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG
# SIb3DQEJBDEiBCDbmnZ2E5UpBrsLZw4zEUjjhtMjugvpyEpUYUk+9XfkRTANBgkq
# hkiG9w0BAQEFAASCAQADqC5WeKT0c/snqlFVHre0jFfaWTP484eJXXvw5aKtrGOE
# kW1iXS9WDT2bWuNMxZsZeLKaYz6QulqXurU2THV5zz3V5g9J1ZBvor3df9nSJjOC
# wb54+znOyUfO0Jg/UYxFWYKl6WISBRllkJdPzQvxNxWQ29gxdcpJ7IEdvdsoBlCQ
# JIFFl5ZA1x1jRP2ObxqbVG9ffumtFQbJSW477AnVm5f+dFOzAmNQSnTlbaQWYRCB
# oo38Cu++p29N/mP19t4Kxo13IFvrdvDLdvo0qaHpcICim0ELBL5R6NG5wmNI6VGW
# GsEgvBjSGwGzTXV2Z5JHIRF6el9sPOoXWk9itONToYICDzCCAgsGCSqGSIb3DQEJ
# BjGCAfwwggH4AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0
# IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl
# cnQgQXNzdXJlZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCg
# XTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA4
# MDIxNTE3MTZaMCMGCSqGSIb3DQEJBDEWBBTyVKKGf9nrBkhJuE9+zOrKSQ1nGTAN
# BgkqhkiG9w0BAQEFAASCAQCLMjbTPVhKAhir+uIQtovIJ67aGVg0+hpQfELFuYbu
# WppawdlwKOdIyxLuOPbryDQFs1Gbhljan0wh8+MX8ybk9wgD3hbZDrYErJ4R9Q5x
# Cy/oJE1+ohHR39mTH6Kelj0n7nrjxK97mY6GNoX+I535Nzty7izAShfAyFXx79v3
# F6QHdVo/Yd2qhOGya1gUpwelt9dhZv+qHkmVC6fFO7K1yQtajtcizB5RDPjJU+M5
# aWtV2vaR6fi/uj2w3yaTbDYRuXCUEjaPidwhjCQCo1DqYrRFdj2ivnRF3N4uklVW
# dWC9nGKvxvXrbJlo1aHevClXx9xSMxdxJMXtKCy1l11x
# SIG # End signature block