Private/WebUtil.ps1
Function Get-FreeWebPort { <# .Synopsis Find a free port for web application. .Description Find a free port for web application, starting from a given port, and increment if needed. .Parameter startingPort The port to start with. .Example # find a free port starting with 8090 Get-FreeWebPort 8090 #> [cmdletbinding()] [OutputType([int])] param( [int] $startingPort ) Process { $usedPorts = @() Import-Module WebAdministration foreach ($bind in (Get-WebBinding).bindingInformation) { $port = Get-BindingPort $bind $usedPorts += $port } $choosenPort = $startingPort while ($usedPorts.contains($choosenPort)) { $choosenPort += 10 } return $choosenPort } } function Get-BindingPort($bind) { $startIndex = $bind.indexof(':')+1 $endIndex = $bind.lastindexof(':') $port = $bind.Substring($startIndex, ($endIndex-$startIndex)) return [int] $port } function Find-WebSite($Port) { $sites = Get-WebSite foreach ($site in $sites) { $matchSite = Find-SiteMatchPort $site $Port if ($matchSite) { return $site } } return $null } function Find-SiteMatchPort($Site, $Port) { $bindings = $Site.bindings.Collection foreach ($binding in $bindings.bindingInformation) { $sitePort = Get-BindingPort $binding $siteName = $Site.Name Write-Verbose "Comparing site $sitePort with $Port" if ($sitePort -eq $Port) { Write-Verbose "Site $siteName match port $Port" return $true } } return $false } function Get-Path($Site, $WebApplication) { return "$Site/$WebApplication" } function Set-WebAuthentication($Tenant, $WebSite, $AppName, $Value, [switch] $NoSave) { $Path = Get-Path $WebSite $AppName Write-Verbose "Path is $Path" if ($Value -eq "Windows") { Set-WebConfigurationProperty -filter /system.webServer/security/authentication/windowsAuthentication -name enabled -value $true -PSPath IIS:\ -location "$Path" Set-WebConfigurationProperty -filter /system.webServer/security/authentication/AnonymousAuthentication -name enabled -value $false -PSPath IIS:\ -location "$Path" $config = (Get-WebConfiguration system.web/authentication "IIS:Sites\$Website\$AppName") $config.mode = "Windows" $config | Set-WebConfiguration system.web/authentication } if ($Value -eq "Formular") { Set-WebConfigurationProperty -filter /system.webServer/security/authentication/windowsAuthentication -name enabled -value $false -PSPath IIS:\ -location "$Path" Set-WebConfigurationProperty -filter /system.webServer/security/authentication/AnonymousAuthentication -name enabled -value $true -PSPath IIS:\ -location "$Path" $config = (Get-WebConfiguration system.web/authentication "IIS:Sites\$Website\$AppName") $config.mode = "Forms" $config | Set-WebConfiguration system.web/authentication } if (!($NoSave)) { Store-WebConf $Tenant "Authentication" $Value } Write-Verbose "Configuration saved" } function Store-WebConf($Tenant, $Key, $Value) { $path = Get-WebConfigPathFromTenant $Tenant if (!(Test-Path $path)) { md $path | Out-Null } $filePath = "$path$Key" Write-Verbose "Writing $Value to $filePath" Set-Content $filePath $Value } function Get-WebConf($Tenant, $Key) { $path = Get-WebConfigPathFromTenant $Tenant $filePath = "$path$Key" if (!(Test-Path $filePath)) { Write-Verbose "Path $filePath does not exist" return $null } Write-Verbose "Reading $filePath" $value = Get-Content $filePath Write-Verbose "$Key : $value" return $value } function Get-SSLConf($Tenant) { $ssljson = [string] (Get-WebConf $Tenant "SSL") if ($ssljson -eq $null) { $ssl = @{ "Enable" = $false; } } else { $ssl = ConvertFrom-Json $ssljson } return $ssl } function Get-AuthenticationConf($Tenant) { $authentication = Get-WebConf $Tenant "Authentication" if ($authentication -eq $null) { $authentication = "Windows" } return $authentication } function Apply-WebConfOnWebServices($webPath) { $sslConf = Get-SSLConf $Tenant if ($sslConf -eq $null) { $ssl = "false" } else { $ssl = $sslConf.Enable } $authentication = Get-AuthenticationConf $Tenant if ($authentication -eq $null) { $authentication = "Windows" } Write-Output "Web configuration - SSL: $ssl, Authentication: $authentication" $servicePath = "$webPath\services.config" $backupPath = "$webPath\services.backup" Backup-ServiceConfig $servicePath $backupPath Write-ServiceInit $servicePath Write-ServicesHeader $servicePath Write-Services $servicePath $authentication $ssl Write-ServicesFooter $servicePath } function Backup-ServiceConfig($Path, $Backup) { Write-Verbose "Creating backup of $Path to $Backup" Copy-Item $Path $Backup -force | Out-Null } function Write-ServiceInit($Path) { Write-Verbose "Initializing $Path" New-Item $Path -force | Out-Null } function Write-ServicesHeader($Path) { Add-Content $Path "<?xml version=`"1.0`"?>" Add-Content $Path "<services>" } function Write-ServicesFooter($Path) { Add-Content $Path "</services>" } function Write-Services($Path, $Authentication, $SSL) { foreach($pair in $services.GetEnumerator()) { $service = $($pair.Name) $behavior = $($pair.Value) $contract = $endpointContract[$service] if ($contract -eq $null) { $contract = $service } Write-Verbose "Registering service $service" Write-ServiceHeader $Path $service $binding = Get-Binding $Authentication "false" Write-EndPoint $Path $behavior $binding $contract if ($SSL -eq "true") { $binding = Get-Binding $Authentication "true" Write-EndPoint $Path $behavior $binding $contract } Write-ServiceFooter $Path } } function Get-Binding($Authentication, $SSL) { if ($Authentication -eq "Windows") { if ($SSL -eq "true") { return "securedWebBinding" } else { return "defaultWebBinding" } } else { if ($SSL -eq "true") { return "anoSecuredWebBinding" } else { return "anoWebBinding" } } } function Write-ServiceHeader($Path, $Service) { $header = "`t" + $serviceHeaderTemplate.Replace("[SERVICE]", $Service) Add-Content $Path $header } function Write-EndPoint($Path, $Behavior, $Binding, $Service) { $endpoint = "`t`t" + $endPointTemplate.Replace("[BEHAVIOR]", $Behavior).Replace("[BINDING]", $Binding).Replace("[SERVICE]", $Service) Add-Content $Path $endpoint } function Write-ServiceFooter($Path) { Add-Content $Path "`t</service>" } $serviceHeaderTemplate = "<service behaviorConfiguration=`"httpGetEnablingBehavior`" name=`"[SERVICE]`">" $endPointTemplate = "<endpoint address=`"`" behaviorConfiguration=`"[BEHAVIOR]`" binding=`"webHttpBinding`" bindingConfiguration=`"[BINDING]`" contract=`"[SERVICE]`"/>" $services = @{ "Ortems.PlannerOne.Web.UserControl.CalendarExceptions.CalendarException" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Indicators.IndicatorsService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Scheduling.ConfirmationLoader" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Sequencing.SequencingService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.Custom.TaskColorService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Filter.FilterService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Views.ResourceSequence.ResourceSequenceService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.DetailsPanel.InfoService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Utilities.UtilitiesService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.RefreshService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.ViewsService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.Custom.RowService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.Custom.Task" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Robots.RobotsService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Search.SearchService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Action.ManageTask.TaskManagerService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Views.Calendar.Service" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.ActivityComputation.ActivityComputationService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Service.SelectionService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Views.JobOverview.JobOverviewService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.Display.Total.TotalService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Service.ViewsService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.SwitchPlanning.SwitchPlanningService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.MoveTasks.MoveTasksService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Api.PlanningProduction" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Api.PlanningProject" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.UserControl.WebGantt.Gantt" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Admin.PerformanceService" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Admin.PerformanceSessionService" = "webHttp"; "Ortems.PlannerOne.Web.Admin.WebSecurityService" = "webHttp"; "Ortems.PlannerOne.Web.UserControl.Action.Assignment.ChooseResource" = "webScriptEnablingBehavior"; "Ortems.PlannerOne.Web.Configure.ConfigurationService" = "webHttp"; "Ortems.PlannerOne.Web.Admin.ICalConfigurationService" = "webHttp"; "Ortems.PlannerOne.Web.UserControl.PinTasks.PinTasksService" = "webScriptEnablingBehavior"; } $endpointContract = @{ "Ortems.PlannerOne.Web.Api.PlanningProduction" = "Ortems.PlannerOne.Web.Api.IPlanningProductionContract"; "Ortems.PlannerOne.Web.Api.PlanningProject" = "Ortems.PlannerOne.Web.Api.IPlanningContract" } function Register-P1WebServices($Tenant) { Write-Section "Registering Web services for current security" if (!(Test-Tenant $Tenant)) { Write-Warning "Tenant $Tenant does not exist." Write-Warning "Operation canceled." return; } $info = Get-P1Tenant $Tenant $host = $info.WebHost $port = $info.SitePort $app = $info.WebApplicationName Write-Output "Host: $host, Port: $port, Application name: $app" $site = Find-WebSite $port $siteName = $site.Name if ($site -eq $null) { Write-Warning "No site use binding $port configured for tenant Web Application $app of tenant $Tenant. Operation canceled." return } else { Write-Verbose "Site found" } $webApp = Get-WebApplication -Name $app -Site $siteName if ($webApp -eq $null) { Write-Warning "Cannot find Web Application $app for port $port" } else { Write-Verbose "Web Application found" } $path = $webApp.PhysicalPath Write-Verbose "Physical path is $path" Apply-WebConfOnWebServices $path Write-OK "REST services registered with security for tenant $Tenant" } function Set-WebAuthenticationInternal([string] $Tenant, [switch] $Windows, [switch] $Formular, [switch] $NoSave) { $info = Get-P1Tenant $Tenant $host = $info.WebHost $port = $info.SitePort $app = $info.WebApplicationName Write-Verbose "Host: $host, Port: $port, Application name: $app" $site = Find-WebSite $port $siteName = $site.Name if ($site -eq $null) { Write-Warning "No site use binding $port configured for tenant Web Application $app of tenant $Tenant. Operation canceled." return } else { Write-Verbose "Site found" } $webApp = Get-WebApplication -Name $app -Site $siteName if ($webApp -eq $null) { Write-Warning "Cannot find Web Application $app for port $port" } else { Write-Verbose "Web Application found" } $mode = "" if ($Windows) { $mode = "Windows" } if ($Formular) { $mode = "Formular" } Write-Verbose "Mode will be set to $mode" Set-WebAuthentication $Tenant $siteName $app $mode -NoSave:$NoSave.IsPresent } function Set-WebSSLInternal([string] $Tenant, [switch] $Enable, [switch] $Disable, [int] $SSLPort, [string] $CertificateStore, [string] $CertificateFriendlyName, [string] $CertificateThumbprint, [string] $HostedIP, [switch] $NoSave) { if ($SSLPort -eq 0) { Write-Warning "No SSL Port define, trying with 443." $SSLPort = 443 } $info = Get-P1Tenant $Tenant $host = $info.WebHost $port = $info.SitePort $app = $info.WebApplicationName Write-Verbose "Host: $host, Port: $port, Application name: $app" $site = Find-WebSite $port $siteName = $site.Name if ($site -eq $null) { Write-Warning "No site use binding $port configured for tenant Web Application $app of tenant $Tenant. Operation canceled." return } else { Write-Verbose "Site found" } $bindingHostedIP = $HostedIP if ($HostedIP -eq "" -or $HostedIP -eq "0.0.0.0") { $HostedIP = "0.0.0.0" $bindingHostedIP = "*" } # Disable binding for site if ($Disable) { Write-Verbose "Removing binding $SSLPort on site $siteName" try { Remove-WebBinding -Name "$siteName" -Port $SSLPort -ErrorAction Stop } catch { Write-KO "Web application binding for port $SSLPort does not exist" } Write-Verbose "Removing SSL binding record" try { Remove-Item "IIS:\SslBindings\$HostedIP!$SSLPort" -ErrorAction Stop } catch { Write-KO "SSL Binding IIS:\SslBindings\$HostedIP!$SSLPort does not exist" } if (!($NoSave)) { $conf = @{ "Enable" = $false; } $jsonConf = ConvertTo-Json $conf Store-WebConf $Tenant "SSL" $jsonConf } Write-OK "Web SSL disabled for tenant $Tenant" return } # Create binding for site Write-Verbose "Creating new binding $SSLPort on site $siteName" try { New-WebBinding -Name "$siteName" -IPAddress "$bindingHostedIP" -Port $SSLPort -Protocol https } catch { Write-KO "Port is already define on site" return } # Create SSL Binding in IIS if ($CertificateStore -eq "") { $CertificateStore = "My" } if ($CertificateFriendlyName -ne "" -and $CertificateThumbprint -ne "" ) { Write-Warning "You can only use one certificate option between CertificateFriendlyName and CertificateThumbprint" return } if ($CertificateFriendlyName -eq "" -and $CertificateThumbprint -eq "" ) { Write-Warning "You must choose one certificate option between CertificateFriendlyName and CertificateThumbprint" return } $certificateLocation = "cert:\LocalMachine\$CertificateStore" Write-Verbose "Certificate location is $certificateLocation" if ($CertificateFriendlyName -ne "") { Write-Verbose "Searching for certificate with friendly name $CertificateFriendlyName" $certificate = Get-ChildItem $certificateLocation | where-object { $_.FriendlyName -eq "$CertificateFriendlyName" } } if ($CertificateThumbprint -ne "") { Write-Verbose "Searching for certificate with thumbprint $CertificateThumbprint" $certificate = Get-ChildItem $certificateLocation | where-object { $_.Thumbprint -eq "$CertificateThumbprint" } } if ($certificate -eq $null) { Write-KO "Cannot find certificate $CertificateFriendlyName $CertificateThumbprint in $certificateLocation" return } else { # Thumbprint is store in configuration $CertificateThumbprint = $certificate.Thumbprint Write-Verbose "Certificate has been found" } Write-Verbose "Writing SSL binding IIS:\SslBindings\$HostedIP!$SSLPort" try { $certificate | New-Item "IIS:\SslBindings\$HostedIP!$SSLPort" } catch { Write-KO "IIS SSL binding IIS:\SslBindings\$HostedIP!$SSLPort already exist" } Write-Verbose "SSL binding written" if (!($NoSave)) { $conf = @{ "Enable" = $true; "Port" = $SSLPort; "Store" = "$CertificateStore"; "Thumbprint" = "$CertificateThumbprint"; "IP" = "$HostedIP"; } $jsonConf = ConvertTo-Json $conf Store-WebConf $Tenant "SSL" $jsonConf } } |