Add support for 3006 on windows bootstrap script

This commit is contained in:
Twangboy 2023-04-20 14:31:28 -06:00
parent 9fa32bd95c
commit 15dfb8efdd
No known key found for this signature in database
GPG key ID: 9B77EE3C5C0D9F63

View file

@ -37,13 +37,13 @@
Specifies all the optional parameters in no particular order. Specifies all the optional parameters in no particular order.
.PARAMETER version .PARAMETER version
Default version defined in this script. The version of the Salt minion to install. Default is "latest" which will
install the latest version of Salt minion available.
.PARAMETER pythonVersion .PARAMETER pythonVersion
The version of Python the installer should use. Specify either "2" or "3". The version of Python the installer should use. Specify either "2" or "3".
Beginning with Salt 2017.7.0, Salt will run on either Python 2 or Python 3. Beginning with Salt 2017.7.0, Salt will run on either Python 2 or Python 3.
The default is Python 2 if not specified. This parameter only works for Salt The default is Python 2 if not specified. This parameter only works for Salt
versions >= 2017.7.0.
.PARAMETER runservice .PARAMETER runservice
Boolean flag to start or stop the minion service. True will start the minion Boolean flag to start or stop the minion service. True will start the minion
@ -81,32 +81,47 @@ param(
# Supports new version and latest # Supports new version and latest
# Option 1 means case insensitive # Option 1 means case insensitive
[ValidatePattern('^(\d{4}(\.\d{1,2}){0,2}(\-\d{1})?)|(latest)$', Options=1)] [ValidatePattern('^(\d{4}(\.\d{1,2}){0,2}(\-\d{1})?)|(latest)$', Options=1)]
[string]$Version = '', [Alias("v")]
[String]$Version = "latest",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
# Doesn't support Python versions prior to "2017.7.0" # Python 3 support was added in 2017. Python 2 support was dropped in
# version 3001. This parameter is ignored for all versions before 2017 and
# after 3000.
[ValidateSet("2","3")] [ValidateSet("2","3")]
[string]$PythonVersion = "3", [Alias("p")]
[String]$PythonVersion = "3",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
[ValidateSet("true","false")] [ValidateSet("true","false")]
[string]$RunService = "true", [Alias("s")]
[String]$RunService = "true",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
[string]$Minion = "not-specified", [Alias("m")]
[String]$Minion = "not-specified",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
[string]$Master = "not-specified", [Alias("a")]
[String]$Master = "not-specified",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
[string]$RepoUrl= "https://repo.saltproject.io/windows", [Alias("r")]
[String]$RepoUrl = "https://repo.saltproject.io/salt/py3/windows",
[Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Parameter(Mandatory=$false, ValueFromPipeline=$True)]
[switch]$ConfigureOnly [Alias("c")]
[Switch]$ConfigureOnly
) )
#===============================================================================
# Script Preferences
#===============================================================================
# Powershell supports only TLS 1.0 by default. Add support for TLS 1.2 # Powershell supports only TLS 1.0 by default. Add support for TLS 1.2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls12' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls12'
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
#=============================================================================== #===============================================================================
# Script Functions # Script Functions
@ -123,6 +138,129 @@ function Get-IsUacEnabled
(Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System).EnableLua -ne 0 (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System).EnableLua -ne 0
} }
function Get-MajorVersion {
# Parses a version string and returns the major version
#
# Args:
# Version (string): The Version to parse
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, Position=0)]
[String] $Version
)
return ( $Version -split "\." )[0]
}
function Convert-PSObjectToHashtable {
param (
[Parameter(ValueFromPipeline)]
$InputObject
)
if ($null -eq $InputObject) { return $null }
$is_enum = $InputObject -is [System.Collections.IEnumerable]
$not_string = $InputObject -isnot [string]
if ($is_enum -and $not_string) {
$collection = @(
foreach ($object in $InputObject) {
Convert-PSObjectToHashtable $object
}
)
Write-Host -NoEnumerate $collection
} elseif ($InputObject -is [PSObject]) {
$hash = @{}
foreach ($property in $InputObject.PSObject.Properties) {
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
}
$hash
} else {
$InputObject
}
}
function Get-FileHash {
# Get-FileHash is a built-in cmdlet in powershell 5+ but we need to support
# powershell 3. This will overwrite the powershell 5 commandlet only for
# this script. But it will provide the missing cmdlet for powershell 3
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[String] $Path,
[Parameter(Mandatory=$false)]
[ValidateSet(
"SHA1",
"SHA256",
"SHA384",
"SHA512",
# https://serverfault.com/questions/820300/
# why-isnt-mactripledes-algorithm-output-in-powershell-stable
"MACTripleDES", # don't use
"MD5",
"RIPEMD160",
IgnoreCase=$true)]
[String] $Algorithm = "SHA256"
)
if ( !(Test-Path $Path) ) {
Write-Verbose "Invalid path for hashing: $Path"
return @{}
}
if ( (Get-Item -Path $Path) -isnot [System.IO.FileInfo]) {
Write-Verbose "Not a file for hashing: $Path"
return @{}
}
$Path = Resolve-Path -Path $Path
Switch ($Algorithm) {
SHA1 {
$hasher = [System.Security.Cryptography.SHA1CryptoServiceProvider]::Create()
}
SHA256 {
$hasher = [System.Security.Cryptography.SHA256]::Create()
}
SHA384 {
$hasher = [System.Security.Cryptography.SHA384]::Create()
}
SHA512 {
$hasher = [System.Security.Cryptography.SHA512]::Create()
}
MACTripleDES {
$hasher = [System.Security.Cryptography.MACTripleDES]::Create()
}
MD5 {
$hasher = [System.Security.Cryptography.MD5]::Create()
}
RIPEMD160 {
$hasher = [System.Security.Cryptography.RIPEMD160]::Create()
}
}
Write-Verbose "Hashing using $Algorithm algorithm"
try {
$data = [System.IO.File]::OpenRead($Path)
$hash = $hasher.ComputeHash($data)
$hash = [System.BitConverter]::ToString($hash) -replace "-",""
return @{
Path = $Path;
Algorithm = $Algorithm.ToUpper();
Hash = $hash
}
} catch {
Write-Verbose "Error hashing: $Path"
return @{}
} finally {
if ($null -ne $data) {
$data.Close()
}
}
}
#=============================================================================== #===============================================================================
# Check for Elevated Privileges # Check for Elevated Privileges
#=============================================================================== #===============================================================================
@ -157,28 +295,56 @@ if (!(Get-IsAdministrator)) {
} }
} }
#===============================================================================
# Change RepoUrl for older versions
#===============================================================================
$defaultUrl = "https://repo.saltproject.io/salt/py3/windows"
$oldRepoUrl = "https://repo.saltproject.io/windows"
$majorVersion = Get-MajorVersion -Version $Version
$customUrl = $true
if ( $Version.ToLower() -ne "latest" ) {
# A specific version has been passed
# We only want to modify the URL if a custom URL was not passed
$uri = [Uri]($RepoUrl)
if ( $uri.AbsoluteUri -eq $defaultUrl ) {
# No customURL passed, let's check for a pre 3006 version
$customUrl = $false
if ( $majorVersion -lt "3006" ) {
# This is an older version, use the old URL
$RepoUrl = $oldRepoUrl
} else {
# This is a new URL, and a version was passed, let's look in minor
if ( $Version.ToLower() -ne $majorVersion.ToLower() ) {
$RepoUrl = "$RepoUrl/minor"
}
}
}
} else {
if ( $RepoUrl -eq $defaultUrl ) {
$customUrl = $false
}
}
#=============================================================================== #===============================================================================
# Verify Parameters # Verify Parameters
#=============================================================================== #===============================================================================
Write-Verbose "Parameters passed in:" Write-Verbose "Parameters passed in:"
Write-Verbose "version: $version" Write-Verbose "version: $Version"
Write-Verbose "runservice: $runservice" Write-Verbose "runservice: $RunService"
Write-Verbose "master: $master" Write-Verbose "master: $Master"
Write-Verbose "minion: $minion" Write-Verbose "minion: $Minion"
Write-Verbose "repourl: $repourl" Write-Verbose "repourl: $RepoUrl"
if ($runservice.ToLower() -eq "true") { if ($RunService.ToLower() -eq "true") {
Write-Verbose "Windows service will be set to run" Write-Verbose "Windows service will be set to run"
[bool]$runservice = $True [bool]$RunService = $True
} } elseif ($RunService.ToLower() -eq "false") {
elseif ($runservice.ToLower() -eq "false") {
Write-Verbose "Windows service will be stopped and set to manual" Write-Verbose "Windows service will be stopped and set to manual"
[bool]$runservice = $False [bool]$RunService = $False
} } else {
else {
# Param passed in wasn't clear so defaulting to true. # Param passed in wasn't clear so defaulting to true.
Write-Verbose "Windows service defaulting to run automatically" Write-Verbose "Windows service defaulting to run automatically"
[bool]$runservice = $True [bool]$RunService = $True
} }
#=============================================================================== #===============================================================================
@ -231,8 +397,14 @@ if (Test-Path C:\tmp\grains) {
$ConfiguredAnything = $True $ConfiguredAnything = $True
} }
if ($ConfigureOnly -and !$ConfiguredAnything) { if ( $ConfigureOnly ) {
Write-Output "No configuration or keys were copied over. No configuration was done!" if ( !$ConfiguredAnything ) {
Write-Host "No configuration or keys were copied over." -ForegroundColor yes
Write-Host "No configuration was done!" -ForegroundColor Yellow
} else {
Write-Host "Salt minion successfully configured" -ForegroundColor Green
}
# If we're only configuring, we want to end here
exit 0 exit 0
} }
@ -246,97 +418,168 @@ if ([IntPtr]::Size -eq 4) {
} }
#=============================================================================== #===============================================================================
# Use version "Latest" if no version is passed # Get file name to download
#=============================================================================== #===============================================================================
if ((!$version) -or ($version.ToLower() -eq 'latest')){ $saltFileName = ""
$versionSection = "Latest-Py$PythonVersion" $saltVersion = ""
$saltSha512= ""
$saltFileUrl = ""
if ( ($customUrl) -or ($majorVersion -lt 3006) ) {
$saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe"
$saltVersion = $Version
$saltFileUrl = "$RepoUrl/$saltFileName"
} else { } else {
$versionSection = $version if ( $majorVersion -ge 3006 ) {
$year = $version.Substring(0, 4) $enc = [System.Text.Encoding]::UTF8
if ([int]$year -ge 2017) { try {
if ($PythonVersion -eq "3") { $response = Invoke-WebRequest -Uri "$RepoUrl/repo.json" -UseBasicParsing
$versionSection = "$version-Py3" if ($response.Content.GetType().Name -eq "Byte[]") {
} else { $psobj = $enc.GetString($response.Content) | ConvertFrom-Json
$versionSection = "$version-Py2" } else {
$psobj = $response.Content | ConvertFrom-Json
}
$hash = Convert-PSObjectToHashtable $psobj
} catch {
Write-Verbose "repo.json not found at: $RepoUrl"
$hash = @{}
}
$searchVersion = $Version.ToLower()
if ( $hash.Contains($searchVersion)) {
foreach ($item in $hash.($searchVersion).Keys) {
if ( $item.EndsWith(".exe") ) {
if ( $item.Contains($arch) ) {
$saltFileName = $hash.($searchVersion).($item).name
$saltVersion = $hash.($searchVersion).($item).version
$saltSha512 = $hash.($searchVersion).($item).SHA512
}
}
}
}
if ( $saltFileName -and $saltVersion -and $saltSha512 ) {
if ( $RepoUrl.Contains("minor") ) {
$saltFileUrl = @($RepoUrl, $saltVersion, $saltFileName) -join "/"
} else {
$saltFileUrl = @($RepoUrl, "minor", $saltVersion, $saltFileName) -join "/"
}
} }
} }
} }
if (!$ConfigureOnly) { #===============================================================================
#=============================================================================== # Download minion setup file
# Download minion setup file #===============================================================================
#=============================================================================== Write-Host "===============================================================================" -ForegroundColor Yellow
$saltExe = "Salt-Minion-$versionSection-$arch-Setup.exe" Write-Host " Bootstrapping Salt Minion" -ForegroundColor Green
Write-Output "Downloading Salt minion installer $saltExe" Write-Host " - version: $Version"
$webclient = New-Object System.Net.WebClient Write-Host " - file name: $saltFileName"
$url = "$repourl/$saltExe" Write-Host " - file url: $saltFileUrl"
$file = "C:\Windows\Temp\$saltExe" Write-Host "-------------------------------------------------------------------------------" -ForegroundColor Yellow
$webclient.DownloadFile($url, $file) Write-Host "Downloading Installer: " -NoNewline
$webclient = New-Object System.Net.WebClient
$localFile = "C:\Windows\Temp\$saltFileName"
$webclient.DownloadFile($saltFileUrl, $localFile)
#=============================================================================== if ( Test-Path -Path $localFile ) {
# Set the parameters for the installer Write-Host "Success" -ForegroundColor Green
#=============================================================================== } else {
# Unless specified, use the installer defaults Write-Host "Failed" -ForegroundColor Red
# - id: <hostname> }
# - master: salt
# - Start the service
$parameters = ""
if($minion -ne "not-specified") {$parameters = "/minion-name=$minion"}
if($master -ne "not-specified") {$parameters = "$parameters /master=$master"}
if($runservice -eq $false) {$parameters = "$parameters /start-service=0"}
#=============================================================================== if ( $saltSha512 ) {
# Install minion silently $localSha512 = (Get-FileHash -Path $localFile -Algorithm SHA512).Hash
#=============================================================================== Write-Host "Comparing Hash: " -NoNewline
#Wait for process to exit before continuing. if ( $localSha512 -eq $saltSha512 ) {
Write-Output "Installing Salt minion" Write-Host "Success" -ForegroundColor Green
Start-Process C:\Windows\Temp\$saltExe -ArgumentList "/S $parameters" -Wait -NoNewWindow -PassThru | Out-Null } else {
Write-Host "Failed" -ForegroundColor Red
#=============================================================================== exit 1
# Configure the minion service
#===============================================================================
# Wait for salt-minion service to be registered before trying to start it
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
while (!$service) {
Start-Sleep -s 2
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
} }
}
if($runservice) { #===============================================================================
# Start service # Set the parameters for the installer
Write-Output "Starting the Salt minion service" #===============================================================================
# Unless specified, use the installer defaults
# - id: <hostname>
# - master: salt
# - Start the service
$parameters = ""
if($Minion -ne "not-specified") {$parameters = "/minion-name=$Minion"}
if($Master -ne "not-specified") {$parameters = "$parameters /master=$Master"}
if($RunService -eq $false) {$parameters = "$parameters /start-service=0"}
#===============================================================================
# Install minion silently
#===============================================================================
#Wait for process to exit before continuing.
Write-Host "Installing Salt Minion: " -NoNewline
Start-Process $localFile -ArgumentList "/S $parameters" -Wait -NoNewWindow -PassThru | Out-Null
#===============================================================================
# Configure the minion service
#===============================================================================
# Wait for salt-minion service to be registered before trying to start it
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
while (!$service) {
Start-Sleep -s 2
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
}
if ( $service ) {
Write-Host "Success" -ForegroundColor Green
} else {
Write-Host "Failed" -ForegroundColor Red
exit 1
}
if($RunService) {
# Start service
Write-Host "Starting Service: " -NoNewline
Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue
# Check if service is started, otherwise retry starting the
# service 4 times.
$try = 0
while (($service.Status -ne "Running") -and ($try -ne 4)) {
Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
# Check if service is started, otherwise retry starting the Start-Sleep -s 2
# service 4 times. $try += 1
$try = 0
while (($service.Status -ne "Running") -and ($try -ne 4)) {
Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue
$service = Get-Service salt-minion -ErrorAction SilentlyContinue
Start-Sleep -s 2
$try += 1
}
# If the salt-minion service is still not running, something probably
# went wrong and user intervention is required - report failure.
if ($service.Status -eq "Stopped") {
Write-Output -NoNewline "Failed to start salt minion"
exit 1
}
} }
else {
Write-Output -NoNewline "Stopping salt minion and setting it to 'Manual'" # If the salt-minion service is still not running, something probably
Set-Service "salt-minion" -StartupType "Manual" # went wrong and user intervention is required - report failure.
Stop-Service "salt-minion" if ($service.Status -eq "Running") {
Write-Host "Success" -ForegroundColor Green
} else {
Write-Host "Failed" -ForegroundColor Red
exit 1
}
} else {
Write-Host "Setting Service to 'Manual': " -NoNewline
Set-Service "salt-minion" -StartupType "Manual"
if ( (Get-Service "salt-minion").StartType -eq "Manual" ) {
Write-Host "Success" -ForegroundColor Green
} else {
Write-Host "Failed" -ForegroundColor Red
exit 1
}
Write-Host "Stopping Service: " -NoNewline
Stop-Service "salt-minion"
if ( (Get-Service "salt-minion").Status -eq "Stopped" ) {
Write-Host "Success" -ForegroundColor Green
} else {
Write-Host "Failed" -ForegroundColor Red
exit 1
} }
} }
#=============================================================================== #===============================================================================
# Script Complete # Script Complete
#=============================================================================== #===============================================================================
if ($ConfigureOnly) { Write-Host "-------------------------------------------------------------------------------" -ForegroundColor Yellow
Write-Output "Salt minion successfully configured" Write-Host "Salt Minion Installed Successfully" -ForegroundColor Green
} Write-Host "===============================================================================" -ForegroundColor Yellow
else { exit 0
Write-Output "Salt minion successfully installed"
}