Clear-History
Clear-Host
$ScriptVersion = "7.2.58"

#Fixes and Enhancements
# - LAST UPDATE: 10/10/2022
# - Fix HTML5 with ESP rules ordering 
# - Added SubVS for new ESP auth mode
# - Removed install of intermediate and root certificates
# - Added check to ensure correct version of Kemp Powershell module and LoadMaster OS is installed
# - Added SAML configuration option
# - Enhanced user feedback as script is running
# - SAML sanity checks added for Token Signing Cert and Metadata file
# - Added support for using a list of hostnames is the vdiservers.txt file
# - Removed checking for format of data in vdiservers.txt and storefront.txt files
# - Added option to set SSL Reencryption on virtual services
# - Added option to set default gateway on virtual services
# - Added check to set Use_HTML5 to False if Reencrypt is set to True
# - Added code to load and/or unload LoadMaster DNS client Hosts for Local Resolution
# - Added debug option (clears out all VS, Rules, SSO, and LDAP services) 
# - Added additional data to feedback and to log files

#REQUIREMENTS 
#  CONFIGURED AND LICENSED KEMP LOADMASTER (LMOS 7.2.53 or newer) 
#  Text file called “storefront.txt.” containing all your StoreFront Servers IP addresses or names (FQDN format)
#  Text file called “vdiservers.txt.” containing all your VDI Server IP addresses or names (FQDN format)
#  Text file called "dns_ip.txt" containing IP addresses to be imported into LoadMaster DNS localhosts file
#  Text file called "dns_name.txt" containing FQDN(s) to be imported into LoadMaster DNS localhosts file
#  Certificate file in pfx format for to load and assign to the Citrix virtual service
#  Certificate file in pfx format to load and assign as LoadMaster management interface certificate
#  If using LDAP or Radius, availability of a LDAP or Radius authentication service
#  If using SAML Authentiation,availablity of Token Signing Cert & IDP Metadata.xml file
#  Citrix StoreFront Fully Qualified Domain Name, e.g. citrix.kemptest.com
#  Citrix StoreFront URL, e.g. /Citrix/KempWeb
#  IP address to assign to Citrix Virtual Service
#  LOADMASTER DNS RESOLVER POINTING TO DNS SERVER THAT CAN RESOLVE hostnames (if used for input files)


#########################################################################################################################
#                                               START CONFIGURING VARIABLES
#########################################################################################################################


#############################
# Wait timer between commands 
#############################
$wait = 250                                    ## UPDATE - Set wait state between commands (increase if script generates errors when running) 

#####################
# LoadMaster settings
#####################
[string]$LoadmasterIP = "10.10.10.2"            ## UPDATE - LoadMaster Management IP Address (shared address if HA)
[string]$LoadMasterPort = "443"                 ## UPDATE - Update only if using a nonstandard management port
[string]$Search_Domain = "kemptech.biz"         ## UPDATE - Value is critical when input files use hostnames instead of IP addresses

#################################
# Citrix Virtual Service settings 
#################################
$SF_File = "storefrontip.txt"                  ## UPPATE - File Name for file containing storefront (IP or hostname)
$VDI_File = "vdiserversip.txt"                 ## UPPATE - File Name for file containing VDI servers (IP or hostname)
$VirtualServiceIp = "10.10.10.3"               ## UPDATE - Virtual Service IP (used to publish Citrix StoreFront service)                      
$Use_HTML5 = $True                             ## UPDATE - If set to $True then build HTML5 listeners, if $False use only ICA listeners (Must be $True or $False)
$VS_GW = "10.0.0.1"                            ## UPDATE - Used to set the Default Gateway for the listener virtual services
$Reencrypt = $False                            ## UPDATE - If VDA servers are configured to only accept TLS 443 connections, set to $True else set to $False

#################
#Citrix StoreName
#################
$StorePath = "/Citrix/STOREWeb"                ## UPDATE - Citrix Store Name URL
$FQDN = "CITRIX.DOMAIN.COM"                    ## UPDATE - Citrix External FQDN

####################
# Import Certificate 
####################
$Load_Cert = $True                             ## UPDATE - Set to $True to load StoreFront TLS certificate on LoadMaster. If it already exists on the LoadMaster, set to False
$CertName = "CITRIX-CERT"                      ## UPDATE - Set to friendly name, to identify the certificate. If it alredy exists, set the Identifier name found under "Certs & Security" on the LoadMaster
$CertFile = "CITRIX-CERT.pfx"                  ## UPDATE - If "Load_Cert" set to "True" Set the filename of the citrix certificate to be imported
$CertPass = "password"                         ## UPDATE - If "Load_Cert" set to "True" Set the password for your TLS cert to install certificate
                                              
                                               ## Ensure that SSL cert contains full chain, otherwise import intermediate or Root certs 
#######################
# Authentication Method                        # NOTE - Only one option can be set to $True or all options can be set to $False
####################### 
$Use_LDAP = $True							   ## UPDATE - If set to $True, then use LDAP for user auth to StoreFront (Must be $True or $False)
$Use_Radius = $False                           ## UPDATE - If set to $True, then use Radius for user auth to StoreFront (Must be $True or $False)
$Use_SAML = $False                             ## UPDATE - If set to $True, then use SAML for user auth to StoreFront (Must be $True or $False)

##########################################################################
# Client Side LDAP or Radius ESP SSO settings. Ignore this section if SAML is required. 
##########################################################################
$AuthServers = "10.0.0.10"                      ## UPDATE - Modify if $Use_LDAP or $Use_Radius is $True. (One or more IP addresses, space seperated)
$TestAccount = "ServiceAccount@DOMAIN.COM"      ## UPDATE - Modify if $Use_LDAP or $Use_Radius is $True. (Account used to bind to LDAP or healthcheck LDAP or Radius)
$TestAccountPass = "PASSWORD"                   ## UPDATE - If left blank, you will be prompted securely for the password
$Domain ="DOMAIN.COM" 		                    ## UPDATE - Modify if $Use_LDAP or $Use_Radius is $True. (LDAP or Radius SSO Domain)

#########################################################################
# Client Side SAML ESP SSO settings. Ignore this section if LDAP or Radius is required
#########################################################################
$SAMLSPEntityID = "LoadMasterSAML"               ## UPDATE - Entity ID used to identify your Citrix SAML App
$SAMLmetadata =   "SAML-Metadata.xml"            ## UPDATE - Name of Metadata file downlaoded from IDP Portal
$Domain = "DOMAIN.COM"                           ## UPDATE - Name of new SAML Configuration
$SAMLIDPCert = "SAML-Citrix.crt"                 ## UPDATE - Name of SAML IDP Cerificate file. Must be located in current working directory
$SAMLIDPCertName ="SAML-Citrix"                  ## UPDATE - Name of SAML Token signing certificate

#########################                        ## Please contact Kemp support before enabling this section. It is only used when VDA servers are identified by hostname instead of IP address.
# LoadMaster DNS Settings                        ## The following settings are needed when VDA DNSResolution is enabled, and VDA DNS name does not yet exist in DNS server.
#########################
#$LoadDNS = $False                               ## UPDATE - Flag to load the LoadMaster DNS with names and IP addresses in the Host file
#$ClearDNS = $True                               ## UPDATE - Flag to clear the LoadMaster DNS names and IP sddresses in the Host file
#$DNS_IP = "dns_ip.txt"                          ## UPPATE - File Name for file containing IP addresses to load into LoadMaster DNS service
#$DNS_Name = "dns_name.txt"                      ## UPPATE - File Name for file containing hostnames to load into LoadMaster DNS service

#########################################################################################################################
#                                               END CONFIGURE VARIABLES
#########################################################################################################################

######################################
# Conditional Settings (do not modify)
######################################
if ($Reencrypt) {$Use_HTML5 = $False}

#########################################################################################################################
#########################################################################################################################
##                                           DO NOT MODIFY SETTINGS BELOW THIS LINE
#########################################################################################################################
#########################################################################################################################
Remove-Variable * -ErrorAction SilentlyContinue               # Remove all session level variables 
$PS_Required = "7.2.53.0"                                     # This is the required minimum release of LoadMaster PowerShell Module for this script to function
$LM_Required = "7.2.53.0"                                     # This is the required minimum release of LoadMaster Operating System for this script to function

################################################
# Enable Powershell to accept certificate errors
################################################ 
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

###############################################
# Force Powershell to use specific TLS Versions
###############################################
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11"  

#########################################################################################################################
#                                               START STANDARD VARIABLES
#########################################################################################################################

#####################################
# Standard Settings - Virtual Service 
#####################################
$VSName = "Citrix StoreFront Gateway"              ## Standard value used in script and template
$VSPort = "443"                                    ## Standard value used in script and template
$RSPort = "443"                                    ## Standard value used in script and template
$CipherSet = "BestPractices"                       ## UPDATE - Set cipher set to BestPractices (eveyone) or FIPS (US Gov)
$VS_Cipher = "BestPractices"                       ## UPDATE - Set cipher set to BestPractices (eveyone) or FIPS (US Gov)

##################################
# Standard Settings - VDI Services 
##################################
$starting_index = 1                                ## Standard value used in script and template
$starting_port = 4431                              ## Standard value used in script and template

###########################################
# Standard Settings - VDI 2598 VS Variables        ## Standard value is 2598 (unencrypted) or 443 (encrypted)
###########################################
$vdi2589_vs_name ="Citrix_Workspace"
if ($Reencrypt) {$vdi2589_RS_Port ="443"}
Else {$vdi2589_RS_Port ="2598"}

#################################
# Standard VDI HTML5 VS Variables                  ## Standard value is 8008 (unencrypted) or 443 (encrypted)
#################################
$vdi8008_vs_name ="Citrix_HTML5"
if ($Reencrypt) {$vdi8008_RS_Port ="443"}
Else {$vdi8008_RS_Port ="8008"}

##########################
# IPv4 regex match pattern
##########################
$pattern1 = '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'

#######################
# Script home directory
#######################
[string]$scripthome = ($pwd).Path                  ## Location to hold files and run powershell commands from

#################
# Create Log File                                  ## Create log file with date time stamp in name
#################
$dd = Get-Date -Format yyMMddhhmm                  ## Get a date time indel to prepend to file name
$logfile = "Citrix_Script_Log_"+$dd+".log"         ## Create a unique log file name including datetime 
date > $logfile; "Log file for Citrix Script" >> $logfile ; "Version Number = $ScriptVersion" >> $logfile

#########################################################################################################################
#                                               END STANDARD VARIABLES
#########################################################################################################################

#############################
# ANNOUNCE SCRIPT AND PURPOSE
#############################
Write-Host -fore Cyan "SCRIPT TO INSTALL CITRIX STOREFRONT"
write-host "`nThis script runs from the folder $scripthome. `nThis folder must contain the following files:"
Write-Host "  - $scripthome\$SF_File containing all StoreFront Server IP addresses."
Write-Host "  - $scripthome\$VDI_File containing all VDI Servers."
if ($LoadDNS) {Write-Host "  - $scripthome\$DNS_Name containing all VDI Server hostnames (omit domain portion of name)."}
if ($LoadDNS) {Write-Host "  - $scripthome\$DNS_IP containing all VDI Server IP addresses."}
if ($Load_Cert) {write-host "  - $scripthome\$CertFile for StoreFront TLS Certficate"}
if ($Use_SAML) { write-host "  - $scripthome\$SAMLIDPCert for SAML IDP Certificate" }
write-host "To run this script, you will need the admin account and password for the LoadMaster."
write-host -fore green  "`nENTER (Y) TO CONTINUE, ANY OTHER VALUE TO TERMINATE" -NoNewline ; $YN = read-host " "
if (-NOT ($YN -match "^Y")) {exit}

Write-Host -fore cyan "`nCHECKING FOR REQUIRED FILES AND SETTINGS"

#####################################################
#Check for Kemp Powershell Build minimum requirements
#####################################################
$PS_R3 = ($PS_Required.Split("."))[2]

####################################################
# Ensure correct Kemp PowerShell module is installed 
####################################################

if ((Test-Path "C:\Program Files\WindowsPowerShell\Modules\KEMP.LoadBalancer.Powershell") -or (Test-Path "C:\Program Files (x86)\WindowsPowerShell\Modules\KEMP.LoadBalancer.Powershell")) {
    $null = Remove-Module -Name KEMP.LoadBalancer.Powershell -errorAction SilentlyContinue
    $null = start-Sleep -Seconds 1
    $null = Import-Module -Name KEMP.LoadBalancer.Powershell -MinimumVersion $PS_Required -ErrorAction SilentlyContinue
    }

$PS_Version = $Null
$PS_Version = (Get-Module -name KEMP.LoadBalancer.Powershell).Version
if ($PS_Version -eq $Null) {$msg = "`nCRITICAL ERROR - SCRIPT TERMINATING - Kemp PowerShell Module not installed. `nPlease install version $PS_Required or newer and rerun script."; $msg >> $logfile;  write-host -fore darkred -back yellow $msg " Press Enter to continue: " -nonewline ; Read-Host ; exit}

$PS_V3 = ($PS_Version.Build)
if ($PS_V3 -lt $PS_R3) {$msg = "`nCRITICAL ERROR - SCRIPT TERMINATING - Newer Kemp PowerShell module required. `nPlease install version $PS_Required or newer and rerun script. "; write-host -fore darkred -back yellow $msg "Press Enter to continue: " -nonewline ; read-host ; exit}


###############################
# Run sanity check on variables
###############################

$Use_ESP = ($Use_LDAP -or $Use_Radius -or $Use_SAML)

$ESP_ERR = $False ; $ESP_ERR = (($Use_Radius -and $Use_SAML) -or ($Use_Radius -and $Use_LDAP) -or ($Use_SAML -and $Use_LDAP))
  if ($ESP_ERR) {
    $msg = "TERMINATING SCRIPT - USE_RADIUS OR USE_LDAP OR USE_SAML SETTINGS INCORRECT"; $msg >> $logfile; Write-Host -fore darkred -back yellow $msg
    $msg = "                     Only one ESP method is allowed. Configuration currently shows more than one enabled."; $msg >> $logfile; Write-Host -fore darkred -back yellow $msg
    $msg = '                     Please adjust settings for $Use_Radius, $Use_LDAP or $Use_SAML and rerun script'; $msg >> $logfile; Write-Host -fore darkred -back yellow $msg
    $msg = "Press Enter to terminate script";  Write-Host -fore darkred -back yellow $msg -nonewline; read-host; exit 
    }


#################################
# Check that required files exist 
#################################

$SF_Test = (Test-Path  -PathType Leaf ".\$SF_File")
$VDI_Test = (Test-Path -PathType Leaf  ".\$VDI_File")
$DNS1_Test = (Test-Path -PathType Leaf ".\$dns_ip")
$DNS2_Test = (Test-Path -PathType Leaf ".\$dns_name") 
$SAML1_Test = (Test-Path -PathType Leaf ".\$SAMLmetadata")
$SAML2_Test = (Test-Path -PathType Leaf ".\$SAMLIDPCert")


if ( -NOT ($SF_Test))  {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $SF_File. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}
if ( -NOT ($VDI_Test)) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $VDI_File. Press Enter to continue: " ; $msg >> $logfile;  write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}

if ($LoadDNS -or $ClearDNS) {
  if ( -NOT ($DNS1_Test)) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $DNS1_File. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}
  if ( -NOT ($DNS2_Test)) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $DNS2_File. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}
}

if ($Use_SAML ) {
  if ( -NOT ($SAML1_Test)) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $SAML11_File. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}
  if ( -NOT ($SAML2_Test)) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $SAML2_File. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg -nonewline; read-host ; exit}
    }


##############################################################################
# Read file and extract individual lines that are in IP address or FQDN format
##############################################################################
[array]$servers = $null
[array]$storefront = $null

##############################################################
# Loading StoreFront Info from File (Skip blank lines in file)
##############################################################
$storefront = @(Get-Content -Path ".\$SF_File" | Where-Object { $_.Trim() -ne '' })

##############################################################
# Loading VDI Server Info from File (Skip blank lines in file)
##############################################################
$servers = @(Get-Content -Path ".\$VDI_File" | Where-Object { $_.Trim() -ne '' })

################################################################################################
# Sanity Check - if no VDI Servers or StoreFront Servers extracted from files - terminate script
#################################################################################################
if ($storefront.count -eq 0) {
    $msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - No StoreFront Servers Identified. Press Enter to continue: "
    $msg >> $logfile
    Write-Host -fore darkred -back yellow $msg ; Read-Host ; exit 
    }
if ($servers.count -eq 0) {
    $msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - No VDI Servers Identified. Press Enter to continue: "
    $msg >> $logfile
    Write-Host -fore darkred -back yellow $msg ; Read-Host ; exit 
    }

$storefront_asip = ($storefront[0] -match $pattern1)
$servers_asip = ($servers[0] -match $pattern1)

#if (-not $storefront_asip) {$storefront = $storefront.trimend($Search_Domain) }

# Reset load dns settings if server and storefront files are in IP address format
if ($servers_asip -and $storefront_asip) {$LoadDNS = $False}

############################################################################
# Conditional setting needed if list of vdi servers is based on IP addresses
############################################################################

if ((-not $servers_asip) -and $Reencrypt) {[bool]$server_fqdn = ($servers[0] -match $Search_domain)}
if ($servers_asip -and $Reencrypt) {[bool]$server_fqdn = $False} 
if ($reencrypt -and (-not $server_fqdn)) {$msg = 'CRITICAL ERROR - When $Reencrypt = $True, server input file must be in FQDN format. Fix and rerun script. Press enter to continue: '; $msg >> $logfile; write-host -fore darkred -back yellow "`n"$msg -nonewline ; read-host ; exit} 
if ($Reencrypt) {$vdi2589_vs_name ="Citrix_VDI_Listener"}


# LIST SERVERS
 
$msg = "`nLIST OF STOREFRONT SERVERS:"; $msg >> $logfile; Write-Host -fore Cyan $msg
$storefront; $storefront >> $logfile
$msg = "`nLIST OF VDI SERVERS:"; $msg >> $logfile; Write-Host -fore Cyan $msg
$servers; $servers >> $logfile

$msg = "`nCHECK LOADMASTER AVAILABILITY AND VERSIONS:"; $msg >> $logfile; Write-Host -fore Cyan $msg

############################################
# Check for access to LoadMaster IP address
############################################
$progresspreference = "SilentlyContinue"; $ok = Test-NetConnection "$LoadMasterIP" -Port "$LoadMasterPort" -InformationLevel Quiet -ErrorAction SilentlyContinue -WarningAction SilentlyContinue; $progresspreference = "Continue"

if ($ok) {
    $msg = "200  - Connection to LoadMaster IP address $LoadmasterIP successful"; $msg; $msg >> $logfile
    }
else { 
    $msg = "TERMINATING SCRIPT - LoadMaster IP address $LoadmasterIP is NOT reachable over the network"; $msg >> $logfile; Write-Host -fore darkRed -back Yellow $msg 
    $msg = "Press Enter to terminate script: "; Write-Host -fore darkRed -back Yellow $msg -NoNewline; Read-Host 
    return
    }
 
################################################
# LOGIN to LoadMaster and enable API interface #
################################################
  $msg = "???  - ENTER KEMPIP AND PASSWORD FOR LOADMASTER"; write-host -fore green $msg
  [string]$doit = $True
  do {
      start-sleep -Seconds 1
      do {$KempCreds = Get-Credential -message "ENTER LOADMASTER ADMIN ACCOUNT NAME AND PASSWORD"} while ($KempCreds.Password.Length -eq 0)
      $null = (Initialize-LmConnectionParameters -Address $LoadmasterIP -LBPort $LoadMasterPort -Credential $KempCreds)
      try {$r = (Enable-SecAPIAccess -LoadBalancer $LoadmasterIP -Credential $KempCreds); $rc = $r.ReturnCode; $rs = $r.Response} catch {}
      $msg = "$rc  - Enable API Access to Validate Login (" + $rs + ") "; $msg >> $logfile ; write-host $msg
      if ($rc -ne 200) {$msg = "Bad userid or password. Press Enter to try again. Ctrl-C to terminate script: "; write-host -fore darkred -back yellow $msg -nonewline; read-host}
  }
  while ($rc -ne 200)

#######################################################
# Check for minimum LoadMaster Operating System version
#######################################################
$LM_R = ($LM_Required.Split("."))[2]
$LM_V = ((get-lmallparameters -Loadbalancer $LoadmasterIP -Credential $KempCreds).data.AllParameters.version).Split(".")[2]
if ($LM_V -ge $LM_R) {$msg = "200  - LMOS version is 7.2.$LM_V"; $msg >> $logfile; write-host $msg}
else {$msg = "500 - LMOS version check failed. Required is 7.2.$LM_R. Actual is 7.2.$LM_V"; $msg >> $logfile; write-host $msg}

##################################
# Create backup of existing config
##################################
# BACKUP EXISTING CONFIG (SAFETY NET)
$dd = Get-Date -Format yyMMddhhmmss
$newbackup = $scripthome + "\" + $dd + "-vlm.backup"
$r = (Backup-LmConfiguration -LoadBalancer $LoadmasterIP -path $newbackup); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING BACKUP OF EXISTING CONFIGURATION.  Filename is :" + $newbackup + " (" + $rs + ") " ; $msg >> $logfile; write-host $msg


##############################################################################
# Check for existing Citrix virtual services and if present - TERMINATE SCRIPT
##############################################################################
$r = (Get-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $starting_port -VSProtocol tcp); $rc = $r.ReturnCode
if ($rc -eq 200) {$msg = "TERMINATING SCRIPT - Existing Citrix virtual service found. Press enter to continue: "; $msg >> $logfile; Write-Host -fore darkred -BackgroundColor yellow -nonewline $msg; read-host ; exit }

###################################################################################################
# Check LoadMaster to see if it includes ESP license - if no - set Use_LDAP and Use_Radius to False
###################################################################################################
if ($Use_ESP) {
  $License_ESP = (Get-LicenseInfo -Loadbalancer $LoadmasterIP -Credential $KempCreds).data.LicenseInfo.ESP

  if (($License_ESP -ne "yes") -and ($Use_ESP) ) {
    add-content -path $logfile -Value "TERMINATING SCRIPT - ESP is required and LoadMaster is not licensed for ESP"
    write-host -fore DarkYellow "TERMINATING SCRIPT - ESP is required and LoadMaster is not licensed for ESP"
    read-host "`nPress enter to terminate script"
    exit
    }

  if ($License_ESP -eq "yes") {
    add-content -path $logfile -Value "  - ESP License was found - Honoring settings for Use_LDAP, Use_Radius and Use_SAML"
    }
  }
$null = start-sleep -milliseconds $wait


#########################################################
# Add or Remove IP addresses from LoadMaster DNS hostfile
#########################################################
if ($LoadDNS) {
$msg = "`n#### LOADING LOADMASTER DNS CACHE ####"; add-content -path $logfile -value $msg; write-host $msg

  [int]$j = $Null
  [string]$i = $Null
  [array]$out = $Null
  [array]$IP = $Null
  [string]$n = $Null
  [array]$Name = $Null
  [bool]$err = $False

  # Load IP addresses and hostnames into variables
  if ($LoadDNS) {$IP = @(Get-Content -Path ".\$DNS_IP" | Where-Object { $_.Trim() -ne '' })}
  if ($LoadDNS) {$Name = @(Get-Content -Path ".\$DNS_Name" | Where-Object { $_.Trim() -ne '' })}
  if ($LoadDNS) {if ($IP.count -eq 0) {$err = $True}}
  if ($LoadDNS) {if ($Name.count -eq 0) {$err = $True}}
  if ($LoadDNS) {if (($IP.Count) -ne ($Name.Count)) {$err = $True}}

  if ($err) {
    add-content -path $logfile -Value "Required DNS input file have errors"
    Write-Host ""
    Write-Host -fore red "CRITICAL ERROR - Required DNS input files are either empty or do not have the same number of entries in each file"
    Write-Host -fore red ""
    Write-Host -fore red "Fix these files and rerun this script"
    write-host -fore red "`nPRESS ENTER TO TERMINATE" -NoNewline ; $YN = read-host " "
    exit
    }

  # Read in any existing IP entries
  if ($LoadDNS) {$out = (Get-HostsEntry -LoadBalancer $LoadmasterIP).data.LocalHosts.HostsEntry.HostIPAddress}

  # Load DNS
    for ($j=0; ($j -lt $Name.Count); $j++){
        $i = $IP[$j] ; $n = $Name[$j]
        if (-not ($out -contains "$i")) {
            $r = (New-HostsEntry -LoadBalancer $LoadmasterIP -HostIP $i -HostFQDN $n); $rc=$r.ReturnCode; $rs=$r.Response
            $msg = "$rc  - Adding $i $n to LoadMaster DNS table (" + $rs + ") "; $msg >> $logfile; write-host $msg
        }
    }
}



##########################
# All VARIABLES CONFIGURED
########################## 
Write-Host -fore Cyan "`nCOMPLETED SANITY CHECK ON VARIABLES AND FILES"

######################################################
# Load Log File with Variables and Standard Parameters
######################################################
add-content -path $logfile -Value "`nLIST OF VARIABLES AND VALUES"
add-content -path $logfile -Value "----------------------------"
add-content -path $logfile -Value "#### LOADMASTER SETTINGS ####"
add-content -path $logfile -Value "wait = $wait"
add-content -path $logfile -Value "LoadmasterIP = $LoadmasterIP"
add-content -path $logfile -Value "LoadMasterPort = $LoadMasterPort"
add-content -path $logfile -Value "#### VIRTUAL SERVICE SETTINGS ####"
add-content -path $logfile -Value "VirtualServiceIp = $VirtualServiceIp"
add-content -path $logfile -Value "Use_HTML5 = $Use_HTML5"
add-content -path $logfile -Value "#### RADIUS AND LDAP SETTINGS ####"
add-content -path $logfile -Value "Use_Ldap = $Use_Ldap"
add-content -path $logfile -Value "Use_Radius = $Use_Radius"
add-content -path $logfile -Value "AuthServers = $AuthServers"
add-content -path $logfile -Value "AuthUser = $TestAccount"
add-content -path $logfile -Value "AuthPass = #####"
add-content -path $logfile -Value "Domain = $Domain"
add-content -path $logfile -Value "SharedSecret = #####"
add-content -path $logfile -Value "#### CITRIX STOREFRONT SETTINGS ####"
add-content -path $logfile -Value "StorePath = $StorePath"
add-content -path $logfile -Value "FQDN = $FQDN"
add-content -path $logfile -Value "CertName = $CertName"
add-content -path $logfile -Value "CertFile = $CertFile"
add-content -path $logfile -Value "CertPass = #####"
add-content -path $logfile -Value "CA_Name = $CA_Name"
add-content -path $logfile -Value "CA_File = $CA_File"
add-content -path $logfile -Value "#### STOREFRONT SERVER LIST ####"
add-content -path $logfile -Value $storefront
add-content -path $logfile -Value "#### VDI SERVER LIST ####"
add-content -path $logfile -Value $servers
add-content -path $logfile -Value "#### STANDARD VIRTUAL SERVICE PARAMETERS ####"
add-content -path $logfile -Value "VirtualServiceName = $VSName"
add-content -path $logfile -Value "VirtualServicePort = $VSPort"
add-content -path $logfile -Value "RealServerPort = $RSPort"
add-content -path $logfile -Value "#### COMMON VDI PARAMETERS ####"
add-content -path $logfile -Value "starting_index = $starting_index"
add-content -path $logfile -Value "starting_port = $starting_port"
add-content -path $logfile -Value "#### STANDARD VDI 2598 PARAMETERS ####"
add-content -path $logfile -Value "vdi2589_vs_name = $vdi2589_vs_name"
add-content -path $logfile -Value "vdi2589_RS_Port = $vdi2589_RS_Port"
add-content -path $logfile -Value "#### STANDARD VDI HTML5 VS PARAMETERS ####"
add-content -path $logfile -Value "vdi8008_vs_name = $vdi8008_vs_name"
add-content -path $logfile -Value "vdi8008_RS_Port = $vdi8008_RS_Port"
add-content -path $logfile -Value "############# END OF PARAMETERS ###########"


#################################
# Install StoreFront Certificates
#################################

if ($Load_Cert) {
    $isit = ((get-TLSCertificate -Loadbalancer $LoadmasterIP -Credential $KempCreds -CertName $CertName).ReturnCode -eq "200")
    if ($isit) {$msg = "200 - Certificate $CertName is available on LoadMaster $LoadmasterIP"; $msg; $msg >> $logfile }
    if ((-not ($isit)) -and (-not (Test-Path -PathType Leaf  ".\$Certfile"))) {$msg = "`nCRITICAL ERROR - TERMINATING SCRIPT - Cannot find $CertFile. Press Enter to continue: " ; $msg >> $logfile; write-host -fore darkred -back yellow $msg; return}
    if (-not $isit) {
        $null = start-sleep -Seconds 1
        if (($certpass -eq "") -or ($certpass -eq $Null)) { do {$certpass = read-host "Enter password to decrypt certificate file"} while ($certpass.length -lt 1)}
        $r = (New-TlsCertificate -Loadbalancer $LoadmasterIP -Credential $KempCreds -Name $CertName -Password $CertPass -Path $CertFile); $rc=$r.ReturnCode; $rs=$r.Response
        $msg = "$rc - Install TLS certificate from $certfile (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        $null = start-sleep -milliseconds $wait
        $CertPass = $Null
        # Validate LoadMaster has necessary certificate file
        if ((get-TLSCertificate -Loadbalancer $LoadmasterIP -Credential $KempCreds -CertName $CertName).ReturnCode -ne "200") {
            $msg = "500 - Cannot locate $certname on LoadMaster $loadmasterIP. Without this certificate, Citrix virtual services cannot be created"; write-host -fore red $msg; $msg >> $logfile
            $msg = "500 - Script will now terminate."; write-host -fore red $msg; $msg >> $logfile; return
        }
    } 
}

#################################
# Install StoreFront Certificates
#################################
if ($Use_SAML) {
  $doSAMLCert = ((Get-TlsIntermediateCertificate -Loadbalancer $LoadmasterIP -Credential $KempCreds -CertName $SAMLIDPCertName).Response -ne "200")

  # Install Intermediate Certificate to validate SAML IDP certificates
  if ($doSAMLCert) {
    $r = (New-TlsIntermediateCertificate -Loadbalancer $LoadmasterIP -Credential $KempCreds -Name $SAMLIDPCertName -Path $SAMLIDPCert); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc - Importing SAML Token Signing Certificate (" + $rs + ") "; $msg >> $logfile; write-host $msg
    }
  }


################################
#Create Radius MFA Configuration 
################################
if ($Use_Radius) {
    add-content -path $logfile -Value "`n#### Radius MFA Configuration ####"
    Write-Host -fore cyan "`nCREATING NEW RADIUS CONFIGURATION"
    if ($TestAccountPass -eq "") {$TestAccountPass = Read-Host -Prompt  'Please Enter Password for Radius Auth Server Test Account' -AsSecureString}
    Write-Host -fore Green "ENTER RADIUS SERVER SHARED SECRET"
    $RadiusSharedSecret = Read-Host -Prompt  'Enter Radius Shared Secret' -AsSecureString ## UPDATE - Modify if $Use_LDAP or $Use_Radius is $True. (Radius shared secret)

    $r = (New-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING new RADIUS client side SSO domain (" + $rs + ") "; $msg >> $logfile; write-host $msg
  
    $r = (Set-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain -logon_domain $Domain -auth_type RADIUS -Server $AuthServers -radius_shared_secret $RadiusSharedSecret -logon_fmt Principalname -sess_tout_idle_pub 1800 -sess_tout_idle_priv 1800 -testuser $TestAccount -testpass $TestAccountPass); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc - Configure new RADIUS client side SSO domain (" + $rs + ") "; $msg >> $logfile; write-host $msg
  
    $null = start-sleep -milliseconds $wait
    }


################################
# Create LDAP Configuration 
################################
if ($Use_LDAP) {
    add-content -path $logfile -Value "`n#### CREATE LDAP MFA ####"
    Write-Host -fore cyan "`nCREATE NEW LDAP CONFIGURATION"
    if ($TestAccountPass -eq "") {$TestAccountPass = Read-Host -Prompt  'Please Enter Password for LDAP Auth Server Test Account' -AsSecureString}

    # Create LDAP Service
    $doLDAP = ((Get-LdapEndpoint -LoadBalancer $LoadmasterIP -Credential $KempCreds -name $Domain).Response -ne 200)
    if ($doLDAP) {
      $r = (New-LdapEndpoint -Loadbalancer $LoadmasterIP -Credential $KempCreds -Name $Domain -AdminPass $TestAccountPass -AdminUser $TestAccount -LdapProtocol LDAPS -Server $AuthServers); $rc=$r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - CREATING NEW LDAP SERVICE ENDPOINT (" + $rs + ") "; $msg >> $logfile; write-host $msg
      }
    Else {$msg = "200 - LDAP SERVICE ENDPOINT ALREADY EXISTS"; $msg >> $logfile; write-host $msg}

    #  CLIENT SIDE SSO DOMAIN - LDAP
    $doSSO = ((Get-SSODomain -LoadBalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain).Response -ne 200)
    if ($doSSO) {
      # Create SSO Domain
      
      $r = (New-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - CREATING NEW LDAP CLIENT SSO DOMAIN (" + $rs + ") "; $msg >> $logfile; write-host $msg
      # Configure SSO Domain
      
      $r = (Set-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain -logon_domain $Domain -ldap_endpoint $Domain -tls ldaps -auth_type ldap-ldaps -logon_fmt Principalname -sess_tout_idle_pub 1800 -sess_tout_idle_priv 1800 -ldapephc 1); $rc=$r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - CONFIGURE SSO DOMAIN (LDAP) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    
      $null = start-sleep -milliseconds $wait
      }
    Else {$msg = "200 - SSO DOMAIN ALREADY EXISTS"; $msg >> $logfile; write-host $msg}
  
    }

################################
# Create SAML Configuration 
################################
if ($Use_SAML) {
    $msg = "`nCREATING NEW SAML CONFIGURATION"; $msg >> $logfile; Write-Host -fore cyan $msg 
    
    # Create new SSO Server Side SAML Domain
    $r = (New-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING new SAML client side SSO domain (" + $rs + ") "; $msg >> $logfile; write-host $msg
    
    # Configure new SSO Server side SAML Domain
    $r = (Set-SSODomain -Loadbalancer $LoadmasterIP -Credential $KempCreds -auth_type SAML -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - Configure SAML SSO domain (" + $rs + ") "; $msg >> $logfile; write-host $msg
    start-sleep -Milliseconds $wait

    # Install SAML MetaFile
    $r = (Install-SAMLIdpMetafile -Loadbalancer $LoadmasterIP -Credential $KempCreds -Path $scripthome\$SAMLmetadata -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - Install SAML Metafile (" + $rs + ") "; $msg >> $logfile; write-host $msg
    start-sleep -Milliseconds $wait

    # Configuring SAML SP Certname
    $r = (Set-SAMLSPEntity -Loadbalancer $LoadmasterIP -Credential $KempCreds -IdpCert $SAMLIDPCertName -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - Setting Certname for SAML SP (" + $rs + ") "; $msg >> $logfile; write-host $msg
    start-sleep -Milliseconds $wait

    # Setting SAML Entity ID
    $r = (Set-SAMLSPEntity -Loadbalancer $LoadmasterIP -Credential $KempCreds -SPEntityId $SAMLSPEntityID -Domain $Domain); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - Setting Entity ID for SAML SP (" + $rs + ") "; $msg >> $logfile; write-host $msg
    start-sleep -Milliseconds $wait
    }


############################
# Global LoadMaster Settings                                                          
############################
write-host -fore cyan "`nSETTING COMMON LOADMASTER PARAMETERS"
add-content -path $logfile -Value "`n#### SETTING COMMON LOADMASTER PARAMETERS ####"

# SETTING OUTBOUND CIPHER  (Recommend FIPS or BestPractices)
$r = (Set-LmParameter -LoadBalancer $LoadmasterIP -Credential $KempCreds  -Param OutboundCipherset -Value "$CipherSet"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Setting OutboundCipherset = $CipherSet (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# SETTING INBOUND CIPHER (Recommend FIPS or BestPractices)
$r = (Set-LmParameter -LoadBalancer $LoadmasterIP -Credential $KempCreds  -Param WUICipherset -Value "$CipherSet"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Setting WUICipherset = $CipherSet (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Share SubVS Persistence
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param ShareSubVSPersist -Value 1 ); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Setting Global LoadMaster Parameters (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Explicitly set management gateway to default GW
$GW = (Get-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param dfltgw).data.dfltgw
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param admingw -Value "$GW"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Setting Management Default Gateway to $GW (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Disable SSL Renegotiation
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -param sslrenegotiate -value 0); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Disable SSL Renegotiation (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Enable Subnet Originating Request (SOR) appliance wide 
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param subnetorigin -Value 1); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Enable subnet originating request based NAT (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Allows loadbalancing of servers located on a different subnet from the load balancer
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param nonlocalrs -Value 1); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Enable load balancing of non-local real servers (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Restict Wed User Interface to TLS1.2 and TLS1.3
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Credential $KempCreds -Param WUITLSProtocols -Value 7); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Restict Web User Interface to TLS1.2 and TLS1.3 (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Enable Movement of Default Gateway
$r = (Set-NetworkConfiguration -LoadBalancer $LoadmasterIP -MultiGW 1); $rc=$r.ReturnCode; $rs=$r.Response
start-sleep -Milliseconds $wait
$msg = "$rc  - Enable Movement of Default Gateway (" + $rs + ") "; $msg >> $logfile; write-host $msg

# Force use of per virtual service default gateway
$r = (Set-NetworkConfiguration -LoadBalancer $LoadmasterIP -Credential $KempCreds -OnlyDefaultRoutes 1); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Set Virtual Services to only use gateway defined in virtual service (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Set DNS Search Path
$r = (Set-NetworkDNSConfiguration -LoadBalancer $LoadmasterIP -Credential $KempCreds -Searchlist "$Search_Domain"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Set Loadmaster DNS client search domain to $Search_Domain (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait

# Enable logs to use SEF data format
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Param "CEFMsgFormat" -Value 1); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - Enable logs to use CEF data format (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait
 
# Enable KcdCipherSha1 (force kerberos to use AES256 - SHA1)
$r = (Set-LmParameter -Loadbalancer $LoadmasterIP -Param "KcdCipherSha1" -Value 1); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - AES236 - SHA1 for Kerberos (" + $rs + ") "; $msg >> $logfile; write-host $msg
start-sleep -Milliseconds $wait


###############################
# Create Content Matching Rules
###############################
Add-Content -Path $logfile -Value "`n#### CREATE CONTENT MATCHING RULES ####"
Write-Host -fore cyan "`nCREATE CONTENT MATCHING RULES"

# CREATING RULE: Citrix_Auth
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Auth" -MatchType regex -NoCase $true -Pattern "/^\/Citrix\/.*Auth\/.*|^\/Citrix\/.*\/CitrixAuth\/Login.*|\/Citrix\/.*\/ExplicitAuth\/AllowSelfServiceAccountManagement.*|\/Citrix\/.*\/Resources\/List.*/"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Auth (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Auth_Cookie
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Auth_Cookie" -MatchType regex -Header Cookie -Pattern "CtxsAuthId" -NoCase $true -OnlyOnFlag 2); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Auth_Cookie (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_LMDATA_Cookie
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_LMDATA_Cookie" -MatchType regex -Header Cookie -Pattern "lmdata" -NoCase $true -SetFlagOnMatch 2); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_LMDATA_Cookie (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_LM_Auth_Proxy
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_LM_Auth_Proxy"-MatchType regex -NoCase $true -Pattern "/^\/lm_auth_proxy.*/"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_LM_Auth_Proxy (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Logout
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Logout" -MatchType regex -Pattern "/^\/Citrix\/.*\/Authentication\/Logoff.*/" -NoCase $true -SetFlagOnMatch 3); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Logout (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Receiver_Useragent
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Receiver_Useragent" -MatchType regex -Header User-Agent -Pattern "/^CitrixReceiver.*|CitrixWorkspace.*/"-NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Receiver_Useragent (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Useragent_Desktop_Receiver
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Useragent_Desktop_Receiver" -MatchType regex -Header User-Agent -Pattern "/^CitrixReceiver.*SelfService.*|SelfService.*/"-NoCase $true -Negate $true -SetFlagOnMatch 2); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Useragent_Desktop_Receiver (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Download_ICA_File
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_Download_ICA_File" -MatchType regex -IncQuery $True -Pattern /^\/Citrix\/.*Web\/Resources\/LaunchIca\/.*CsrfToken.*/ -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Download_ICA_File (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_WorkSpace_Receiver_PreAuth
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_WorkSpace_Receiver_PreAuth" -MatchType regex -IncQuery $True -Pattern /^\/Citrix\/kempstoreAuth\/ExplicitForms$/ -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_WorkSpace_Receiver_PreAuth (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_PNAgent_Store
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_PNAgent_Store" -MatchType regex -Pattern "/^\/citrix\/store\/pnagent.*/" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_PNAgent_Store (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_PNAgent_LaunchApp
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName "Citrix_PNAgent_LaunchApp" -MatchType regex -Pattern "/^\/citrix\/store\/pnagent\/launch.aspx$/" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_PNAgent_LaunchApp (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

##################################
# Create Header Modification Rules
##################################
add-content -path $logfile -Value "`n#### CREATE HEADER MODIFICATION RULES ####"
write-host -fore cyan "`nCREATE HEADER MODIFICATION RULES"

# CREATING RULE: Citrix_AcceptEncoding
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_AcceptEncoding -Type 2 -Pattern Accept-Encoding); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_AcceptEncoding (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Browser_URL
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_Browser_URL -Type 4 -Pattern /^\/$/ -Replacement $StorePath); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Browser_URL (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Delete_CtxAithID
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_Delete_CtxAithID -Type 1 -Header Set-Cookie -Replacement "CtxsAuthId=*; expires=Thu, 14-Jun-1990 16:53:03 GMT; path=$StorePath/; secure" -OnlyOnFlag 3); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Delete_CtxAithID (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_HTTPS
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_HTTPS -Type 1 -Header X-Citrix-IsUsingHTTPS -Replacement Yes); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_HTTPS (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_HTTP_200_To_302
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_HTTP_200_To_302 -Type 4 -Pattern "200 OK" -Replacement "301 Moved Permanently"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_HTTP_200_To_302 (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Redirect
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_Redirect -Type 1 -Header Location -Replacement "https://$FQDN$StorePath/"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Redirect (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_Delete_DeviceID
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_Delete_DeviceID -Type 3 -Header Cookie -Pattern "/^CtxsDeviceId=.*\; (.*)\; (.*)/" -Replacement "\1; \2"); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_Delete_DeviceID (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

################################
# Create Body Modification Rules
################################
add-content -path $logfile -Value "`n#### CREATE BODY MODIFICATION RULES ####"
Write-Host -fore cyan "`nCREATE BODY MODIFICATION RULES"

if (-not $Reencrypt) {
  
  # CREATING RULE: Citrix_GatewayAddress
  $r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_GatewayAddress -Type 5 -Pattern "LongCommandLine="  -Replacement "Address=$FQDN" -OnlyOnFlag 2 -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
  $msg = "$rc  - CREATING RULE: Citrix_GatewayAddress (" + $rs + ") "; $msg >> $logfile; write-host $msg
  $null = start-sleep -milliseconds $wait

  # CREATING RULE: Citrix_SSL_On
  $r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName Citrix_SSL_On -Type 5 -Pattern "SSLEnable=Off" -Replacement "SSLEnable=On" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
  $msg = "$rc  - CREATING RULE: Citrix_SSL_On (" + $rs + ") "; $msg >> $logfile; write-host $msg
  $null = start-sleep -milliseconds $wait
  }

# CREATING RULE: Citrix_UDPCGP
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName  Citrix_UDPCGP -Type 5 -Pattern "/UDPCGPPort=.*:2598/" -Replacement "UDPCGPPort=$FQDN" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_UDPCGP (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_UDPICA
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName  Citrix_UDPICA -Type 5 -Pattern "/UDPICAPort=.*:1494/" -Replacement "UDPICAPort=$FQDN" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_UDPICA (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_UDPWebSocket
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName  Citrix_UDPWebSocket -Type 5 -Pattern "/UDPWebSocketPort=.*:8008/" -Replacement "UDPWebSocketPort=$FQDN" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_UDPWebSocket (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: Citrix_UDPCGP
$r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName  Citrix_UDPDTLSPort -Type 5 -Pattern "/UDPDTLSPort=.*:443/" -Replacement "UDPDTLSPort=$FQDN" -NoCase $true); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING RULE: Citrix_UDPCGP (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# CREATING RULE: $vdi2589_vs_name
if ($Reencrypt) {
    $r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName $vdi2589_vs_name -Type 5 -Pattern "/Address=.*:1494/" -Replacement "Address=$FQDN" -OnlyOnFlag 2 -NoCase 1); $rc=$r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING RULE: $vdi2589_vs_name (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
  }


write-host -fore cyan "`nALL RULES CREATED"

#############################
# Creating Virtual Services #
#############################
add-content -path $logfile -Value "`n#### CREATING VIRTUAL SERVICES ####"
Write-Host -fore cyan "`nCREATING VIRTUAL SERVICES"

######################################################
#Create VS - Citrix StoreFront Gateway - HTTP redirect
######################################################
$doit = ((Get-AdcVirtualService -LoadBalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIP -VSPort 80 -VSProtocol tcp).data.vs.nickname -ne "$VSName - HTTP redirect-Test")

if ($doit) {
$msg = "`n#### CREATING STOREFRONT GATEWAY HTTP REDIRECT VIRTUAL SERVICE ####"; add-content -path $logfile -Value $msg ; write-host $msg

# Create VS: $VSName - HTTP redirect-Test
$r = (New-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -nickname "$VSName - HTTP redirect" -VSPort 80 -VSProtocol tcp -VSType http); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CREATING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Configure VS: $VSName - HTTP redirect-Test
$r = (Set-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort 80 -VSProtocol tcp -ErrorCode 302 -ErrorUrl https://%h%s -AddVia 5); $rc=$r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CONFIGURING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait
}

#######################################
# Create VS - Citrix StoreFront Gateway
#######################################
$doit = ((Get-AdcVirtualService -LoadBalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIP -VSPort $VSPort -VSProtocol tcp).data.vs.nickname -ne "$VSName")

if ($doit) {
$msg = "`n#### CREATING STOREFRONT GATEWAY VIRTUAL SERVICE ####"; add-content -path $logfile -Value $msg ; write-host $msg

# Create VS: $VSName
$VS = (New-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -nickname $VSName -VSPort $VSPort -VSProtocol tcp -VSType http)
$VSIndex = $VS.data.VS.Index
$rc = $VS.ReturnCode; $rs=$VS.Response
$msg = "$rc  - CREATING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Configure VS: $VSName
$r = (Set-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -nickname $VSName -VSPort $VSPort -VSProtocol tcp -SSLAcceleration $true -SSLReencrypt $true -CertFile $CertName -CipherSet $VS_Cipher); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CONFIGURING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait
}

# HTTP Selection Rules 

if ($USE_ESP) {

    # Assign Rule: Citrix_Logout
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RuleType pre -RuleName Citrix_Logout); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_Logout (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Assign Rule: Citrix_LMDATA_Cookie
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RuleType pre -RuleName Citrix_LMDATA_Cookie); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_LMDATA_Cookie (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    }

# HTTP Header Modifications

# Assign Rule: Citrix_Browser_URL
$r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RuleType request -RuleName Citrix_Browser_URL); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_Browser_URL (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait


if ($Use_ESP) {
    # Assign Rule: Citrix_Delete_CtxAithID
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RuleType response -RuleName Citrix_Delete_CtxAithID); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_Delete_CtxAithID (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    } 


#############################
# Create Sub Virtual Services
#############################

if ($Use_ESP) {
    ##############################################
    # Create SubVS: StoreFront Browser Auth ESP
    ##############################################
    $msg = "`n#### CREATE STOREFRONT BROWSER AUTH ESP SUBVS ####"; add-content -path $logfile -Value $msg; write-host $msg

    $InputAuthMode = 2
    if ($Use_SAML) {$InputAuthMode = 6}
    $OutputAuthMode = 2
    if ($Use_SAML) {$OutputAuthMode = 0}
    
    $StoreFrontBrowserAuthESP = (New-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $VSIndex)
    $rc = $StoreFrontBrowserAuthESP.ReturnCode; $rs = $StoreFrontBrowserAuthESP.Response
    $StoreFrontBrowserAuthESPIndex = ($StoreFrontBrowserAuthESP.Data.VS.SubVS[-1]).VSIndex
    $StoreFrontBrowserAuthESPIndexRS = $StoreFrontBrowserAuthESP.Data.VS.SubVS.RSIndex
    $msg = "$rc  - CREATING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg

    # Configure SubVS: (core settings)
    $r = (Set-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontBrowserAuthESPIndex -Persist cookie -cookie "CtxsAuthId" -PersistTimeout 3600 -CheckPort $RSPort -CheckType https -CheckUrl $StorePath -CheckUse1_1 1 -Nickname "StoreFront Browser Auth ESP" -VSType http -Weight 1000 -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure SubVS: (ESP settings)
    $r = (Set-AdcSubVirtualService  -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontBrowserAuthESPIndex -ESPEnabled $true -InputAuthMode $InputAuthMode -AllowedHosts $FQDN -AllowedDirectories "/*" -OutputAuthMode $OutputAuthMode); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (ESP) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure SubVS: (SSO settings)
    $r = (Set-AdcSubVirtualService  -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontBrowserAuthESPIndex -Domain $Domain -ServerFbaPath "$StorePath/PostCredentialsAuth/Login" -Logoff $StorePath/Authentication/Logoff); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (SSO) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
        
    # Configure SubVS: (Add Real Servers)
    [int]$i = $Null
    [string]$ip = $Null
    for ($i=0; $i -lt $storefront.Count; $i++) {
        $ip = $storefront[$i]
        $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserAuthESPIndex -RealServer $ip -RealServerPort $RSPort -Enable $true -Forward nat -Weight 1000 -Non_Local $true); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ADDING HOST TO SUB-VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }
 
    # HTTP Header Modifications Rules

    if (-not $Use_SAML) {

        # Assign Rule: Citrix_HTTPS
        $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserAuthESPIndex -RuleType request -RuleName Citrix_HTTPS); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_HTTPS (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_AcceptEncoding
        $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserAuthESPIndex -RuleType request -RuleName Citrix_AcceptEncoding); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_AcceptEncoding (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_HTTP_200_To_302
        $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserAuthESPIndex -RuleType response -RuleName Citrix_HTTP_200_To_302); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_HTTP_200_To_302 (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Redirect
        $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserAuthESPIndex -RuleType response -RuleName Citrix_Redirect); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Redirect (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }
    }

####################################################
# Create SubVS: StoreFront Browser Launch HTML5 App
####################################################

if ($Use_HTML5) {
    $msg = "`n#### CREATE STOREFRONT BROWSER LAUNCH HTML5 SUBVS ####"; add-content -path $logfile -Value $msg; write-host $msg

    $StoreFrontBrowserLaunchHTML5App = (New-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $VSIndex)
    $rc = $StoreFrontBrowserLaunchHTML5App.ReturnCode; $rs = $StoreFrontBrowserLaunchHTML5App.Response
    $StoreFrontBrowserLaunchHTML5AppIndex =   ($StoreFrontBrowserLaunchHTML5App.Data.VS.SubVS[-1]).VSIndex
    $StoreFrontBrowserLaunchHTML5AppIndexRS = ($StoreFrontBrowserLaunchHTML5App.Data.VS.SubVS[-1]).RSIndex
    $msg = "$rc  - CREATING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg

    # Configure SubVS: (core settings)
    $r = (Set-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontBrowserLaunchHTML5AppIndex -Persist cookie -cookie "CtxsAuthId" -PersistTimeout 3600 -CheckPort $RSPort -CheckType https -CheckUrl $StorePath -CheckUse1_1 1 -Nickname "StoreFront Browser Launch HTML5 App" -VSType http -Weight 1000 -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (CORE) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure SubVS: (Add Real Servers)
    [int]$i = $Null
    [string]$ip = $Null
    for ($i=0; $i -lt $storefront.Count; $i++) {
        $ip = $storefront[$i]
        $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RealServer $ip -RealServerPort $RSPort -Enable $true -Forward nat -Weight 1000 -Non_Local $true); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ADDING HOST TO SUB-VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }
 
    # HTTP Selection Rules

    # Assign Rule: Citrix_Useragent_Desktop_Receiver
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleType pre -RuleName Citrix_Useragent_Desktop_Receiver); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_Useragent_Desktop_Receiver (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # HTTP Header Modifications Rules

    # Assign Rule: Citrix_AcceptEncoding
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleType request -RuleName Citrix_AcceptEncoding); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_AcceptEncoding (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Response Body Modification Rules
 
    if (-not $Reencrypt) {

      # Assign Rule: Citrix_GatewayAddress
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_GatewayAddress); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_GatewayAddress (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait

      # Assign Rule: Citrix_SSL_On
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_SSL_On); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_SSL_On (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait
      }  

      # Assign Rule: Citrix_UDPCGP
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_UDPCGP); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_UDPCGP (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait

      # Assign Rule: Citrix_UDPICA
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_UDPICA); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_UDPICA (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait

      # Assign Rule: Citrix_UDPWebSocket
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_UDPWebSocket); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_UDPWebSocket (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait

      # Assign Rule: Citrix_UDPDTLSPort
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName Citrix_UDPDTLSPort); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: Citrix_UDPWebSocket (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait

    }

######################################################### 
# Create SubVS: StoreFront Workspace-Receiver Add Account
#########################################################
$msg = "`n#### CREATE STOREFRONT WORKSPACE-RECEIVER ADD ACCOUNT SUBVS ####"; add-content -path $logfile -Value $msg; write-host $msg

$StoreFrontWorkspaceReceiverAddAccount = (New-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $VSIndex)
$rc = $StoreFrontWorkspaceReceiverAddAccount.ReturnCode ; $rs = $StoreFrontWorkspaceReceiverAddAccount.Response
$StoreFrontWorkspaceReceiverAddAccountIndex = ($StoreFrontWorkspaceReceiverAddAccount.Data.VS.SubVS[-1]).VSIndex
$StoreFrontWorkspaceReceiverAddAccountIndexRS = ($StoreFrontWorkspaceReceiverAddAccount.Data.VS.SubVS[-1]).RSIndex
$msg = "$rc  - CREATING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg

# Configure SubVS: StoreFront Workspace-Receiver Add Account
$r = (Set-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontWorkspaceReceiverAddAccountIndex -Persist cookie -cookie "CtxsAuthId" -PersistTimeout 3600 -CheckPort $RSPort -CheckType https -CheckUrl $StorePath -CheckUse1_1 1 -Nickname "StoreFront Workspace-Receiver Add Account" -VSType http -Weight 1000 -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (CORE) (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait
 
# Configure SubVS: (Add Real Servers)
[int]$i = $Null
[string]$ip = $Null
for ($i=0; $i -lt $storefront.Count; $i++) {
    $ip = $storefront[$i]
    $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverAddAccountIndex -RealServer $ip -RealServerPort $RSPort -Enable $true -Forward nat -Weight 1000 -Non_Local $true); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ADDING HOST TO SUB-VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    }


# HTTP Header Modification Rules

# Assign Rule: Citrix_Delete_DeviceID
$r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverAddAccountIndex -RuleType request -RuleName Citrix_Delete_DeviceID); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_Delete_DeviceID (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

#######################################################
# Create SubVS StoreFront Workspace-Receiver Launch App
#######################################################
$msg = "`n#### CREATE STOREFRONT WORKSPACE-RECEIVER LAUNCH SUBVS ####"; add-content -path $logfile -Value $msg; write-host $msg

$StoreFrontWorkspaceReceiverLaunchApp = (New-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $VSIndex)
$rc = $StoreFrontWorkspaceReceiverLaunchApp.ReturnCode ; $rs = $StoreFrontWorkspaceReceiverLaunchApp.Response
$StoreFrontWorkspaceReceiverLaunchAppIndex = ($StoreFrontWorkspaceReceiverLaunchApp.Data.VS.SubVS[-1]).VSIndex
$StoreFrontWorkspaceReceiverLaunchAppRS = ($StoreFrontWorkspaceReceiverLaunchApp.Data.VS.SubVS[-1]).RSIndex
$msg = "$rc  - CREATING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg

$r = (Set-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -Persist cookie -cookie "CtxsAuthId" -PersistTimeout 3600 -CheckPort $RSPort -CheckType https -CheckUrl $StorePath -CheckUse1_1 1 -Nickname "StoreFront Workspace-Receiver Launch App" -VSType http -Weight 1000 -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (CORE) (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Configure SubVS: (Add Real Servers)
[int]$i = $Null
[string]$ip = $Null
for ($i=0; $i -lt $storefront.Count; $i++) {
    $ip = $storefront[$i]
    $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RealServer $ip -RealServerPort $RSPort -Enable $true -Forward nat -Weight 1000 -Non_Local $true); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ADDING HOST TO SUB-VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    }

# HTTP Header Modification Rules

# Assign Rule: Citrix_Useragent_Desktop_Receiver
$r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleType pre -RuleName Citrix_Useragent_Desktop_Receiver); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_Useragent_Desktop_Receiver (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Assign Rule: Citrix_AcceptEncoding
$r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleType request -RuleName Citrix_AcceptEncoding); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_AcceptEncoding (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait


# Response Body Modification Rules will be added in the VDI 2598 Listener Virtual Services

if (-not $Reencrypt) {
  # Assign Rule: Citrix_GatewayAddress
  $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_GatewayAddress); $rc = $r.ReturnCode; $rs=$r.Response
  $msg = "$rc  - ASSIGNING RULE: Citrix_GatewayAddress (" + $rs + ") "; $msg >> $logfile; write-host $msg
  $null = start-sleep -milliseconds $wait

  # Assign Rule: Citrix_SSL_On
  $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_SSL_On); $rc = $r.ReturnCode; $rs=$r.Response
  $msg = "$rc  - ASSIGNING RULE: Citrix_SSL_On (" + $rs + ") "; $msg >> $logfile; write-host $msg
  $null = start-sleep -milliseconds $wait
  }


if ($Use_ESP) {
    #######################################################
    #SubVS StoreFront Workspace-Receiver Pre-Authentication
    #######################################################
    $msg = "`n#### CREATE STOREFRONT WORKSPACE-RECEIVER PRE-AUTHENTICATION SUBVS ####"; add-content -path $logfile -Value $msg; write-host $msg

    $StoreFrontWorkspaceReceiverPreAuthentication = (New-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $VSIndex)
    $rc = $StoreFrontWorkspaceReceiverPreAuthentication.ReturnCode; $rs = $StoreFrontWorkspaceReceiverPreAuthentication.Response
    $StoreFrontWorkspaceReceiverPreAuthenticationIndex = ($StoreFrontWorkspaceReceiverPreAuthentication.Data.VS.SubVS[-1]).VSIndex
    $StoreFrontWorkspaceReceiverPreAuthenticationIndexRS = ($StoreFrontWorkspaceReceiverPreAuthentication.Data.VS.SubVS[-1]).RSIndex
    $msg = "$rc  - CREATING SUB-VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg

    $r = (Set-AdcSubVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndex -Persist cookie -cookie "CtxsAuthId" -PersistTimeout 3600 -CheckPort $RSPort -CheckType https -CheckUrl $StorePath -CheckUse1_1 1 -Nickname "StoreFront Workspace-Receiver Pre-Authentication" -VSType http -Weight 1000 -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (CORE) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    add-content -path $logfile -Value "## Enable ESP"
    $r = (Set-AdcSubVirtualService  -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndex -ESPEnabled $true -InputAuthMode 7 -AllowedHosts $FQDN -AllowedDirectories "/*" -OutputAuthMode 2); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (ESP Part 1) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    $r = (Set-AdcSubVirtualService  -Loadbalancer $LoadmasterIP -Credential $KempCreds -SubVSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndex -Domain $Domain -ServerFbaPath "$StorePath/ExplicitAuth/Login"); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING SUB-VIRTUAL SERVICE (ESP Part 2) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
 
    # Configure SubVS: (Add Real Servers)
    [int]$i = $Null
    [string]$ip = $Null
    for ($i=0; $i -lt $storefront.Count; $i++) {
        $ip = $storefront[$i]
        $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndex -RealServer $ip -RealServerPort $RSPort -Enable $true -Forward nat -Weight 1000 -Non_Local $true); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ADDING HOST TO SUB-VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }

    # Add HTTP Header Modification Rules

    # Assign Rule: Citrix_Delete_DeviceID
    $r = (New-AdcVirtualServiceRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndex -RuleType request -RuleName Citrix_Delete_DeviceID); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: Citrix_Delete_DeviceID (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    }

# Assign Rule: Citrix_UDPCGP
$r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_UDPCGP); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_UDPCGP (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Assign Rule: Citrix_UDPICA
$r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_UDPICA); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_UDPICA (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Assign Rule: Citrix_UDPWebSocket
$r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_UDPWebSocket); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_UDPWebSocket (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Assign Rule: Citrix_UDPDTLSPort
$r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName Citrix_UDPDTLSPort); $rc = $r.ReturnCode; $rs=$r.Response
$msg = "$rc  - ASSIGNING RULE: Citrix_UDPWebSocket (" + $rs + ") "; $msg >> $logfile; write-host $msg
$null = start-sleep -milliseconds $wait

# Assign Rule: $vdi2589_vs_name
if ($Reencrypt) {
  $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName $vdi2589_vs_name); $rc = $r.ReturnCode; $rs=$r.Response
  $msg = "$rc  - ASSIGNING RULE: $vdi2589_vs_name (" + $rs + ") "; $msg >> $logfile; write-host $msg
  $null = start-sleep -milliseconds $wait
  }


########################
# Content matching rules
########################

if ($Use_ESP) {

    if ($Use_HTML5) {

        # Assign Rule: Citrix_PNAgent_Store
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_PNAgent_Store); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_Store (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_PNAgent_LaunchApp
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_PNAgent_LaunchApp); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_LaunchApp (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        

        # Assign Rule: Citrix_WorkSpace_Receiver_PreAuth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndexRS -RuleName Citrix_WorkSpace_Receiver_PreAuth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_WorkSpace_Receiver_PreAuth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Download_ICA_File
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Download_ICA_File); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Download_ICA_File (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_LM_Auth_Proxy
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName Citrix_LM_Auth_Proxy); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_LM_Auth_Proxy (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Logout
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName Citrix_Logout); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Logout (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Auth_Cookie
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserLaunchHTML5AppIndexRS -RuleName Citrix_Auth_Cookie); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth_Cookie (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Auth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_Auth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Receiver_Useragent
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Receiver_Useragent); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Receiver_Useragent (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: default
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName default); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: default (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }

    #################################################################################################

    if (-NOT $Use_HTML5) {
    
        # Assign Rule: Citrix_PNAgent_Store
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_PNAgent_Store); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_Store (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_PNAgent_LaunchApp
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_PNAgent_LaunchApp); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_LaunchApp (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Download_ICA_File
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Download_ICA_File); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Download_ICA_File (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_WorkSpace_Receiver_PreAuth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverPreAuthenticationIndexRS -RuleName Citrix_WorkSpace_Receiver_PreAuth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_WorkSpace_Receiver_PreAuth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_LM_Auth_Proxy
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName Citrix_LM_Auth_Proxy); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_LM_Auth_Proxy (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Logout
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName Citrix_Logout); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Logout (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        ## Assign Rule: Citrix_Auth_Cookie
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Auth_Cookie); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth_Cookie (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Auth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_Auth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Receiver_Useragent
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Receiver_Useragent); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Receiver_Useragent (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: default
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserAuthESPIndexRS -RuleName default); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: default (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        }

    }

#################################################################################################

if (-NOT $Use_ESP) {

    if ($Use_HTML5) {

        # Assign Rule: Citrix_PNAgent_Store
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_PNAgent_Store); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_Store (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_PNAgent_LaunchApp
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_PNAgent_LaunchApp); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_PNAgent_LaunchApp (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Download_ICA_File
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Download_ICA_File); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Download_ICA_File (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Auth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_Auth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: Citrix_Receiver_Useragent
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName Citrix_Receiver_Useragent); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Receiver_Useragent (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: default
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontBrowserLaunchHTML5AppIndexRS  -RuleName default); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: default (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait
        }
   ELSE {

        # Assign Rule: Citrix_Auth
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverAddAccountIndexRS -RuleName Citrix_Auth); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: Citrix_Auth (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        # Assign Rule: default
        $r = (New-AdcRealServerRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp -RSIndex $StoreFrontWorkspaceReceiverLaunchAppRS -RuleName default); $rc = $r.ReturnCode; $rs=$r.Response
        $msg = "$rc  - ASSIGNING RULE: default (" + $rs + ") "; $msg >> $logfile; write-host $msg
        $null = start-sleep -milliseconds $wait

        }

    }

#################################################################################################
$msg = "`nALL SUB-VIRTUAL SERVICES CREATED AND RULES ASSIGNED"; add-content -path $logfile -Value $msg; write-host $msg

########################################################################
# Completed configuration of Citrix StoreFront Gateway Virtual Service #
########################################################################

###########################################
# Create Secure Listener Virtual Services #
###########################################
$msg = "`n#### CREATE SECURE LISTENER VIRTUAL SERVICE ####"; add-content -path $logfile -Value $msg; write-host $msg

[int]$index = $starting_index - 1
[int]$port = $starting_port - 1

[array]$VS = (Get-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $VSPort -VSProtocol tcp)

#########################
# Create Secure Listeners
#########################

# Index for SubVS StoreFront Workspace-Receiver Launch App is $StoreFrontWorkspaceReceiverLaunchAppIndex
[int]$i = $Null
[string]$ip = $Null

for ($i=0; $i -lt $servers.Count; $i++) {
    $ip = $servers[$i]
    $index = $index + 1
    $Port = $port + 1 

    $RuleName = $vdi2589_vs_name + "_" + $index
    if ($Reencrypt) {$Pattern = "SSLProxyHost=" + $servers[$i] + ":443"} Else {$Pattern = "Address=" + $servers[$i] + ":1494"}
    $Replacement = "SSLProxyHost=" + $FQDN + ":" + $Port
    
    # Create Workspace Secure Listeners
    $msg = "`n#### CREATING WORKPLACE SECURE LISTENER VIRTUAL SERVICES - $Rulename ####"; add-content -path $logfile -Value $msg; write-host $msg
   
    # Create VS: Workspace VDI Instance
    $r = (New-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -nickname $RuleName -VSPort $Port -VSProtocol tcp -VSType http -SSLAcceleration $true -SSLReencrypt $false -CertFile $CertName -CheckType none -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure VS: (Type = Generic)
    $r = (Set-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $Port -VSProtocol tcp -VSType gen ); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING VIRTUAL SERVICE (CORE) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure VS: (Reencryption) (Gateway)
    $r = (Set-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $Port -VSProtocol tcp -DefaultGW $VS_GW -SSLReencrypt $Reencrypt -CipherSet $VS_Cipher); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING VIRTUAL SERVICE (Reencryption/Gateway) (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure VS: (Add Server)
    $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -RealServer $ip -RealServerPort $vdi2589_RS_Port -Non_Local 1 -Enable $true -Forward nat -Weight 1000 -VirtualService $VirtualServiceIp -VSPort $Port -VSProtocol tcp); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ADDING HOST TO VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # CREATING RULE: $RuleName
    # if ($Reencrypt) {
      $r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName $RuleName -Type 5 -Pattern $Pattern -Replacement $Replacement -NoCase 1); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - CREATING RULE: $RuleName (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait
 
      # Assign Rule: $RuleName
      $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontWorkspaceReceiverLaunchAppIndex -RuleName $RuleName); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - ASSIGNING RULE: $RuleName (" + $rs + ") "; $msg >> $logfile; write-host $msg
      $null = start-sleep -milliseconds $wait
      # }
      
# Create HTML5 Secure Listeners

  if ($Use_HTML5) {
    $Port = $port + 1 
    $RuleName = $vdi8008_vs_name + "_" + $index
    $Pattern = "Address=" + $servers[$i] + ":1494"
    $Replacement = "SSLProxyHost=" + $FQDN + ":" + $Port

    # Create 
    $msg = "`n#### CREATING HTML5 SECURE LISTENER VIRTUAL SERVICE - $Rulename ####"; add-content -path $logfile -Value $msg; write-host $msg

    # Create VS: HTML5 VDI Instance
    $r = (New-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $Port -nickname $RuleName -VSProtocol tcp -VSType gen -SSLAcceleration $true -CertFile $CertName -CheckType none -AddVia 5); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure VS: (Reecryption) (Gateway)
    $r = (Set-AdcVirtualService -Loadbalancer $LoadmasterIP -Credential $KempCreds -VirtualService $VirtualServiceIp -VSPort $Port -VSProtocol tcp -DefaultGW $VS_GW -SSLReencrypt $Reencrypt -CipherSet $VS_Cipher); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CONFIGURING VIRTUAL SERVICE (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Configure VS: (Add Server)
    add-content -path $logfile -Value "  Adding VDI Server $ip"
    $r = (New-AdcRealServer -Loadbalancer $LoadmasterIP -Credential $KempCreds -RealServer $ip -RealServerPort $vdi8008_RS_Port -Non_Local 1 -Enable $true -Forward nat -Weight 1000 -VirtualService $VirtualServiceIp -VSPort $Port -VSProtocol tcp); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ADDING HOST TO VIRTUAL SERVICE - $ip (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    
    # CREATING RULE: $RuleName
    $r = (New-AdcContentRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -RuleName $RuleName -Type 5 -Pattern $Pattern -Replacement $Replacement -NoCase 1); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - CREATING RULE: $RuleName (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait

    # Assign Rule: $RuleName
    $r = (New-AdcVirtualServiceResponseBodyRule -Loadbalancer $LoadmasterIP -Credential $KempCreds -VSIndex $StoreFrontBrowserLaunchHTML5AppIndex -RuleName $RuleName); $rc = $r.ReturnCode; $rs=$r.Response
    $msg = "$rc  - ASSIGNING RULE: $Rulename (" + $rs + ") "; $msg >> $logfile; write-host $msg
    $null = start-sleep -milliseconds $wait
    }
}
   

##################################################
# Remove IP addresses from LoadMaster DNS hostfile
##################################################

if ($ClearDNS) {
  $msg = "`n#### CLEARING LOADMASTER DNS CACHE ####"; add-content -path $logfile -value $msg; write-host $msg

  [int]$j = $Null
  [string]$i = $Null
  [array]$out = $Null
  [array]$IP = $Null
  [bool]$err = $False

  # Load IP addresses and hostnames into variables
  $IP = @(Get-Content -Path ".\$DNS_IP" | Where-Object { $_.Trim() -ne '' })

  # Read in any existing IP entries
  $out = (Get-HostsEntry -LoadBalancer $LoadmasterIP).data.LocalHosts.HostsEntry.HostIPAddress

  # unLoad DNS
  for ($j=0; ($j -lt $IP.Count); $j++){
    $i = $IP[$j]
    if ($out -contains "$i") {
      $r = (Remove-HostsEntry -LoadBalancer $LoadmasterIP -HostIP $i); $rc = $r.ReturnCode; $rs=$r.Response
      $msg = "$rc  - Removed LoadMaster DNS local list entry for $i (" + $rs + ") "; $msg >> $logfile; write-host $msg
      }
    }
  }

if ($Use_HTML5 -AND $Use_LDAP) { 
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING HTML5 AND ESP (LDAPS) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ($Use_HTML5 -AND $Use_Radius) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING HTML5 AND ESP (RADIUS) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ($Use_HTML5 -AND $Use_SAML) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING HTML5 AND ESP (SAML) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ((-NOT $Use_HTML5) -AND $Use_LDAP) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING ICA AND ESP (LDAPS) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ((-NOT $Use_HTML5) -AND $Use_Radius) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING ICA AND ESP (RADIUS) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ((-NOT $Use_HTML5) -AND $Use_SAML) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING ICA AND ESP (SAML) COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ($Use_HTML5 -AND (-NOT $Use_ESP)) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING HTML5 WITHOUT ESP COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

if ((-NOT $Use_HTML5) -AND (-NOT $Use_ESP)) {
    $msg = "`nPROVISIONING OF CITRIX VIRTUAL SERVICES USING ICA WITHOUT ESP COMPLETED"; $msg >> $logfile; write-host -fore cyan $msg
    }

# Warn user that a reboot is required to enable Sare SubVS Persistence Globally
write-host -fore DarkMagenta -BackgroundColor yellow "`nPLEASE REBOOT LOADMASTER TO COMPLETE CITRIX VIRTUAL SERVICE INSTALL`n"


#################
# END OF SCRIPT #
#################

