SHARE
TWEET

Untitled

a guest Jun 1st, 2018 603 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. DESCRIPTION   This script will create a configured Remote Desktop Session Farm.
  3. Author:         Julian Mooren | https://citrixguyblog.com
  4. Contributer:    Sander van Gelderen | https://www.van-gelderen.eu
  5. Creation Date:  12.05.17
  6. Change Date:    09.02.18
  7. #>
  8.  
  9.  
  10. #Requires -version 4.0
  11. #Requires -RunAsAdministrator
  12.  
  13. #Functions
  14. #http://www.leeholmes.com/blog/2009/11/20/testing-for-powershell-remoting-test-psremoting/
  15. function Test-PsRemoting {
  16.     param(
  17.         [Parameter(Mandatory = $true)]
  18.         $computername
  19.     )
  20.    
  21.     try
  22.     {
  23.         $errorActionPreference = "Stop"
  24.         $result = Invoke-Command -ComputerName $computername { 1 }
  25.     }
  26.     catch
  27.     {
  28.         Write-Verbose $_
  29.         return $false
  30.     }
  31.    
  32.     ## I've never seen this happen, but if you want to be
  33.     ## thorough....
  34.     if($result -ne 1)
  35.     {
  36.         Write-Verbose "Remoting to $computerName returned an unexpected result."
  37.         return $false
  38.     }
  39.    
  40.     $true  
  41. } # end Test-PsRemoting
  42.  
  43. function Test-SQLDatabase
  44. {
  45.     param(
  46.     [Parameter(Position=0, Mandatory=$True, ValueFromPipeline=$True)] [string] $Server,
  47.     [Parameter(Position=1, Mandatory=$True)] [string] $Database,
  48.     [Parameter(Position=2, Mandatory=$True, ParameterSetName="SQLAuth")] [string] $Username,
  49.     [Parameter(Position=3, Mandatory=$True, ParameterSetName="SQLAuth")] [string] $Password,
  50.     [Parameter(Position=2, Mandatory=$True, ParameterSetName="WindowsAuth")] [switch] $UseWindowsAuthentication
  51.     )
  52.  
  53.     # connect to the database, then immediatly close the connection. If an exception occurrs it indicates the conneciton was not successful.
  54.     process {
  55.         $dbConnection = New-Object System.Data.SqlClient.SqlConnection
  56.         if (!$UseWindowsAuthentication) {
  57.             $dbConnection.ConnectionString = "Data Source=$Server; uid=$Username; pwd=$Password; Database=$Database;Integrated Security=False"
  58.             $authentication = "SQL ($Username)"
  59.         }
  60.         else {
  61.             $dbConnection.ConnectionString = "Data Source=$Server; Database=$Database;Integrated Security=True;"
  62.             $authentication = "Windows ($env:USERNAME)"
  63.         }
  64.         try {
  65.             $connectionTime = measure-command {$dbConnection.Open()}
  66.             $Result = @{
  67.                 Connection = "Successful"
  68.                 ElapsedTime = $connectionTime.TotalSeconds
  69.                 Server = $Server
  70.                 Database = $Database
  71.                 User = $authentication}
  72.         }
  73.         # exceptions will be raised if the database connection failed.
  74.         catch {
  75.                 $Result = @{
  76.                 Connection = "Failed"
  77.                 ElapsedTime = $connectionTime.TotalSeconds
  78.                 Server = $Server
  79.                 Database = $Database
  80.                 User = $authentication}
  81.         }
  82.         Finally{
  83.             # close the database connection
  84.             $dbConnection.Close()
  85.             #return the results as an object
  86.             $outputObject = New-Object -Property $Result -TypeName psobject
  87.             write-output $outputObject
  88.         }
  89.     }
  90. }
  91.  
  92. # Thanks @xenappblog.com for the Transcript Log idea
  93. $configpath= "C:\rds\config.json"
  94. $StartDate = (Get-Date)
  95. $Vendor = "Microsoft"
  96. $Product = "Remote Desktop Farm"
  97. $Version = "2016"
  98. $LogPath = "${env:SystemRoot}" + "\Temp\$Vendor $Product $Version.log"
  99.  
  100. Start-Transcript $LogPath
  101.  
  102. #region "Check Prerequisites"
  103. Write-Verbose "Check Prerequisites" -Verbose
  104.  
  105. #check that we are running script on Domain Controller
  106. if (Get-WindowsFeature -Name AD-Domain-Services | Where-Object {$_.Installed -eq $False}) {
  107.     Write-Warning "You are not running script on Domain Controller. Abort."
  108.     Stop-Transcript
  109.     break
  110. } else { Write-Verbose "You are on Domain Controller - good." }
  111.  
  112. if (Get-WindowsFeature -Name RSAT-AD-Tools, RSAT-DNS-Server){
  113.    Write-Verbose "Needed PowerShell Modules available." -Verbose
  114. } else {    
  115.     Write-Verbose "Needed PowerShell Modules will be installed." -Verbose
  116.     Install-WindowsFeature RSAT-AD-Tools, RSAT-DNS-Server
  117.     Write-Verbose "Needed PowerShell Modules have been installed." -Verbose
  118. } #end if Get-WindowsFeature
  119.  
  120. if (Test-Path $configpath) {
  121.     Write-Verbose "JSON File was found." -Verbose
  122.     $config = Get-Content -Path $configpath -Raw | ConvertFrom-Json
  123.     Write-Verbose "JSON File was imported." -Verbose
  124. } else {
  125.     Write-Warning "Failed to find the JSON File."
  126.     Stop-Transcript
  127.     break
  128. } #end if Test-Path $configpath
  129.  
  130. if (Test-Path $config.CertPath) {
  131.     Write-Verbose "SSL Certificate was found." -Verbose
  132. } Else {
  133.     Write-Warning "Failed to find the SSL Certificate."
  134.     Stop-Transcript
  135.     break
  136. } # end if Test-Path $config.CertPath
  137.  
  138. #check if logged in user is Domain Admin
  139. $LocalUser = &whoami
  140. $AdminUsernames = Get-ADGroupMember -Identity 'Domain Admins' -Recursive | Select-Object -ExpandProperty SamAccountName
  141. $AdminUsers = $AdminUsernames | ForEach-Object {$config.DomainNetbios+"\"+$_}
  142. If ($AdminUsers.Contains($LocalUser) -eq $False) {
  143.     Write-Warning "Logged in user does not belong to Domain Admins -group!"
  144.     Stop-Transcript
  145.     break
  146. } else { Write-Verbose "$LocalUser is Domain Admin - excellent." }
  147.  
  148. #endregion "Check Prerequisites"
  149.  
  150. #region TEST
  151. if($config.HADeployment -like "Yes"){
  152.  
  153.     if(Test-PsRemoting -computername $config.RDSHost01, $config.RDSHost02, $config.ConnectionBroker01, $config.ConnectionBroker02, $config.WebAccessServer01, $config.WebAccessServer02, $config.RDGatewayServer01, $config.RDGatewayServer02, $config.FileServerCluster ){
  154.         Write-Verbose "PSRemoting is enabled on all Hosts." -Verbose
  155.     } Else {
  156.         Write-Warning "PSRemoting is not enabled on all Hosts." -Verbose
  157.         $PSRemoteHA = @("$($config.RDSHost01)","$($config.RDSHost02)","$($config.ConnectionBroker01)","$($config.ConnectionBroker02)","$($config.WebAccessServer01)","$($config.WebAccessServer02)","$($config.RDGatewayServer01)","$($config.RDGatewayServer02)")
  158.         foreach($TestHA in $PSRemoteHA){
  159.             $status = Test-PsRemoting -computername $TestHA; "$TestHA;$status"
  160.         }
  161.         Stop-Transcript
  162.         break
  163.     } #end if Test-PsRemoting
  164.  
  165.     # Test SQL connection and logging
  166.     $SQLConnection = Test-SQLDatabase -Server $config.SQLServer -Database $config.SQLDatabase -UseWindowsAuthentication
  167.  
  168.     If ($SQLConnection.Connection -eq "Successful") {
  169.         Write-Verbose "SQL connection successful, $config.SQLDatabase exists"
  170.     }
  171.     else {
  172.         Write-Warning "Cannot reach SQL Database ($config.SQLDatabase), exiting ..."
  173.         Stop-Transcript
  174.         break
  175.     } #end of SQL tests
  176.  
  177.     #Add AD groups
  178.     Import-Module Activedirectory
  179.     $NameRDSAccessGroup = $config.RDSAccessGroup.split('@')[0]
  180.     $NameGatewayAccessGroup = $config.GatewayAccessGroup.split('@')[0]
  181.     New-ADGroup -Name $NameRDSAccessGroup -DisplayName $NameRDSAccessGroup -GroupCategory Security -GroupScope Global
  182.     New-ADGroup -Name $NameGatewayAccessGroup -DisplayName $NameGatewayAccessGroup -GroupCategory Security -GroupScope Global
  183.  
  184.     try {Invoke-WebRequest -Uri "https://download.microsoft.com/download/8/7/2/872BCECA-C849-4B40-8EBE-21D48CDF1456/ENU/x64/sqlncli.msi"} catch {Write-Warning "Couldnt Download SQL Native Client, copy sqlncli.msi to your broker servers.";Stop-Transcript; break}    
  185.  
  186.     if(!($NameGatewayAccessGroup)){Write-Warning "AD group $NameGatewayAccessGroup does not exist.";Stop-Transcript; break}
  187.  
  188.     #enable SMB    
  189.     Invoke-Command -ComputerName $config.ConnectionBroker01 {
  190.         Get-NetFirewallRule -DisplayName "File and Printer Sharing (SMB-In)" | Enable-NetFirewallRule
  191.     }
  192.     if(Test-Path "\\$($config.ConnectionBroker01)\c$"){Write-Verbose "UNC path reachable"} else { Write-Warning "$($config.ConnectionBroker01) might have troubles";Stop-Transcript; break}
  193.  
  194.     Invoke-Command -ComputerName $config.ConnectionBroker02 {
  195.         Get-NetFirewallRule -DisplayName "File and Printer Sharing (SMB-In)" | Enable-NetFirewallRule
  196.     }
  197.     if(Test-Path "\\$($config.ConnectionBroker02)\c$"){Write-Verbose "UNC path reachable"} else { Write-Warning "$($config.ConnectionBroker02) might have troubles"}
  198.    
  199. }
  200.  
  201. #enable SMB on FileServerCluster
  202. Invoke-Command -ComputerName $config.FileServerCluster {
  203.     Get-NetFirewallRule -DisplayName "File and Printer Sharing (SMB-In)" | Enable-NetFirewallRule
  204. }
  205.  
  206. # create UserProfile folder & set permissions
  207. if(Test-Path "\\$($config.FileServerCluster)\c$") {
  208.     Write-Verbose "UNC path reachable"    
  209.     #invoke-command -computername DC2 -scriptblock {new-item -itemtype directory -path $args[0] -verbose -credentials $args[1]} -argumentlist $homeDir,$cred
  210.     Invoke-Command -ComputerName $config.FileServerCluster -ArgumentList $config.ProfilePath, $config.DomainNetbios, $config.AdminGroup {              
  211.         $ProfilePath = $args[0]
  212.         $DomainNetbios = $args[1]
  213.         $AdminGroup = $args[2]
  214.         New-Item -ItemType directory -Path $ProfilePath
  215.         New-SMBShare –Name "UserProfiles" –Path $ProfilePath –FullAccess "$DomainNetbios\$AdminGroup" -ReadAccess "Everyone"
  216.     }
  217. }
  218. else { Write-Warning "$($config.FileServerCluster) might have troubles. Could not reach Cee dollar";Stop-Transcript; break }
  219.  
  220. if(Test-Path "$($config.ProfileDiskPath)"){Write-Verbose "Profile path reachable"  -Verbose} else { Write-Warning "$($config.ProfileDiskPath) might have troubles"  -Verbose;Stop-Transcript; break}
  221.  
  222. if(!($NameRDSAccessGroup)){Write-Warning "AD group $NameRDSAccessGroup does not exist."  -Verbose;Stop-Transcript; break}
  223.  
  224. Read-Host "All Testing is done. Ready for the real stuff? -> Press enter to continue"
  225.  
  226. #endregion TEST
  227.  
  228. Write-Verbose "Starting Installation of $Vendor $Product $Version" -Verbose
  229.  
  230. # Import the RemoteDesktop Module
  231. Import-Module RemoteDesktop
  232.  
  233. ##### MultiDeployment Configuration Parameters #####
  234.  
  235. if($config.MultiDeployment -like "Yes"){
  236.  
  237.     # Create RDS deployment
  238.     New-RDSessionDeployment -ConnectionBroker $config.ConnectionBroker01 -WebAccessServer $config.WebAccessServer01 -SessionHost @($config.RDSHost01, $config.RDSHost02)
  239.     Write-Verbose "Created new RDS deployment" -Verbose
  240.  
  241.     # Create Desktop Collection
  242.     New-RDSessionCollection  -CollectionName $config.DesktopCollectionName -SessionHost @($config.RDSHost01, $config.RDSHost02)  -CollectionDescription $config.DesktopDiscription  -ConnectionBroker $config.ConnectionBroker01
  243.     Write-Verbose "Created new Desktop Collection"  -Verbose
  244.  
  245.     #Install Gateway
  246.     Add-WindowsFeature -Name RDS-Gateway -IncludeManagementTools -ComputerName $config.RDGatewayServer01
  247.     Write-Verbose "Installed RDS Gateway"  -Verbose
  248.  
  249.     #Join Gateway to Broker
  250.     Add-RDServer -Server $config.RDGatewayServer01 -Role "RDS-GATEWAY" -ConnectionBroker $config.ConnectionBroker01 -GatewayExternalFqdn $config.GatewayExternalFqdn
  251.     Write-Verbose "Joined RDS Gateway to Broker"  -Verbose
  252.    
  253.     # Configure GW Policies on RDGatewayServer01
  254.     Invoke-Command -ComputerName $config.RDGatewayServer01 -ArgumentList $config.GatewayAccessGroup, $config.RDBrokerDNSInternalName, $config.RDBrokerDNSInternalZone, $config.RDSHost01, $config.RDSHost02 -ScriptBlock {
  255.         $GatewayAccessGroup = $args[0]
  256.         $RDBrokerDNSInternalName = $args[1]
  257.         $RDBrokerDNSInternalZone = $args[2]
  258.         $RDSHost01 = $args[3]
  259.         $RDSHost02 = $args[4]
  260.         Import-Module RemoteDesktopServices
  261.         Remove-Item -Path "RDS:\GatewayServer\CAP\RDG_CAP_AllUsers" -Force -recurse
  262.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_RDConnectionBrokers" -Force -recurse
  263.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_AllDomainComputers" -Force -recurse
  264.         Remove-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDG_RDCBComputers" -Force -recurse
  265.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups" -Name "RDSFarm1" -Description "RDSFarm1" -Computers "$RDBrokerDNSInternalName.$RDBrokerDNSInternalZone" -ItemType "String"
  266.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDSFarm1\Computers" -Name $RDSHost01 -ItemType "String"
  267.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDSFarm1\Computers" -Name $RDSHost02 -ItemType "String"
  268.  
  269.         New-Item -Path "RDS:\GatewayServer\RAP" -Name "RDG_RAP_RDSFarm1" -UserGroups $GatewayAccessGroup -ComputerGroupType 0 -ComputerGroup "RDSFarm1"
  270.         New-Item -Path "RDS:\GatewayServer\CAP" -Name "RDG_CAP_RDSFarm1" -UserGroups $GatewayAccessGroup -AuthMethod 1
  271.  
  272.     }
  273.     Write-Verbose "Configured CAP & RAP Policies on: $($config.RDGatewayServer01)"  -Verbose
  274.  
  275.     read-host "Configuring CAP & RAP on $($config.RDGatewayServer01) error? Re-run this part of the script before continue"
  276.  
  277.     # Create WebAccess DNS-Record
  278.     Import-Module DNSServer
  279.     $IPWebAccess01 = [System.Net.Dns]::GetHostAddresses("$($config.WebAccessServer01)")[0].IPAddressToString
  280.     Add-DnsServerResourceRecordA -ComputerName $config.DomainController -Name $config.RDWebAccessDNSInternalName -ZoneName $config.RDWebAccessDNSInternalZone -AllowUpdateAny -IPv4Address $IPWebAccess01
  281.     Write-Verbose "Configured WebAccess DNS-Record"  -Verbose
  282.  
  283.     # Redirect to RDWeb (IIS)
  284.     Invoke-Command -ComputerName $config.WebAccessServer01 -ArgumentList $config.RDWebAccessDNSInternalName, $config.RDWebAccessDNSInternalZone  -ScriptBlock {
  285.         $RDWebAccessDNSInternalName = $args[0]
  286.         $RDWebAccessDNSInternalZone = $args[1]
  287.         $siteName = "Default Web Site"
  288.         Import-Module webAdministration
  289.         Set-WebConfiguration system.webServer/httpRedirect "IIS:\sites\$siteName" -Value @{enabled="true";destination="https://$RDWebAccessDNSInternalName.$RDWebAccessDNSInternalZone/RDWeb";exactDestination="true";httpResponseStatus="Found"}
  290.     } #end Redirect to RDWeb
  291.     Write-Verbose "Configured RDWeb Redirect"  -Verbose
  292.  
  293. } #end if $config.MultiDeployment
  294.  
  295. #region Default Configuration Parameters
  296. ##### Default Configuration Parameters #####
  297.  
  298. # Set Access Group for RDS Farm
  299. Set-RDSessionCollectionConfiguration -CollectionName $config.DesktopCollectionName -UserGroup $config.RDSAccessGroup -ConnectionBroker $config.ConnectionBroker01
  300. Write-Verbose "Configured Access for $($config.RDSAccessGroup)"  -Verbose
  301.  
  302. # Set Profile Disk
  303. Set-RDSessionCollectionConfiguration -CollectionName $config.DesktopCollectionName -EnableUserProfileDisk -MaxUserProfileDiskSizeGB "20" -DiskPath $config.ProfileDiskPath -ConnectionBroker $config.ConnectionBroker01
  304. Write-Verbose "Configured ProfileDisk"  -Verbose
  305.  
  306. # RDS Licencing
  307. Add-RDServer -Server $config.LICserver1 -Role "RDS-LICENSING" -ConnectionBroker $config.ConnectionBroker01
  308. Add-RDServer -Server $config.LICserver2 -Role "RDS-LICENSING" -ConnectionBroker $config.ConnectionBroker02
  309. Write-Verbose "Installed RDS Licence Server: $($config.LICserver)"  -Verbose
  310. Set-RDLicenseConfiguration -LicenseServer $config.LICserver1, $config.LICserver2 -Mode $config.LICmode -ConnectionBroker $config.ConnectionBroker01 -Force
  311. Write-Verbose "Configured RDS Licening. $config.ConnectionBroker01 is primary License server!"  -Verbose
  312.  
  313. # Set Certificates
  314. $Password = ConvertTo-SecureString -String $config.CertPassword -AsPlainText -Force
  315. Set-RDCertificate -Role RDPublishing -ImportPath $config.CertPath  -Password $Password -ConnectionBroker $config.ConnectionBroker01 -Force
  316. Set-RDCertificate -Role RDRedirector -ImportPath $config.CertPath -Password $Password -ConnectionBroker $config.ConnectionBroker01 -Force
  317. Set-RDCertificate -Role RDWebAccess -ImportPath $config.CertPath -Password $Password -ConnectionBroker $config.ConnectionBroker01 -Force
  318. Set-RDCertificate -Role RDGateway -ImportPath $config.CertPath  -Password $Password -ConnectionBroker $config.ConnectionBroker01 -Force
  319. Write-Verbose "Configured SSL Certificates"  -Verbose
  320.  
  321. # Configure WebAccess (when RDBroker is available, no Gateway will be used)
  322. Set-RDDeploymentGatewayConfiguration -GatewayMode Custom -GatewayExternalFqdn $config.GatewayExternalFqdn -LogonMethod Password -UseCachedCredentials $True -BypassLocal $True -ConnectionBroker $config.ConnectionBroker01 -Force
  323. Write-Verbose "Configured Gateway Mapping"  -Verbose
  324.  
  325. # Create TXT WebFeed DNS Record - Create RemoteAccess connection via e-Mail address
  326. Add-DnsServerResourceRecord -ZoneName $config.RDWebAccessDNSInternalZone -Name "_msradc" -Txt -DescriptiveText "https://$($config.RDWebAccessDNSInternalName).$($config.RDWebAccessDNSInternalZone)/RDWeb/Feed"
  327. Write-Verbose "Created TXT WebFeed DNS Record"  -Verbose
  328.  
  329. # Create RDS Broker DNS-Record
  330. Import-Module DNSServer
  331. $IPBroker01 = [System.Net.Dns]::GetHostAddresses("$($config.ConnectionBroker01)")[0].IPAddressToString
  332. Add-DnsServerResourceRecordA -ComputerName $config.DomainController  -Name $config.RDBrokerDNSInternalName -ZoneName $config.RDBrokerDNSInternalZone -AllowUpdateAny -IPv4Address $IPBroker01
  333. Write-Verbose "Configured RDSBroker DNS-Record"  -Verbose
  334.  
  335. #Change RDPublishedName
  336. #https://gallery.technet.microsoft.com/Change-published-FQDN-for-2a029b80
  337. Invoke-WebRequest -Uri "https://gallery.technet.microsoft.com/Change-published-FQDN-for-2a029b80/file/103829/2/Set-RDPublishedName.ps1" -OutFile "c:\rds\Set-RDPublishedName.ps1"
  338. Copy-Item "c:\rds\Set-RDPublishedName.ps1" -Destination "\\$($config.ConnectionBroker01)\c$"
  339. Invoke-Command -ComputerName $config.ConnectionBroker01 -ArgumentList $config.RDBrokerDNSInternalName, $config.RDBrokerDNSInternalZone -ScriptBlock {
  340.     $RDBrokerDNSInternalName = $args[0]
  341.     $RDBrokerDNSInternalZone = $args[1]
  342.     Set-Location C:\
  343.     .\Set-RDPublishedName.ps1 -ClientAccessName "$RDBrokerDNSInternalName.$RDBrokerDNSInternalZone"
  344.     Remove-Item "C:\Set-RDPublishedName.ps1"
  345. }
  346. Write-Verbose "Configured RDPublisher Name"  -Verbose
  347. #endregion Default Configuration Parameters
  348.  
  349.  
  350. ##### HA Configuration Configuration Parameters #####
  351.  
  352. if($config.HADeployment -like "Yes"){
  353.  
  354.     #Create HA Broker Security Group for SQL Database Access
  355.     Import-Module ActiveDirectory
  356.     New-ADGroup  -Name "RDS_Connection_Brokers" -GroupCategory Security -GroupScope Global  -Server $config.DomainController
  357.     #wrong servers where added to the group (RDS), changed to brokers
  358.     Add-ADGroupMember -Identity "RDS_Connection_Brokers" -Members "$($config.ConnectionBroker01.Split(".")[0])$" -Server $config.DomainController
  359.     Add-ADGroupMember -Identity "RDS_Connection_Brokers" -Members "$($config.ConnectionBroker02.Split(".")[0])$" -Server $config.DomainController
  360.     Write-Verbose "Created RDSBroker Security Group in ActiveDirectory" -Verbose
  361.  
  362.     # Restart Broker Server (that Broker Security Group is being applied)
  363.     #alternative without server reboot
  364.     #klist -lh 0 -li 0x3e7 purge
  365.     #klist -lh 0 -li x3e7 purge
  366.  
  367.     Write-Verbose "$($config.ConnectionBroker01) will reboot"  -Verbose
  368.     Restart-Computer -ComputerName $config.ConnectionBroker01 -Wait -For PowerShell -Timeout 300 -Delay 2 -Force
  369.     Write-Verbose "$($config.ConnectionBroker01) online again"  -Verbose
  370.  
  371.     #Reboot ConnectionBroker02 (without Reboot, there can occur errors with the next commands)
  372.     Write-Verbose "$($config.ConnectionBroker02) will reboot"  -Verbose
  373.     Restart-Computer -ComputerName $config.ConnectionBroker02 -Wait -For PowerShell -Timeout 300 -Delay 2 -Force
  374.     Write-Verbose "$($config.ConnectionBroker02) online again"  -Verbose
  375.  
  376.     # Create HA RDS Broker DNS-Record
  377.     Import-Module DNSServer
  378.     $IPBroker02 = [System.Net.Dns]::GetHostAddresses("$($config.ConnectionBroker02)")[0].IPAddressToString
  379.     Add-DnsServerResourceRecordA -ComputerName $config.DomainController  -Name $config.RDBrokerDNSInternalName -ZoneName $config.RDBrokerDNSInternalZone -AllowUpdateAny -IPv4Address $IPBroker02
  380.     Write-Verbose "Configured RDSBroker DNS-Record"  -Verbose
  381.  
  382.     # Create HA WebAccess DNS-Record
  383.     Import-Module DNSServer
  384.     $IPWebAccess02 = [System.Net.Dns]::GetHostAddresses("$($config.WebAccessServer02)")[0].IPAddressToString
  385.     Add-DnsServerResourceRecordA -ComputerName $config.DomainController  -Name $config.RDWebAccessDNSInternalName -ZoneName $config.RDWebAccessDNSInternalZone -AllowUpdateAny -IPv4Address $IPWebAccess02
  386.     Write-Verbose "Configured WebAccess DNS-Record"  -Verbose
  387.  
  388.     # Download SQL Native Client
  389.     try {Invoke-WebRequest -Uri "https://download.microsoft.com/download/8/7/2/872BCECA-C849-4B40-8EBE-21D48CDF1456/ENU/x64/sqlncli.msi" -OutFile "c:\rds\sqlncli.msi"} catch {(Read-Host "Last change :-), copy sqlncli.msi to the brokers!. 'Press enter to continue'")}
  390.     if (Test-Path c:\rds\sqlncli.msi) {
  391.         Write-Verbose "Downloaded SQL Native Client" -Verbose
  392.     } Else {
  393.         Write-Warning "Couldnt Download SQL Native Client"
  394.         Stop-Transcript
  395.         break
  396.     } #end Test-Path c:\rds\sqlncli.msi
  397.  
  398.     #Install SQLNativeClient on ConnectionBroker01
  399.     Copy-Item "c:\rds\sqlncli.msi" -Destination "\\$($config.ConnectionBroker01)\c$"
  400.     Invoke-Command -ComputerName $config.ConnectionBroker01 -ArgumentList $config.ConnectionBroker01 -ScriptBlock {
  401.         $ConnectionBroker01 = $args[0]
  402.         $install = Start-Process "msiexec.exe" -ArgumentList "/i C:\sqlncli.msi", "/qn", "IACCEPTSQLNCLILICENSETERMS=YES", "/log C:\sql.log" -PassThru -Wait
  403.  
  404.         if ($install.ExitCode -ne 0) {
  405.             Write-Warning "SQL Client failed to install with $($install.ExitCode) on $ConnectionBroker01"
  406.             Stop-Transcript
  407.             break
  408.         } else {
  409.             Write-Verbose "SQL Client installed succesfull on $ConnectionBroker01" -Verbose
  410.         }
  411.         Remove-Item "C:\sqlncli.msi"
  412.     }
  413.  
  414.     #Install SQLNativeClient on ConnectionBroker02
  415.     Copy-Item "c:\rds\sqlncli.msi" -Destination "\\$($config.ConnectionBroker02)\c$"
  416.     Invoke-Command -ComputerName $config.ConnectionBroker02 -ArgumentList $config.ConnectionBroker02 -ScriptBlock {
  417.         $ConnectionBroker02 = $args[0]
  418.         $install = Start-Process "msiexec.exe" -ArgumentList "/i C:\sqlncli.msi", "/qn", "IACCEPTSQLNCLILICENSETERMS=YES", "/log C:\sql.log" -PassThru -Wait
  419.  
  420.         if ($install.ExitCode -ne 0) {
  421.             Write-Warning "SQL Client failed to install with $($install.ExitCode) on $ConnectionBroker02"
  422.             Stop-Transcript
  423.             break
  424.         } else {
  425.             Write-Verbose "SQL Client installed succesfull on $ConnectionBroker02" -Verbose
  426.         }
  427.         Remove-Item "C:\sqlncli.msi"
  428.     }
  429.  
  430.     #Configure RDSBrokerHighAvailability
  431.  
  432.     Invoke-Command -ComputerName $config.SQLServer -ArgumentList $config.SQLServer, $config.DomainNetbios -ScriptBlock {
  433.         $SQLserver = $args[0]
  434.         $NetBios = $args[1]
  435.  
  436.         [void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO')
  437.         $server = new-Object Microsoft.SqlServer.Management.Smo.Server("$SQLserver")
  438.         $SqlUser = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login ($server,"$NetBios\RDS_Connection_Brokers")
  439.         $SqlUser.LoginType='WindowsUser'
  440.         $SqlUser.create()
  441.  
  442.         $SvrRole = $server.Roles | where {$_.Name -eq 'sysadmin'};
  443.         $SvrRole.AddMember("$NetBios\RDS_Connection_Brokers");
  444.     }
  445.  
  446.     #(Read-Host 'Please give the "RDS_Connection_Brokers" Security Group the right "sysadmin" to create the databases on the SQL Server. Press Enter when finished')
  447.  
  448.     Set-RDConnectionBrokerHighAvailability -ConnectionBroker $config.ConnectionBroker01`
  449.     -DatabaseConnectionString "DRIVER=SQL Server Native Client 11.0;SERVER=$($config.SQLServer);Trusted_Connection=Yes;APP=Remote Desktop Services Connection Broker;DATABASE=$($config.SQLDatabase)"`
  450.     -ClientAccessName "$($config.RDBrokerDNSInternalName).$($config.RDBrokerDNSInternalZone)"
  451.     #parameter DatabaseFilePath not needed.
  452.     #-DatabaseFilePath  $config.SQLFilePath
  453.     Write-Verbose "Configured RDSBroker High Availablilty"  -Verbose
  454.  
  455.    
  456.     #Join ConnectionBroker02
  457.     Invoke-Command -ComputerName $config.ConnectionBroker02 -ScriptBlock {
  458.         <#
  459.         Don't know why, but pre installing the RDS-Connection-Broker role prevents the error: The server BR2.rdsfarm.lab has to be same OS version as the active RD Connection Broker server BR1.rdsfarm.lab: Microsoft Windows Server 2016 Standard.
  460.         #>
  461.         Install-WindowsFeature RDS-Connection-Broker
  462.     }
  463.    
  464.     Add-RDServer -Server $config.ConnectionBroker02 -Role "RDS-CONNECTION-BROKER" -ConnectionBroker $config.ConnectionBroker01
  465.     Write-Verbose "Joined Broker Server: $($config.ConnectionBroker02)"  -Verbose
  466.  
  467.     #Reboot ConnectionBroker02 (without Reboot, there can occur errors with the next commands)
  468.     Write-Verbose "$($config.ConnectionBroker02) will reboot"  -Verbose
  469.     Restart-Computer -ComputerName $config.ConnectionBroker02 -Wait -For PowerShell -Timeout 300 -Delay 2 -Force
  470.     Write-Verbose "$($config.ConnectionBroker02) online again"  -Verbose
  471.  
  472.     read-host "If reboot of $($config.ConnectionBroker02) fails, do it manualy!"
  473.  
  474.     #Determine ActiveBroker
  475.     $primaryBroker = (Get-RDConnectionBrokerHighAvailability -ConnectionBroker $config.ConnectionBroker01).ActiveManagementServer
  476.  
  477.     #Join WebAccess02
  478.     Add-RDServer -Server $config.WebAccessServer02 -Role "RDS-WEB-ACCESS" -ConnectionBroker $primaryBroker
  479.     Write-Verbose "Joined WebAccess Server:  $($config.ConnectionBroker02)"  -Verbose
  480.  
  481.     # WebAccess02 - Redirect to RDWeb (IIS)
  482.     Invoke-Command -ComputerName $config.WebAccessServer02 -ArgumentList $config.RDWebAccessDNSInternalName, $config.RDWebAccessDNSInternalZone  -ScriptBlock {
  483.         $RDWebAccessDNSInternalName = $args[0]
  484.         $RDWebAccessDNSInternalZone = $args[1]
  485.         $siteName = "Default Web Site"
  486.         Import-Module webAdministration
  487.         Set-WebConfiguration system.webServer/httpRedirect "IIS:\sites\$siteName" -Value @{enabled="true";destination="https://$RDWebAccessDNSInternalName.$RDWebAccessDNSInternalZone/RDWeb";exactDestination="true";httpResponseStatus="Found"}
  488.     }
  489.     Write-Verbose "Configured RDWeb Redirect"  -Verbose
  490.  
  491.     # Create same Machine Key for RDWeb Services
  492.     # https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-rdweb-gateway-ha
  493.     # https://gallery.technet.microsoft.com/Get-and-Set-the-machineKeys-9a1e7b77
  494.     Invoke-WebRequest -Uri "https://gallery.technet.microsoft.com/Get-and-Set-the-machineKeys-9a1e7b77/file/122500/1/Configure-MachineKeys.ps1" -OutFile "c:\rds\Configure-MachineKeys.ps1"
  495.     if (Test-Path c:\rds\Configure-MachineKeys.ps1){
  496.         Write-Verbose "Downloaded Configure-MachineKeys Script" -Verbose
  497.         c:\rds\Configure-MachineKeys.ps1 -ComputerName $config.WebAccessServer01, $config.WebAccessServer02 -Mode Write
  498.         Write-Verbose "Configured same Machine Key for RDWeb Servers"
  499.     } Else {
  500.         Write-Warning "Couldnt download Configure-MachineKeys Script"
  501.         Stop-Transcript
  502.         break
  503.     }
  504.  
  505.     #Join RDGatewayServer02
  506.     Add-RDServer -Server $config.RDGatewayServer02 -Role "RDS-GATEWAY" -ConnectionBroker $primaryBroker -GatewayExternalFqdn $config.GatewayExternalFqdn
  507.     Write-Verbose "Joined Gateway Server:  $($config.ConnectionBroker02)"  -Verbose
  508.  
  509.     # Configure GW Policies on RDGatewayServer02
  510.     Invoke-Command -ComputerName $config.RDGatewayServer02 -ArgumentList $config.GatewayAccessGroup, $config.RDBrokerDNSInternalName, $config.RDBrokerDNSInternalZone, $config.RDSHost01, $config.RDSHost02, $config.RDGatewayServer01, $config.RDGatewayServer02 -ScriptBlock {
  511.         $GatewayAccessGroup = $args[0]
  512.         $RDBrokerDNSInternalName = $args[1]
  513.         $RDBrokerDNSInternalZone = $args[2]
  514.         $RDSHost01 = $args[3]
  515.         $RDSHost02 = $args[4]
  516.         $RDGatewayServer01 = $args[5]
  517.         $RDGatewayServer02 = $args[6]
  518.         Import-Module RemoteDesktopServices
  519.         Remove-Item -Path "RDS:\GatewayServer\CAP\RDG_CAP_AllUsers" -Force -recurse
  520.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_RDConnectionBrokers" -Force -recurse
  521.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_AllDomainComputers" -Force -recurse
  522.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_HighAvailabilityBroker_DNS_RR" -Force -recurse
  523.         Remove-Item  -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDG_RDCBComputers"-Force -recurse
  524.         Remove-Item  -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDG_DNSRoundRobin"-Force -recurse
  525.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups" -Name "RDSFarm1" -Description "RDSFarm1" -Computers "$RDBrokerDNSInternalName.$RDBrokerDNSInternalZone" -ItemType "String"
  526.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDSFarm1\Computers" -Name $RDSHost01 -ItemType "String"
  527.         New-Item -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDSFarm1\Computers" -Name $RDSHost02 -ItemType "String"
  528.         New-Item -Path "RDS:\GatewayServer\RAP" -Name "RDG_RAP_RDSFarm1" -UserGroups $GatewayAccessGroup -ComputerGroupType 0 -ComputerGroup "RDSFarm1"
  529.         New-Item -Path "RDS:\GatewayServer\CAP" -Name "RDG_CAP_RDSFarm1" -UserGroups $GatewayAccessGroup -AuthMethod 1
  530.         New-Item -Path "RDS:\GatewayServer\GatewayFarm\Servers" -Name $RDGatewayServer01 -ItemType "String"
  531.         New-Item -Path "RDS:\GatewayServer\GatewayFarm\Servers" -Name $RDGatewayServer02 -ItemType "String"
  532.     } #end invoke GW Policies on RDGatewayServer02
  533.     Write-Verbose "Configured CAP & RAP Policies on: $($config.RDGatewayServer02)"  -Verbose
  534.  
  535.     #Cleanup Gateway Policies on RDGatewayServer01
  536.     Invoke-Command -ComputerName $config.RDGatewayServer01 -ScriptBlock {
  537.         Import-Module RemoteDesktopServices
  538.         Remove-Item -Path "RDS:\GatewayServer\RAP\RDG_HighAvailabilityBroker_DNS_RR" -Force -recurse
  539.         Remove-Item  -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\RDG_DNSRoundRobin"-Force -recurse
  540.     } #ne invoke Cleanup Gateway Policies on RDGatewayServer01
  541.     Write-Verbose "Cleanup RAP Policy on: $($config.RDGatewayServer01)"  -Verbose
  542.  
  543.     #Create Gateway Farm on RDGatewayServer01
  544.     Invoke-Command -ComputerName $config.RDGatewayServer01 -ArgumentList $config.RDGatewayServer01, $config.RDGatewayServer02 -ScriptBlock {
  545.         $RDGatewayServer01 = $args[0]
  546.         $RDGatewayServer02 = $args[1]
  547.         Import-Module RemoteDesktopServices
  548.         New-Item -Path "RDS:\GatewayServer\GatewayFarm\Servers" -Name $RDGatewayServer01 -ItemType "String"
  549.         New-Item -Path "RDS:\GatewayServer\GatewayFarm\Servers" -Name $RDGatewayServer02 -ItemType "String"
  550.     } #end invoke Create Gateway Farm on RDGatewayServer01
  551.     Write-Verbose "Created Gateway Server Farm on: $($config.RDGatewayServer01)"  -Verbose
  552.  
  553.     #Set Certificates (need to be applied again, that ConnectioBroker02 is getting the certificates)
  554.     $Password = ConvertTo-SecureString -String $config.CertPassword -AsPlainText -Force
  555.     Set-RDCertificate -Role RDPublishing -ImportPath $config.CertPath  -Password $Password -ConnectionBroker $primaryBroker -Force
  556.     Set-RDCertificate -Role RDRedirector -ImportPath $config.CertPath -Password $Password -ConnectionBroker $primaryBroker -Force
  557.     Set-RDCertificate -Role RDWebAccess -ImportPath $config.CertPath -Password $Password -ConnectionBroker $primaryBroker -Force
  558.     Set-RDCertificate -Role RDGateway -ImportPath $config.CertPath  -Password $Password -ConnectionBroker $primaryBroker -Force
  559.     Write-Verbose "Configured SSL Certificates"  -Verbose
  560.  
  561. } #end if $config.HADeployment
  562.  
  563.  
  564. Write-Verbose "Stop logging" -Verbose
  565. $EndDate = (Get-Date)
  566. Write-Verbose "Elapsed Time: $(($EndDate-$StartDate).TotalSeconds) Seconds" -Verbose
  567. Write-Verbose "Elapsed Time: $(($EndDate-$StartDate).TotalMinutes) Minutes" -Verbose
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top