forked from puppetlabs/bolt
-
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.
(puppetlabsGH-1535) Use container infrastructure for WinRM testing
This modifies the infrastructure used to test WinRM connections to test against a running container as opposed to connecting back to the virtual machine itself. This changes how we provision the Github Actions environment, now using docker-compose to bring up two Windows server 2019 containers - one with the Puppet Agent ruby taking precedence, and one with Windows ruby taking precedence. The containers have the same username and password as Linux container infrastructure, and connect over winrm without SSL. WinRM has 5 authentication methods by default, with the default non-SSL authentication method being 'negotiate'. Negotiate determine whether to use Kerberos or NTLM for authentication, preferring Kerberos. Previous Bolt testing setups seem to have fallen back to using NTLM, or otherwise been configured to allow user-password authentication (possibly through Group Policies). However the default for the Windows Server 2019 container is to attempt Kerberos, which fails. As such the WinRM connection must specify the `basic` auth method in order to use user-pasword authentication between the the GH Action environment and the containers. This is possible using the WinRM ruby gem, but not something we want to expose to users. As such we specify the appropriate settings when connecting to WinRM, wrapped in an environment variable set when testing Bolt in CI.
- Loading branch information
Showing
10 changed files
with
97 additions
and
165 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
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
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,158 +1,18 @@ | ||
$InformationPreference = 'Continue' | ||
$ErrorActionPreference = 'Stop' | ||
|
||
function Set-CACert | ||
{ | ||
$uri = 'https://curl.haxx.se/ca/cacert.pem' | ||
$CACertFile = Join-Path -Path $ENV:AppData -ChildPath 'RubyCACert.pem' | ||
# Remove the current NAT network and pre-create the network for docker-compose | ||
Write-Output "Removing current NAT network..." | ||
Remove-NetNat -Confirm:$false | ||
|
||
$retryArgs = @{ | ||
SuccessMessage = "Succeeded in downloading CA bundle from $uri" | ||
FailMessage = "Failed to download CA bundle from $uri" | ||
Retries = 5 | ||
Timeout = 1 | ||
Script = { | ||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | ||
Invoke-WebRequest -Uri $uri -UseBasicParsing -OutFile $CACertFile | Out-Null | ||
} | ||
} | ||
# Create the new network | ||
Write-Output "Creating spec_default docker network..." | ||
& cmd /c --% docker network create spec_default --driver nat 2>&1 | ||
|
||
# only download CA file if not present - throw on failures | ||
If (-Not (Test-Path -Path $CACertFile)) { Invoke-ScriptBlockWithRetry @retryArgs } | ||
|
||
Write-Information "Setting CA Certificate store set to $CACertFile.." | ||
$ENV:SSL_CERT_FILE = $CACertFile | ||
[System.Environment]::SetEnvironmentVariable('SSL_CERT_FILE', $CACertFile, [System.EnvironmentVariableTarget]::Machine) | ||
} | ||
|
||
function Install-Puppetfile | ||
{ | ||
Set-CACert | ||
|
||
# Forge connections may fail intermittently | ||
$retryArgs = @{ | ||
SuccessMessage = 'Succeeded in installing Puppetfile' | ||
FailMessage = 'Failed to install required modules from Forge' | ||
Retries = 10 | ||
Timeout = 2 | ||
Script = { bundle exec r10k puppetfile install } | ||
} | ||
|
||
Invoke-ScriptBlockWithRetry @retryArgs | ||
} | ||
|
||
function New-RandomPassword | ||
{ | ||
Add-Type -AssemblyName System.Web | ||
"&aA4" + [System.Web.Security.Membership]::GeneratePassword(10, 3) | ||
} | ||
|
||
function New-LocalAdmin($userName, $password) | ||
{ | ||
$userArgs = @{ | ||
Name = $userName | ||
Password = (ConvertTo-SecureString -String $password -Force -AsPlainText) | ||
} | ||
|
||
$user = New-LocalUser @userArgs | ||
Write-Information ($user | Format-List | Out-String) | ||
Add-LocalGroupMember -Group 'Remote Management Users' -Member $user | ||
Add-LocalGroupMember -Group Administrators -Member $user | ||
} | ||
|
||
function Install-Certificate($path, $password) | ||
{ | ||
$importArgs = @{ | ||
FilePath = $path | ||
CertStoreLocation = 'cert:\\LocalMachine\\My' | ||
Password = (ConvertTo-SecureString -String $password -Force -AsPlainText) | ||
} | ||
|
||
return (Import-PfxCertificate @importArgs) | ||
} | ||
|
||
function Grant-WinRMHttpsAccess($certThumbprint) | ||
{ | ||
$winRMArgs = @{ | ||
ResourceURI = 'winrm/config/Listener' | ||
SelectorSet = @{ Address = '*'; Transport = 'HTTPS'; } | ||
ValueSet = @{ Hostname = 'boltserver'; CertificateThumbprint = $certThumbprint } | ||
} | ||
$instance = Set-WSManInstance @winRMArgs | ||
Write-Information ($instance | Format-List | Out-String) | ||
} | ||
|
||
function Set-WinRMHostConfiguration | ||
{ | ||
# configure WinRM to use cert.pfx for SSL | ||
$cert = Install-Certificate -Path 'spec/fixtures/ssl/cert.pfx' -Password 'bolt' | ||
Write-Information ($cert | Format-List | Out-String) | ||
Grant-WinRMHttpsAccess -CertThumbprint $cert.Thumbprint | ||
} | ||
|
||
function Invoke-ScriptBlockWithRetry([ScriptBlock]$script, $failMessage, $successMessage, $retries = 15, $timeout = 1) | ||
{ | ||
$retried = 0 | ||
|
||
Do | ||
{ | ||
try { | ||
$script.Invoke() | ||
Write-Information "$successMessage after $($retried + 1) attempt(s)" | ||
return $true | ||
} | ||
catch | ||
{ | ||
$retried++ | ||
Start-Sleep -Seconds $timeout | ||
} | ||
} While ($retried -lt $retries) | ||
|
||
throw "ERROR: $failMessage in $retried retries`n$($Error[0])" | ||
|
||
} | ||
|
||
function Test-WinRMConfiguration($userName, $password, $retries = 15, $timeout = 1) | ||
{ | ||
$retryArgs = @{ | ||
FailMessage = 'Failed to establish WinRM connection over SSL' | ||
SuccessMessage = "Successfully established WinRM connection with $userName" | ||
Retries = $retries | ||
Timeout = $timeout | ||
Script = { | ||
$pass = ConvertTo-SecureString $password -AsPlainText -Force | ||
$sessionArgs = @{ | ||
ComputerName = 'localhost' | ||
Credential = New-Object System.Management.Automation.PSCredential ($userName, $pass) | ||
UseSSL = $true | ||
SessionOption = New-PSSessionOption -SkipRevocationCheck -SkipCACheck | ||
} | ||
|
||
if (New-PSSession @sessionArgs) { return $true } | ||
} | ||
} | ||
|
||
Invoke-ScriptBlockWithRetry @retryArgs | ||
} | ||
|
||
# Ensure Puppet Ruby 5 / 6 takes precedence over system Ruby | ||
function Set-ActiveRubyFromPuppet | ||
{ | ||
# https://github.com/puppetlabs/puppet-specifications/blob/master/file_paths.md | ||
$path = @( | ||
"${ENV:ProgramFiles}\Puppet Labs\Puppet\sys\ruby\bin", | ||
"${ENV:ProgramFiles}\Puppet Labs\Puppet\puppet\bin", | ||
$ENV:Path | ||
) -join ';' | ||
|
||
[System.Environment]::SetEnvironmentVariable('Path', $path, [System.EnvironmentVariableTarget]::Machine) | ||
} | ||
|
||
$Pass = New-RandomPassword | ||
$User = @{ UserName = $ENV:BOLT_WINRM_USER; Password = $Pass } | ||
New-LocalAdmin @User | ||
Enable-PSRemoting | ||
Set-WSManQuickConfig -Force | ||
Set-WinRMHostConfiguration | ||
Test-WinRMConfiguration @User | Out-Null | ||
Write-Output "::set-env name=BOLT_WINRM_PASSWORD::$pass" | ||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force | ||
winrm "set" "winrm/config/client/auth" "@{Kerberos=`"false`"}" | ||
winrm "set" "winrm/config/client" "@{AllowUnencrypted=`"true`"}" | ||
Set-ItemProperty -Path REGISTRY::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System -Name ConsentPromptBehaviorAdmin -Value 0 | ||
|
||
& cmd /c --% docker-compose -f spec/docker-compose-windev.yml --verbose --no-ansi up -d --build 2>&1 |
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 |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM mcr.microsoft.com/windows/servercore:ltsc2019 | ||
|
||
COPY fixtures/scripts/windev/setup.ps1 ./ | ||
COPY fixtures/scripts/windev/agent.ps1 ./ | ||
RUN powershell ./setup.ps1 | ||
RUN powershell ./agent.ps1 | ||
CMD ["powershell", "Start-Sleep", "-s 1000000"] |
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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM mcr.microsoft.com/windows/servercore:ltsc2019 | ||
|
||
COPY fixtures/ssl/cert.pfx ./ | ||
COPY fixtures/scripts/windev/setup.ps1 ./ | ||
RUN powershell ./setup.ps1 | ||
CMD ["powershell", "Start-Sleep", "-s 1000000"] |
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 |
---|---|---|
@@ -0,0 +1,17 @@ | ||
version: "3" | ||
services: | ||
windows_node: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile.windev | ||
ports: | ||
- "25985:5985" | ||
- "25986:5986" | ||
|
||
windows_agent: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile.winagent | ||
ports: | ||
- "35985:5985" | ||
- "35986:5986" |
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 |
---|---|---|
@@ -0,0 +1,12 @@ | ||
$InformationPreference = 'Continue' | ||
$ErrorActionPreference = 'Stop' | ||
|
||
# Ensure Puppet Ruby 5 / 6 takes precedence over system Ruby | ||
# https://github.com/puppetlabs/puppet-specifications/blob/master/file_paths.md | ||
$path = @( | ||
"${ENV:ProgramFiles}\Puppet Labs\Puppet\sys\ruby\bin", | ||
"${ENV:ProgramFiles}\Puppet Labs\Puppet\puppet\bin", | ||
$ENV:Path | ||
) -join ';' | ||
|
||
[System.Environment]::SetEnvironmentVariable('Path', $path, [System.EnvironmentVariableTarget]::Machine) |
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 |
---|---|---|
@@ -0,0 +1,21 @@ | ||
$InformationPreference = 'Continue' | ||
$ErrorActionPreference = 'Stop' | ||
|
||
$User = 'bolt' | ||
$Password = 'bolt' | ||
|
||
# Disable password complexity requirements | ||
secedit /export /cfg c:\secpol.cfg | ||
(gc C:\secpol.cfg).replace("PasswordComplexity = 1", "PasswordComplexity = 0") | Out-File C:\secpol.cfg | ||
secedit /configure /db c:\windows\security\local.sdb /cfg c:\secpol.cfg /areas SECURITYPOLICY | ||
rm -force c:\secpol.cfg -confirm:$false | ||
|
||
# add the bolt user account | ||
New-LocalUser -Name $User -Password (ConvertTo-SecureString -String $Password -Force -AsPlainText) | ||
#Add-LocalGroupMember -Group 'Remote Management Users' -Member $User | ||
Add-LocalGroupMember -Group 'Administrators' -Member $User | ||
|
||
# Enable WinRM | ||
Enable-PSRemoting | ||
winrm "set" "winrm/config/service/auth" "@{Kerberos=`"false`"}" | ||
winrm "set" "winrm/config/service" "@{AllowUnencrypted=`"true`"}" |
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
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