Artifacts/windows-winrm/config-winrm.ps1 (150 lines of code) (raw):

[CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $HostName ) ################################################################################################### # # PowerShell configurations # # NOTE: Because the $ErrorActionPreference is "Stop", this script will stop on first failure. # This is necessary to ensure we capture errors inside the try-catch-finally block. $ErrorActionPreference = "Stop" # Ensure we set the working directory to that of the script. Push-Location $PSScriptRoot ################################################################################################### # # Handle all errors in this script. # trap { # NOTE: This trap will handle all errors. There should be no need to use a catch below in this # script, unless you want to ignore a specific error. $message = $error[0].Exception.Message if ($message) { Write-Host -Object "ERROR: $message" -ForegroundColor Red } # IMPORTANT NOTE: Throwing a terminating error (using $ErrorActionPreference = "Stop") still # returns exit code zero from the PowerShell script when using -File. The workaround is to # NOT use -File when calling this script and leverage the try-catch-finally block and return # a non-zero exit code from the catch block. exit -1 } ################################################################################################### # # Functions used in this script. # function Handle-LastExitCode { [CmdletBinding()] param( ) if ($LASTEXITCODE -ne 0) { throw 'The artifact failed to apply.' } } function New-Certificate { [CmdletBinding()] param( [string] $HostName ) # makecert ocassionally produces negative serial numbers, which golang tls/crypto < 1.6.1 cannot handle. # https://github.com/golang/go/issues/8265 $serial = Get-Random .\makecert -r -pe -n CN=$HostName -b 01/01/2022 -e 01/01/2032 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -# $serial 2>&1 | Out-Null $thumbprint=(Get-ChildItem cert:\Localmachine\my | Where-Object { $_.Subject -eq "CN=" + $HostName } | Select-Object -Last 1).Thumbprint if(-not $thumbprint) { throw 'Failed to create the test certificate.' } return $thumbprint } function Remove-WinRMListener { [CmdletBinding()] param( ) try { $config = Winrm enumerate winrm/config/listener foreach($conf in $config) { if($conf.Contains('HTTPS')) { Write-Output 'HTTPS is already configured. Deleting the exisiting configuration.' winrm delete winrm/config/Listener?Address=*+Transport=HTTPS 2>&1 | Out-Null break } } } catch { Write-Output "INFO: Exception while deleting the listener: $($_.Exception.Message)" } } function Set-WinRMListener { [CmdletBinding()] param( [string] $HostName) # Delete the WinRM Https listener, if it is already configured. Remove-WinRMListener # Create a test certificate. $cert = (Get-ChildItem cert:\LocalMachine\My | Where-Object { $_.Subject -eq "CN=" + $HostName } | Select-Object -Last 1) $thumbprint = $cert.Thumbprint if(-not $thumbprint) { $thumbprint = New-Certificate -HostName $HostName } elseif (-not $cert.PrivateKey) { # The private key is missing - could have been sysprepped. Delete the certificate. Remove-Item Cert:\LocalMachine\My\$thumbprint -Force | Out-Null $thumbprint = New-Certificate -HostName $HostName } $WinrmCreate = "winrm create --% winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=`"$HostName`";CertificateThumbprint=`"$thumbPrint`"}" invoke-expression $WinrmCreate Handle-LastExitCode winrm set winrm/config/service/auth '@{Basic="true"}' Handle-LastExitCode } function Add-FirewallException { [CmdletBinding()] param( [string] $Port ) $ruleName = "Windows Remote Management (HTTPS-In)" # Determine if the rule already exists. netsh advfirewall firewall show rule name=$ruleName | Out-Null if ($LastExitCode -eq 0) { # Delete the existing rule. netsh advfirewall firewall delete rule name=$ruleName dir=in protocol=TCP localport=$Port | Out-Null Handle-LastExitCode } # Add a new firewall rule. netsh advfirewall firewall add rule name=$ruleName dir=in action=allow protocol=TCP localport=$Port | Out-Null Handle-LastExitCode } try { Write-Output 'Add firewall exception for port 5986.' Add-FirewallException -Port 5986 # Ensure that the service is running and is accepting requests. winrm quickconfig -force # The default MaxEnvelopeSizekb on Windows Server is 500 Kb which is very less. It needs to be at 8192 Kb. # The small envelop size, if not changed, results in the WS-Management service responding with an error that # the request size exceeded the configured MaxEnvelopeSize quota. Write-Output 'Configuring MaxEnvelopeSize to 8192 kb.' winrm set winrm/config '@{MaxEnvelopeSizekb = "8192"}' Write-Output 'Configuring WinRM listener.' Set-WinRMListener -HostName $HostName Write-Output 'Artifact completed successfully.' } finally { Pop-Location }