forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ansible#9537 from cchurch/update_remoting_config
Updates to ConfigureRemotingForAnsible.ps1
- Loading branch information
Showing
1 changed file
with
133 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <[email protected]> | ||
# Updated by Chris Church <[email protected]> | ||
# | ||
# Version 1.0 - July 6th, 2014 | ||
|
||
# Version 1.1 - November 11th, 2014 | ||
|
||
Param ( | ||
[string]$SubjectName = $env:COMPUTERNAME, | ||
|
@@ -14,168 +21,184 @@ Param ( | |
) | ||
|
||
|
||
#region function defs | ||
Function New-LegacySelfSignedCert | ||
{ | ||
Param ( | ||
[string]$SubjectName, | ||
[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 | ||
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" | ||
$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"} | ||
} | ||
# 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 | ||
} | ||
|
||
|
||
#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" | ||
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")) | ||
} | ||
Catch | ||
{ | ||
$thumprint = New-LegacySelfSignedCert -SubjectName $env:COMPUTERNAME | ||
} | ||
if (($CreateSelfSignedCert) -and ($OSVersion -match "2012")) | ||
} | ||
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','*') | ||
|
||
Write-Verbose "Enabling SSL-based remoting" | ||
New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset | ||
} | ||
Else | ||
{ | ||
Write-Verbose "SSL-based remoting already active" | ||
} | ||
$selectorset.Add('Transport', 'HTTPS') | ||
$selectorset.Add('Address', '*') | ||
|
||
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." |