ConfigureRM
1 #Requires -Version 3.0 2 3 # Configure a Windows host for remote management with Ansible 4 # ----------------------------------------------------------- 5 # 6 # This script checks the current WinRM (PS Remoting) configuration and makes 7 # the necessary changes to allow Ansible to connect, authenticate and 8 # execute PowerShell commands. 9 # 10 # All events are logged to the Windows EventLog, useful for unattended runs. 11 # 12 # Use option -Verbose in order to see the verbose output messages. 13 # 14 # Use option -CertValidityDays to specify how long this certificate is valid 15 # starting from today. So you would specify -CertValidityDays 3650 to get 16 # a 10-year valid certificate. 17 # 18 # Use option -ForceNewSSLCert if the system has been SysPreped and a new 19 # SSL Certificate must be forced on the WinRM Listener when re-running this 20 # script. This is necessary when a new SID and CN name is created. 21 # 22 # Use option -EnableCredSSP to enable CredSSP as an authentication option. 23 # 24 # Use option -SkipNetworkProfileCheck to skip the network profile check. 25 # Without specifying this the script will only run if the device's interfaces 26 # are in DOMAIN or PRIVATE zones. Provide this switch if you want to enable 27 # WinRM on a device with an interface in PUBLIC zone. 28 # 29 # Use option -SubjectName to specify the CN name of the certificate. This 30 # defaults to the system's hostname and generally should not be specified. 31 32 # Written by Trond Hindenes <trond@hindenes.com> 33 # Updated by Chris Church <cchurch@ansible.com> 34 # Updated by Michael Crilly <mike@autologic.cm> 35 # Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com> 36 # Updated by Nicolas Simond <contact@nicolas-simond.com> 37 # Updated by Dag Wie?rs <dag@wieers.com> 38 # Updated by Jordan Borean <jborean93@gmail.com> 39 # 40 # Version 1.0 - 2014-07-06 41 # Version 1.1 - 2014-11-11 42 # Version 1.2 - 2015-05-15 43 # Version 1.3 - 2016-04-04 44 # Version 1.4 - 2017-01-05 45 # Version 1.5 - 2017-02-09 46 # Version 1.6 - 2017-04-18 47 48 # Support -Verbose option 49 [CmdletBinding()] 50 51 Param ( 52 [string]$SubjectName = $env:COMPUTERNAME, 53 [int]$CertValidityDays = 1095, 54 [switch]$SkipNetworkProfileCheck, 55 $CreateSelfSignedCert = $true, 56 [switch]$ForceNewSSLCert, 57 [switch]$EnableCredSSP 58 ) 59 60 Function Write-Log 61 { 62 $Message = $args[0] 63 Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message 64 } 65 66 Function Write-VerboseLog 67 { 68 $Message = $args[0] 69 Write-Verbose $Message 70 Write-Log $Message 71 } 72 73 Function Write-HostLog 74 { 75 $Message = $args[0] 76 Write-Host $Message 77 Write-Log $Message 78 } 79 80 Function New-LegacySelfSignedCert 81 { 82 Param ( 83 [string]$SubjectName, 84 [int]$ValidDays = 1095 85 ) 86 87 $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" 88 $name.Encode("CN=$SubjectName", 0) 89 90 $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" 91 $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider" 92 $key.KeySpec = 1 93 $key.Length = 4096 94 $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" 95 $key.MachineContext = 1 96 $key.Create() 97 98 $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" 99 $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") 100 $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" 101 $ekuoids.Add($serverauthoid) 102 $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" 103 $ekuext.InitializeEncode($ekuoids) 104 105 $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" 106 $cert.InitializeFromPrivateKey(2, $key, "") 107 $cert.Subject = $name 108 $cert.Issuer = $cert.Subject 109 $cert.NotBefore = (Get-Date).AddDays(-1) 110 $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) 111 $cert.X509Extensions.Add($ekuext) 112 $cert.Encode() 113 114 $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" 115 $enrollment.InitializeFromRequest($cert) 116 $certdata = $enrollment.CreateRequest(0) 117 $enrollment.InstallResponse(2, $certdata, 0, "") 118 119 # extract/return the thumbprint from the generated cert 120 $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 121 $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata)) 122 123 return $parsed_cert.Thumbprint 124 } 125 126 # Setup error handling. 127 Trap 128 { 129 $_ 130 Exit 1 131 } 132 $ErrorActionPreference = "Stop" 133 134 # Get the ID and security principal of the current user account 135 $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() 136 $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) 137 138 # Get the security principal for the Administrator role 139 $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator 140 141 # Check to see if we are currently running "as Administrator" 142 if (-Not $myWindowsPrincipal.IsInRole($adminRole)) 143 { 144 Write-Host "ERROR: You need elevated Administrator privileges in order to run this script." 145 Write-Host " Start Windows PowerShell by using the Run as Administrator option." 146 Exit 2 147 } 148 149 $EventSource = $MyInvocation.MyCommand.Name 150 If (-Not $EventSource) 151 { 152 $EventSource = "Powershell CLI" 153 } 154 155 If ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False) 156 { 157 New-EventLog -LogName Application -Source $EventSource 158 } 159 160 # Detect PowerShell version. 161 If ($PSVersionTable.PSVersion.Major -lt 3) 162 { 163 Write-Log "PowerShell version 3 or higher is required." 164 Throw "PowerShell version 3 or higher is required." 165 } 166 167 # Find and start the WinRM service. 168 Write-Verbose "Verifying WinRM service." 169 If (!(Get-Service "WinRM")) 170 { 171 Write-Log "Unable to find the WinRM service." 172 Throw "Unable to find the WinRM service." 173 } 174 ElseIf ((Get-Service "WinRM").Status -ne "Running") 175 { 176 Write-Verbose "Setting WinRM service to start automatically on boot." 177 Set-Service -Name "WinRM" -StartupType Automatic 178 Write-Log "Set WinRM service to start automatically on boot." 179 Write-Verbose "Starting WinRM service." 180 Start-Service -Name "WinRM" -ErrorAction Stop 181 Write-Log "Started WinRM service." 182 183 } 184 185 # WinRM should be running; check that we have a PS session config. 186 If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener))) 187 { 188 If ($SkipNetworkProfileCheck) { 189 Write-Verbose "Enabling PS Remoting without checking Network profile." 190 Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop 191 Write-Log "Enabled PS Remoting without checking Network profile." 192 } 193 Else { 194 Write-Verbose "Enabling PS Remoting." 195 Enable-PSRemoting -Force -ErrorAction Stop 196 Write-Log "Enabled PS Remoting." 197 } 198 } 199 Else 200 { 201 Write-Verbose "PS Remoting is already enabled." 202 } 203 204 # Make sure there is a SSL listener. 205 $listeners = Get-ChildItem WSMan:\localhost\Listener 206 If (!($listeners | Where {$_.Keys -like "TRANSPORT=HTTPS"})) 207 { 208 # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 209 $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 210 Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 211 212 # Create the hashtables of settings to be used. 213 $valueset = @{ 214 Hostname = $SubjectName 215 CertificateThumbprint = $thumbprint 216 } 217 218 $selectorset = @{ 219 Transport = "HTTPS" 220 Address = "*" 221 } 222 223 Write-Verbose "Enabling SSL listener." 224 New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 225 Write-Log "Enabled SSL listener." 226 } 227 Else 228 { 229 Write-Verbose "SSL listener is already active." 230 231 # Force a new SSL cert on Listener if the $ForceNewSSLCert 232 If ($ForceNewSSLCert) 233 { 234 235 # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 236 $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 237 Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 238 239 $valueset = @{ 240 CertificateThumbprint = $thumbprint 241 Hostname = $SubjectName 242 } 243 244 # Delete the listener for SSL 245 $selectorset = @{ 246 Address = "*" 247 Transport = "HTTPS" 248 } 249 Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset 250 251 # Add new Listener with new SSL cert 252 New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 253 } 254 } 255 256 # Check for basic authentication. 257 $basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where {$_.Name -eq "Basic"} 258 If (($basicAuthSetting.Value) -eq $false) 259 { 260 Write-Verbose "Enabling basic auth support." 261 Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true 262 Write-Log "Enabled basic auth support." 263 } 264 Else 265 { 266 Write-Verbose "Basic auth is already enabled." 267 } 268 269 # If EnableCredSSP if set to true 270 If ($EnableCredSSP) 271 { 272 # Check for CredSSP authentication 273 $credsspAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where {$_.Name -eq "CredSSP"} 274 If (($credsspAuthSetting.Value) -eq $false) 275 { 276 Write-Verbose "Enabling CredSSP auth support." 277 Enable-WSManCredSSP -role server -Force 278 Write-Log "Enabled CredSSP auth support." 279 } 280 } 281 282 # Configure firewall to allow WinRM HTTPS connections. 283 $fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" 284 $fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any 285 If ($fwtest1.count -lt 5) 286 { 287 Write-Verbose "Adding firewall rule to allow WinRM HTTPS." 288 netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow 289 Write-Log "Added firewall rule to allow WinRM HTTPS." 290 } 291 ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5)) 292 { 293 Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile." 294 netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any 295 Write-Log "Updated firewall rule to allow WinRM HTTPS for any profile." 296 } 297 Else 298 { 299 Write-Verbose "Firewall rule already exists to allow WinRM HTTPS." 300 } 301 302 # Test a remoting connection to localhost, which should work. 303 $httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue 304 $httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck 305 306 $httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue 307 308 If ($httpResult -and $httpsResult) 309 { 310 Write-Verbose "HTTP: Enabled | HTTPS: Enabled" 311 } 312 ElseIf ($httpsResult -and !$httpResult) 313 { 314 Write-Verbose "HTTP: Disabled | HTTPS: Enabled" 315 } 316 ElseIf ($httpResult -and !$httpsResult) 317 { 318 Write-Verbose "HTTP: Enabled | HTTPS: Disabled" 319 } 320 Else 321 { 322 Write-Log "Unable to establish an HTTP or HTTPS remoting session." 323 Throw "Unable to establish an HTTP or HTTPS remoting session." 324 } 325 Write-VerboseLog "PS Remoting has been successfully configured for Ansible."
如果前方无人等候,那就像风一样自由

浙公网安备 33010602011771号