From d568966e2c9c879c8a9b699ec2f2c9b3358423f2 Mon Sep 17 00:00:00 2001 From: Trond Hindenes Date: Sun, 6 Jul 2014 19:02:32 +0200 Subject: [PATCH 1/3] Added script for configuring winrm for Ansible The script can be used to set up a windows host with WinRM with the least possible effort. --- .../scripts/ConfigureRemotingForAnsible.ps1 | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 examples/scripts/ConfigureRemotingForAnsible.ps1 diff --git a/examples/scripts/ConfigureRemotingForAnsible.ps1 b/examples/scripts/ConfigureRemotingForAnsible.ps1 new file mode 100644 index 0000000000..1cb3375725 --- /dev/null +++ b/examples/scripts/ConfigureRemotingForAnsible.ps1 @@ -0,0 +1,181 @@ +# 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 +# +# Written by Trond Hindenes +# +# Version 1.0 - July 6th, 2014 + + +Param ( + [string]$SubjectName = $env:COMPUTERNAME, + [int]$CertValidityDays = 365, + $CreateSelfSignedCert = $true +) + + +#region function defs +Function New-LegacySelfSignedCert +{ + Param ( + [string]$SubjectName, + [int]$ValidDays = 365 + ) + + $name = new-object -com "X509Enrollment.CX500DistinguishedName.1" + $name.Encode("CN=$SubjectName", 0) + + $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.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" + $ekuext.InitializeEncode($ekuoids) + + $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.NotAfter = $cert.NotBefore.AddDays($ValidDays) + $cert.X509Extensions.Add($ekuext) + $cert.Encode() + + $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 +} + +#endregion + +#Start script +$ErrorActionPreference = "Stop" + +#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" +} + +#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" + 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 + { + 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")) + { + $cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\My" + $thumprint = $cert.Thumbprint + } + + + + # Create the hashtables of settings to be used. + $valueset = @{} + $valueset.add('Hostname',$env:COMPUTERNAME) + $valueset.add('CertificateThumbprint',$thumprint) + + $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" + } + + + #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" + 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 + + + + Write-Verbose "PS Remoting successfully setup for Ansible" From 7eac2121a54b8859aecbd5af37ef3adcec4d5da7 Mon Sep 17 00:00:00 2001 From: Trond Hindenes Date: Sun, 6 Jul 2014 22:34:37 +0200 Subject: [PATCH 2/3] improved msi --- library/windows/win_msi | 12 +++++- library/windows/win_msi.ps1 | 73 ++++++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/library/windows/win_msi b/library/windows/win_msi index 9eb6f1bafa..12da6e1422 100644 --- a/library/windows/win_msi +++ b/library/windows/win_msi @@ -45,7 +45,15 @@ options: description: - Path to a file created by installing the MSI to prevent from attempting to reinstall the package on every run -author: Matt Martz + msiname: + description: + - alternative way to check for the existence of an msi (can be used for both states (absent and present). + The msiname can be found by looking at name property of the the win32_product object for the item. + msiversionstring + description: + - used in conjunction with msiname - you cannot specify msiversionstring only. + The msiversionstring can be found by looking at version property of the the win32_product object for the item. +author: Matt Martz / Trond Hindenes ''' EXAMPLES = ''' @@ -54,5 +62,7 @@ EXAMPLES = ''' # Uninstall an MSI file - win_msi: path=C:\\\\7z920-x64.msi state=absent + +- win_msi: path=C:\\\\7z920-x64.msi msiname="myproduct" msiversionstring="3.2.0" ''' diff --git a/library/windows/win_msi.ps1 b/library/windows/win_msi.ps1 index 1c2bc8a301..6f27e0eea3 100644 --- a/library/windows/win_msi.ps1 +++ b/library/windows/win_msi.ps1 @@ -24,34 +24,89 @@ $params = Parse-Args $args; $result = New-Object psobject; Set-Attr $result "changed" $false; -If (-not $params.path.GetType) +If (!($params.path)) { Fail-Json $result "missing required arguments: path" } -$extra_args = "" -If ($params.extra_args.GetType) +if (!(test-path $params.path)) +{ + Fail-Json $result "couldn't find a file at $($params.path)" +} + + +If ($params.extra_args) { $extra_args = $params.extra_args; } - -If ($params.creates.GetType -and $params.state.GetType -and $params.state -ne "absent") +Else { - If (Test-File $creates) + $extra_args = "" +} + +if ($params.MsiVersionString) +{ + $MsiVersionString = $params.MsiVersionString +} + +if ($params.MsiName) +{ + $MsiName = $params.MsiName +} + +if (($MsiVersionString) -and (!($MsiName))) +{ + #If msiversionstring is specified, we need msiname as well + Fail-Json $result "missing required arguments: MsiName" +} + + +If (($params.creates) -and ($params.state -ne "absent")) +{ + If (Test-Path ($params.creates)) { Exit-Json $result; } } -$logfile = [IO.Path]::GetTempFileName(); -if ($params.state.GetType -and $params.state -eq "absent") +if ($MsiName) { - msiexec.exe /x $params.path /qb /l $logfile $extra_args; + $AlreadyInstalledMsi = Get-WmiObject -Query "Select * from win32_product" | where {$_.Name -eq $MsiName} +} +ElseIf (($MsiName) -and ($MsiVersionString)) +{ + $AlreadyInstalledMsi = Get-WmiObject -Query "Select * from win32_product" | where {($_.Name -eq $MsiName) -and ($_.version -eq $MsiVersionString)} } Else { + if ($params.state -eq "absent") + { + #existing msi check not specify, assume msi does exist + $AlreadyInstalledMsi = $true + } + if ($params.state -eq "present") + { + #existing msi check not specify, assume msi does exist + $AlreadyInstalledMsi = $false + } +} + +if (($AlreadyInstalledMsi) -and ($params.state -eq "absent")) +{ + #Already installed, perform uninstall + msiexec.exe /x $params.path /qb /l $logfile $extra_args; +} +Elseif((!$AlreadyInstalledMsi) -and ($params.state -eq "present")) +{ + #Not already installed, perform the install + $logfile = [IO.Path]::GetTempFileName(); msiexec.exe /i $params.path /qb /l $logfile $extra_args; } +Else +{ + #Do nothing + Exit-Json $result; +} Set-Attr $result "changed" $true; From f0dcc36e6d9b322b7a54c2c324503ee268a016c0 Mon Sep 17 00:00:00 2001 From: Trond Hindenes Date: Sun, 6 Jul 2014 22:36:01 +0200 Subject: [PATCH 3/3] Revert "improved msi" This reverts commit 7eac2121a54b8859aecbd5af37ef3adcec4d5da7. --- library/windows/win_msi | 12 +------ library/windows/win_msi.ps1 | 71 +++++-------------------------------- 2 files changed, 9 insertions(+), 74 deletions(-) diff --git a/library/windows/win_msi b/library/windows/win_msi index 12da6e1422..9eb6f1bafa 100644 --- a/library/windows/win_msi +++ b/library/windows/win_msi @@ -45,15 +45,7 @@ options: description: - Path to a file created by installing the MSI to prevent from attempting to reinstall the package on every run - msiname: - description: - - alternative way to check for the existence of an msi (can be used for both states (absent and present). - The msiname can be found by looking at name property of the the win32_product object for the item. - msiversionstring - description: - - used in conjunction with msiname - you cannot specify msiversionstring only. - The msiversionstring can be found by looking at version property of the the win32_product object for the item. -author: Matt Martz / Trond Hindenes +author: Matt Martz ''' EXAMPLES = ''' @@ -62,7 +54,5 @@ EXAMPLES = ''' # Uninstall an MSI file - win_msi: path=C:\\\\7z920-x64.msi state=absent - -- win_msi: path=C:\\\\7z920-x64.msi msiname="myproduct" msiversionstring="3.2.0" ''' diff --git a/library/windows/win_msi.ps1 b/library/windows/win_msi.ps1 index 6f27e0eea3..1c2bc8a301 100644 --- a/library/windows/win_msi.ps1 +++ b/library/windows/win_msi.ps1 @@ -24,88 +24,33 @@ $params = Parse-Args $args; $result = New-Object psobject; Set-Attr $result "changed" $false; -If (!($params.path)) +If (-not $params.path.GetType) { Fail-Json $result "missing required arguments: path" } -if (!(test-path $params.path)) -{ - Fail-Json $result "couldn't find a file at $($params.path)" -} - - -If ($params.extra_args) +$extra_args = "" +If ($params.extra_args.GetType) { $extra_args = $params.extra_args; } -Else -{ - $extra_args = "" -} -if ($params.MsiVersionString) +If ($params.creates.GetType -and $params.state.GetType -and $params.state -ne "absent") { - $MsiVersionString = $params.MsiVersionString -} - -if ($params.MsiName) -{ - $MsiName = $params.MsiName -} - -if (($MsiVersionString) -and (!($MsiName))) -{ - #If msiversionstring is specified, we need msiname as well - Fail-Json $result "missing required arguments: MsiName" -} - - -If (($params.creates) -and ($params.state -ne "absent")) -{ - If (Test-Path ($params.creates)) + If (Test-File $creates) { Exit-Json $result; } } -if ($MsiName) +$logfile = [IO.Path]::GetTempFileName(); +if ($params.state.GetType -and $params.state -eq "absent") { - $AlreadyInstalledMsi = Get-WmiObject -Query "Select * from win32_product" | where {$_.Name -eq $MsiName} -} -ElseIf (($MsiName) -and ($MsiVersionString)) -{ - $AlreadyInstalledMsi = Get-WmiObject -Query "Select * from win32_product" | where {($_.Name -eq $MsiName) -and ($_.version -eq $MsiVersionString)} -} -Else -{ - if ($params.state -eq "absent") - { - #existing msi check not specify, assume msi does exist - $AlreadyInstalledMsi = $true - } - if ($params.state -eq "present") - { - #existing msi check not specify, assume msi does exist - $AlreadyInstalledMsi = $false - } -} - -if (($AlreadyInstalledMsi) -and ($params.state -eq "absent")) -{ - #Already installed, perform uninstall msiexec.exe /x $params.path /qb /l $logfile $extra_args; } -Elseif((!$AlreadyInstalledMsi) -and ($params.state -eq "present")) -{ - #Not already installed, perform the install - $logfile = [IO.Path]::GetTempFileName(); - msiexec.exe /i $params.path /qb /l $logfile $extra_args; -} Else { - #Do nothing - Exit-Json $result; + msiexec.exe /i $params.path /qb /l $logfile $extra_args; } Set-Attr $result "changed" $true;