diff --git a/examples/scripts/ConfigureRemotingForAnsible.ps1 b/examples/scripts/ConfigureRemotingForAnsible.ps1 index 1cb3375725..39601d2a76 100644 --- a/examples/scripts/ConfigureRemotingForAnsible.ps1 +++ b/examples/scripts/ConfigureRemotingForAnsible.ps1 @@ -1,11 +1,18 @@ -# Script to set a windows computer up for remoting -# The script checks the current WinRM/Remoting configuration and makes the necessary changes -# set $VerbosePreference="Continue" before running the script in order to see the output of the script +# Configure a Windows host for remote management with Ansible +# ----------------------------------------------------------- +# +# This script checks the current WinRM/PSRemoting configuration and makes the +# necessary changes to allow Ansible to connect, authenticate and execute +# PowerShell commands. +# +# Set $VerbosePreference = "Continue" before running the script in order to +# see the output messages. # # Written by Trond Hindenes +# Updated by Chris Church # # Version 1.0 - July 6th, 2014 - +# Version 1.1 - November 11th, 2014 Param ( [string]$SubjectName = $env:COMPUTERNAME, @@ -14,7 +21,6 @@ Param ( ) -#region function defs Function New-LegacySelfSignedCert { Param ( @@ -22,10 +28,10 @@ Function New-LegacySelfSignedCert [int]$ValidDays = 365 ) - $name = new-object -com "X509Enrollment.CX500DistinguishedName.1" + $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" $name.Encode("CN=$SubjectName", 0) - $key = new-object -com "X509Enrollment.CX509PrivateKey.1" + $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider" $key.KeySpec = 1 $key.Length = 1024 @@ -33,149 +39,166 @@ Function New-LegacySelfSignedCert $key.MachineContext = 1 $key.Create() - $serverauthoid = new-object -com "X509Enrollment.CObjectId.1" + $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") - $ekuoids = new-object -com "X509Enrollment.CObjectIds.1" - $ekuoids.add($serverauthoid) - $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" + $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" + $ekuoids.Add($serverauthoid) + $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" $ekuext.InitializeEncode($ekuoids) - $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1" + $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" $cert.InitializeFromPrivateKey(2, $key, "") $cert.Subject = $name $cert.Issuer = $cert.Subject - $cert.NotBefore = (get-date).addDays(-1) + $cert.NotBefore = (Get-Date).AddDays(-1) $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) $cert.X509Extensions.Add($ekuext) $cert.Encode() - $enrollment = new-object -com "X509Enrollment.CX509Enrollment.1" + $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" $enrollment.InitializeFromRequest($cert) $certdata = $enrollment.CreateRequest(0) $enrollment.InstallResponse(2, $certdata, 0, "") - #return the thumprint of the last installed cert - ls "Cert:\LocalMachine\my"| Sort-Object notbefore -Descending | select -First 1 | select -expand Thumbprint + # Return the thumbprint of the last installed cert. + Get-ChildItem "Cert:\LocalMachine\my"| Sort-Object NotBefore -Descending | Select -First 1 | Select -Expand Thumbprint } -#endregion -#Start script +# Setup error handling. +Trap +{ + $_ + Exit 1 +} $ErrorActionPreference = "Stop" -#Detect PowerShell version -if ($PSVersionTable.PSVersion.Major -lt 3) + +# Detect PowerShell version. +If ($PSVersionTable.PSVersion.Major -lt 3) { - Write-Error "PowerShell/Windows Management Framework needs to be updated to 3 or higher. Stopping script" + Throw "PowerShell version 3 or higher is required." } -#Detect OS - $Win32_OS = Get-WmiObject Win32_OperatingSystem - switch ($Win32_OS.Version) - { - "6.2.9200" {$OSVersion = "Windows Server 2012"} - "6.1.7601" {$OSVersion = "Windows Server 2008R2"} - } - - - #Set up remoting - Write-verbose "Verifying WS-MAN" - if (!(get-service "WinRM")) - { - Write-Error "I couldnt find the winRM service on this computer. Stopping" - } - Elseif ((get-service "WinRM").Status -ne "Running") - { - Write-Verbose "Starting WinRM" +# Find and start the WinRM service. +Write-Verbose "Verifying WinRM service." +If (!(Get-Service "WinRM")) +{ + Throw "Unable to find the WinRM service." +} +ElseIf ((Get-Service "WinRM").Status -ne "Running") +{ + Write-Verbose "Starting WinRM service." Start-Service -Name "WinRM" -ErrorAction Stop - } +} - #At this point, winrm should be running - #Check that we have a ps session config - if (!(Get-PSSessionConfiguration -verbose:$false) -or (!(get-childitem WSMan:\localhost\Listener))) - { - Write-Verbose "PS remoting is not enabled. Activating" - try + +# WinRM should be running; check that we have a PS session config. +If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener))) +{ + Write-Verbose "Enabling PS Remoting." + Try { Enable-PSRemoting -Force -ErrorAction SilentlyContinue - } - catch{} - } - Else - { - Write-Verbose "PS remoting is already active and running" - } - - #At this point, test a remoting connection to localhost, which should work - $result = invoke-command -ComputerName localhost -ScriptBlock {$env:computername} -ErrorVariable localremotingerror -ErrorAction SilentlyContinue - - $options = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck - $resultssl = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $options -ErrorVariable localremotingsslerror -ErrorAction SilentlyContinue - - - if (!$result -and $resultssl) - { - Write-Verbose "HTTP-based sessions not enabled, HTTPS based sessions enabled" - } - ElseIf (!$result -and !$resultssl) - { - Write-error "Could not establish session on either HTTP or HTTPS. Breaking" - } - - - #at this point, make sure there is a SSL-based listener - $listeners = dir WSMan:\localhost\Listener - - if (!($listeners | where {$_.Keys -like "TRANSPORT=HTTPS"})) - { - #HTTPS-based endpoint does not exist. - if (($CreateSelfSignedCert) -and ($OSVersion -notmatch "2012")) - { - $thumprint = New-LegacySelfSignedCert -SubjectName $env:COMPUTERNAME } - if (($CreateSelfSignedCert) -and ($OSVersion -match "2012")) + Catch + { + } +} +Else +{ + Write-Verbose "PS Remoting is already enabled." +} + + +# Test a remoting connection to localhost, which should work. +$httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue +$httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck + +$httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue + +If ($httpResult -and $httpsResult) +{ + Write-Verbose "HTTP and HTTPS sessions are enabled." +} +ElseIf ($httpsResult -and !$httpResult) +{ + Write-Verbose "HTTP sessions are disabled, HTTPS session are enabled." +} +ElseIf ($httpResult -and !$httpsResult) +{ + Write-Verbose "HTTPS sessions are disabled, HTTP session are enabled." +} +Else +{ + Throw "Unable to establish an HTTP or HTTPS remoting session." +} + + +# Make sure there is a SSL listener. +$listeners = Get-ChildItem WSMan:\localhost\Listener +If (!($listeners | Where {$_.Keys -like "TRANSPORT=HTTPS"})) +{ + # HTTPS-based endpoint does not exist. + If (Get-Command "New-SelfSignedCertificate" -ErrorAction SilentlyContinue) { $cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\My" - $thumprint = $cert.Thumbprint + $thumbprint = $cert.Thumbprint } - - - + Else + { + $thumbprint = New-LegacySelfSignedCert -SubjectName $env:COMPUTERNAME + } + # Create the hashtables of settings to be used. $valueset = @{} - $valueset.add('Hostname',$env:COMPUTERNAME) - $valueset.add('CertificateThumbprint',$thumprint) + $valueset.Add('Hostname', $env:COMPUTERNAME) + $valueset.Add('CertificateThumbprint', $thumbprint) $selectorset = @{} - $selectorset.add('Transport','HTTPS') - $selectorset.add('Address','*') + $selectorset.Add('Transport', 'HTTPS') + $selectorset.Add('Address', '*') - Write-Verbose "Enabling SSL-based remoting" - New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset - } - Else - { - Write-Verbose "SSL-based remoting already active" - } + Write-Verbose "Enabling SSL listener." + New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset +} +Else +{ + Write-Verbose "SSL listener is already active." +} - #Check for basic authentication - $basicauthsetting = Get-ChildItem WSMan:\localhost\Service\Auth | where {$_.Name -eq "Basic"} - - if (($basicauthsetting.Value) -eq $false) - { - Write-Verbose "Enabling basic auth" +# Check for basic authentication. +$basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where {$_.Name -eq "Basic"} +If (($basicAuthSetting.Value) -eq $false) +{ + Write-Verbose "Enabling basic auth support." Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true - } - Else - { - Write-verbose "basic auth already enabled" - } - -#FIrewall -netsh advfirewall firewall add rule Profile=public name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow +} +Else +{ + Write-Verbose "Basic auth is already enabled." +} +# Configure firewall to allow WinRM HTTPS connections. +$fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" +$fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any +If ($fwtest1.count -lt 5) +{ + Write-Verbose "Adding firewall rule to allow WinRM HTTPS." + netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow +} +ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5)) +{ + Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile." + netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any +} +Else +{ + Write-Verbose "Firewall rule already exists to allow WinRM HTTPS." +} - Write-Verbose "PS Remoting successfully setup for Ansible" + +Write-Verbose "PS Remoting has been successfully configured for Ansible."