#Requires -RunAsAdministrator
<#
.SYNOPSIS
Makes aicenter related changes to orchestrator web.config to enable aicenter installation and access.
.DESCRIPTION
Add entries in orchestrator web.config(if not exists) for orchestrator internal IDP and aicenter access from robot and orchestrator.
Removes cache to allow access to new controllers and resets iis to load new values.
.NOTES
Name: ./orchestratorAutomation.ps1
Author: AICenter Team
Pre-Requisites: script has to be executed throuh powershell in Administrator mode & before running script set execution policy to RemoteSigned by running "Set-ExecutionPolicy RemoteSigned"
.EXAMPLE
If orchestrator is hosted at orchestrator.uipath.com and aicenter is available at ww.xx.yy.zz, command to run would be
./orchestratorAutomation.ps1 -aifip ww.xx.yy.zz -orcname orchestrator.uipath.com
If ai-app is accessed via domain instead of IP:PORT combo, then enable domainBasedAccess to true
.\orchestratorAutomation.ps1 -aifip "aif-sahil-aks.westeurope.cloudapp.azure.com" -orcname "aicenterdevorch.northeurope.cloudapp.azure.com" -portlessAccess "true"
If Orchestrator Installation Path has to be specified,
./orchestratorAutomation.ps1 -aifip ww.xx.yy.zz -orcname orchestrator.uipath.com -config "C:\Program Files (x86)\UiPath\Orchestrator"
#>
Param (
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName)]
[string] $orcname,
[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName)]
[string] $config,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName)]
[string] $aifip,
[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName)]
[string] $aifport,
[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName)]
[string] $portlessAccess,
[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName)]
[string] $storageport
)
Import-Module 'WebAdministration'
if(!$config){
$config = "C:\Program Files (x86)\UiPath\Orchestrator"
}
#if path does not end with \ add it
if( $config -notmatch '\\$' ){
$config += '\'
}
$dll_config = $config + 'UiPath.Orchestrator.dll.config'
#Fetching Orchestrator version
if(Test-Path $dll_config){
$orchestrator_version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($config + 'UiPath.Orchestrator.web.dll').FileVersion
echo "Orchestrator version : $orchestrator_version"
}
if(Test-Path $dll_config){
$config = $config + 'UiPath.Orchestrator.dll.config'
$configFile = 'UiPath.Orchestrator.dll.config'
} else{
$config = $config + 'web.config'
$configFile = 'web.config'
}
#Check for the existence of config file
if(-not (Test-Path $config)){
throw "$config File does not Exists. Please make sure that the Orchestrator installation folder is correct !"
exit
}
if(!$aifport){
$aifport = "31390"
}
if(!$storageport){
$storageport = "31443"
}
if($portlessAccess.Length -gt 0){
$portlessAccess = $portlessAccess.ToString()
} else {
$portlessAccess = "false"
}
echo "Path to Web config: "$config
Copy-Item $config -Destination ("$config.original."+(Get-Date -Format "MMddyyyy.HH.mm.ss"))
if($portlessAccess -eq "true"){
$hostName = $aifip
} else{
$hostName = "$($aifip):$($aifport)"
}
#AiFabric Settings template
$STATIC_NODES_STRING='
'
#Client App Settings
$CLIENT_APP_NODES_STRING='
'
# get orchestrator cert values
$thumbrint = $null
$RawBase64 = $null
$orchestratorhostname = $null
Get-ChildItem -Path IIS:SSLBindings | ForEach-Object -Process `
{
if ($_.Sites)
{
$_.Sites
$sname = $_.Sites.Value
echo "SiteName: $sname"
if($config.Trim().ToLower().Equals((Get-WebFilePath "IIS:\Sites\$sname\$configFile").ToString().Trim().ToLower()))
{
$certificate = Get-ChildItem -Path CERT:LocalMachine/My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
$thumbprint = $certificate.Thumbprint.ToLower()
echo "thumprint is $thumbprint"
$RawBase64 = [System.Convert]::ToBase64String($certificate.GetRawCertData())
$orchestratorhostname = ((Get-WebBinding -Name $sname) | where{$_.protocol -eq "https"}).bindingInformation.Split(":")[-1]
}
}
}
# validations of input
if($orcname)
{
if ($orcname.StartsWith("http://") -or $orcname.StartsWith("https://"))
{
echo "orcname should not start with http or https"
throw "Invalid orcname input provided: $orcname"
}
$orchestratorhostname = $orcname.ToLower()
}
if($aifip.StartsWith("http://") -or $aifip.StartsWith("https://"))
{
echo "aifip should not start with http or https"
throw "Invalid aifip input provided: $aifip"
}
# set nodes value
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{hostName}}",$hostName);
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{aifip}}",$aifip);
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{thumbprint}}",$thumbprint);
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{cert}}",$RawBase64);
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{orchestratorhostname}}",$orchestratorhostname);
$STATIC_NODES_STRING = $STATIC_NODES_STRING.Replace("{{storageport}}",$storageport);
$STATIC_NODES = [xml]$STATIC_NODES_STRING
$CLIENT_APP_NODES = [xml]$CLIENT_APP_NODES_STRING
# edit web config
function AifabricFixedConfig
{
$nodes = Select-Xml -XPath '//add' -Xml $STATIC_NODES
$additionalSection = Select-Xml -XPath '//section' -Xml $STATIC_NODES
$ClientApplicationsSection = Select-Xml -XPath '//ClientApplications' -Xml $CLIENT_APP_NODES
$file = gi $config
$xml = [xml](gc $file)
foreach($node in $nodes)
{
#remove existing nodes if they exist. They should not.
$key = $node.Node.key
$xml.SelectNodes("configuration/appSettings/add[@key='$key']") | %{$xml.configuration.appSettings.RemoveChild($_)}
$xml.configuration.appSettings.AppendChild($xml.ImportNode($node.Node,1))
}
#if DDL does not exist then orch version is 20.4 or less than that
if(!(Test-Path $dll_config)){
if($xml.SelectNodes("configuration/configSections/section[@name='ClientApplications']").Count -eq 0){
$xml.configuration.configSections.AppendChild($xml.ImportNode($additionalSection.Node,1))
}
if($xml.SelectNodes("configuration/ClientApplications").Count -eq 0){
$xml.configuration.AppendChild($xml.ImportNode($ClientApplicationsSection.Node,1))
}
}
$xml.Save($file.FullName)
}
# Reset IIS to reload values
function Retry-IISRESET
{
param (
[Parameter(Mandatory=$false)][int]$retries = 5,
[Parameter(Mandatory=$false)][int]$secondsDelay = 2
)
$retrycount = 0
$completed = $false
while (-not $completed) {
try {
iisreset | Tee-Object -Variable statusiisreset
if("$statusiisreset".Contains("failed"))
{
throw
}
Write-Verbose ("reset succeded")
$completed = $true
} catch {
if ($retrycount -ge $retries) {
throw
} else {
Start-Sleep $secondsDelay
$retrycount++
}
}
}
}
# remove cache
function EmptyAspNetCache
{
$Framework32bitFolder = "\Framework\"
$Framework64bitFolder = "\Framework64\"
$temporaryAspNetFolder = "Temporary ASP.NET Files\root"
$ControllerCacheFileName = "MS-ApiControllerTypeCache.xml"
$aspNetCacheFolder = [System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()+$temporaryAspNetFolder
if ([Environment]::Is64BitOperatingSystem)
{
$aspNetCacheFolder = $aspNetCacheFolder.Replace($Framework32bitFolder, $Framework64bitFolder);
}
if (!(Test-Path $aspNetCacheFolder))
{
echo $"Folder $aspNetCacheFolder not found for removing $ControllerCacheFileName"
return
}
echo $"Removing $ControllerCacheFileName files from ASP.NET cache folder $aspNetCacheFolder"
Get-Childitem –Path $aspNetCacheFolder -Include $ControllerCacheFileName -Recurse | ForEach {
$retrycount = 0
$retries = 3
$completed = $false
while (-not $completed) {
try {
Remove-Item $_.FullName
$completed = $true
} catch {
if ($retrycount -ge $retries) {
throw
} else {
Start-Sleep 2
$retrycount++
}
}
}
echo $"Removed $ControllerCacheFileName"
}
}
#create the proper web.config with configuration
AifabricFixedConfig
EmptyAspNetCache
Retry-IISRESET 3 2
Sleep 2
echo "Orchestrator configured successfully"