mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-09 08:42:33 -04:00
Powershell Provisioner Error Handling (#13334)
* WIP Testing Approach * WIP Testing Approach * WIP Testing Approach Work * WIP Testing Approach * adding acceptance test for windows Amazon EBS. * modify wrapper string to use Set-Variable * fixing unit tests * cleanup * updated approach to use -file instead of inline powershell execution. * adding more scenarios for acceptance test. * using writeString for file directly. * changing variable name * updating test case. cleanup. * updating test case * updating test case * updating test case - nested try catch * adding unit test for None Execution Policy * adding unit test for None Execution Policy * fix test case
This commit is contained in:
parent
fe6eba27f2
commit
089df02532
6 changed files with 261 additions and 33 deletions
|
|
@ -8,7 +8,6 @@
|
|||
package powershell
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -38,6 +37,33 @@ var psEscape = strings.NewReplacer(
|
|||
"'", "`'",
|
||||
)
|
||||
|
||||
// wraps the content in try catch block and exits with a status.
|
||||
const wrapPowershellString string = `
|
||||
if (Test-Path variable:global:ProgressPreference) {
|
||||
set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'
|
||||
}
|
||||
{{if .DebugMode}}
|
||||
Set-PsDebug -Trace {{.DebugMode}}
|
||||
{{- end}}
|
||||
$exitCode = 0
|
||||
try {
|
||||
{{.Vars}}
|
||||
{{.Payload}}
|
||||
$exitCode = 0
|
||||
} catch {
|
||||
Write-Error "An error occurred: $_"
|
||||
$exitCode = 1
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {
|
||||
$exitCode = $LASTEXITCODE
|
||||
}
|
||||
|
||||
Write-Host $result
|
||||
exit $exitCode
|
||||
|
||||
`
|
||||
|
||||
type Config struct {
|
||||
shell.Provisioner `mapstructure:",squash"`
|
||||
|
||||
|
|
@ -105,23 +131,15 @@ type Provisioner struct {
|
|||
}
|
||||
|
||||
func (p *Provisioner) defaultExecuteCommand() string {
|
||||
baseCmd := `& { if (Test-Path variable:global:ProgressPreference)` +
|
||||
`{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};`
|
||||
|
||||
if p.config.DebugMode != 0 {
|
||||
baseCmd += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
|
||||
}
|
||||
|
||||
baseCmd += `. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }`
|
||||
|
||||
if p.config.ExecutionPolicy == ExecutionPolicyNone {
|
||||
return baseCmd
|
||||
return `-file {{.Path}}`
|
||||
}
|
||||
|
||||
if p.config.UsePwsh {
|
||||
return fmt.Sprintf(`pwsh -executionpolicy %s -command "%s"`, p.config.ExecutionPolicy, baseCmd)
|
||||
return fmt.Sprintf(`pwsh -executionpolicy %s -file {{.Path}}`, p.config.ExecutionPolicy)
|
||||
} else {
|
||||
return fmt.Sprintf(`powershell -executionpolicy %s "%s"`, p.config.ExecutionPolicy, baseCmd)
|
||||
return fmt.Sprintf(`powershell -executionpolicy %s -file {{.Path}}`, p.config.ExecutionPolicy)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -247,24 +265,41 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Takes the inline scripts, concatenates them into a temporary file and
|
||||
// Takes the inline scripts, adds a wrapper around the inline scripts, concatenates them into a temporary file and
|
||||
// returns a string containing the location of said file.
|
||||
func extractScript(p *Provisioner) (string, error) {
|
||||
temp, err := tmp.File("powershell-provisioner")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer temp.Close()
|
||||
writer := bufio.NewWriter(temp)
|
||||
|
||||
var commandBuilder strings.Builder
|
||||
|
||||
// we concatenate all the inline commands
|
||||
for _, command := range p.config.Inline {
|
||||
log.Printf("Found command: %s", command)
|
||||
if _, err := writer.WriteString(command + "\n"); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
if _, err := commandBuilder.WriteString(command); err != nil {
|
||||
return "", fmt.Errorf("failed to wrap script contents: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := writer.Flush(); err != nil {
|
||||
return "", fmt.Errorf("Error preparing powershell script: %s", err)
|
||||
// injecting all the variables in the string
|
||||
ctxData := p.generatedData
|
||||
ctxData["Vars"] = p.createFlattenedEnvVars(p.config.ElevatedUser != "")
|
||||
ctxData["Payload"] = commandBuilder.String()
|
||||
ctxData["DebugMode"] = p.config.DebugMode
|
||||
p.config.ctx.Data = ctxData
|
||||
|
||||
data, err := interpolate.Render(wrapPowershellString, &p.config.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error building powershell wrapper: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Writing PowerShell script to file: %s", temp.Name())
|
||||
if _, err := temp.WriteString(data); err != nil {
|
||||
return "", fmt.Errorf("Error writing PowerShell script: %w", err)
|
||||
}
|
||||
|
||||
return temp.Name(), nil
|
||||
|
|
|
|||
|
|
@ -111,3 +111,26 @@ func TestAccPowershellProvisioner_Script(t *testing.T) {
|
|||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
||||
func TestAccPowershellProvisioner_ExitCodes(t *testing.T) {
|
||||
templateString, err := LoadProvisionerFragment("powershell-exit_codes-provisioner.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't load test fixture; %s", err.Error())
|
||||
}
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: powershellIsCompatible,
|
||||
Name: "powershell-provisioner-script",
|
||||
Template: templateString,
|
||||
Type: TestProvisionerType,
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ func TestProvisionerPrepare_extractScript(t *testing.T) {
|
|||
config := testConfig()
|
||||
p := new(Provisioner)
|
||||
_ = p.Prepare(config)
|
||||
p.generatedData = generatedData()
|
||||
file, err := extractScript(p)
|
||||
defer os.Remove(file)
|
||||
if err != nil {
|
||||
|
|
@ -35,13 +36,15 @@ func TestProvisionerPrepare_extractScript(t *testing.T) {
|
|||
|
||||
// File contents should contain 2 lines concatenated by newlines: foo\nbar
|
||||
readFile, err := os.ReadFile(file)
|
||||
expectedContents := "foo\nbar\n"
|
||||
expectedContents := "if (Test-Path variable:global:ProgressPreference) {\n set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'\n }\n \n $exitCode = 0\n try {\n $env:PACKER_BUILDER_TYPE=\"\"; $env:PACKER_BUILD_NAME=\"\"; \n foobar\n $exitCode = 0\n } catch {\n Write-Error \"An error occurred: $_\"\n $exitCode = 1\n }\n \n if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {\n $exitCode = $LASTEXITCODE\n }\n \n Write-Host $result\n exit $exitCode"
|
||||
normalizedExpectedContent := normalizeWhiteSpace(expectedContents)
|
||||
if err != nil {
|
||||
t.Fatalf("Should not be error: %s", err)
|
||||
}
|
||||
s := string(readFile[:])
|
||||
if s != expectedContents {
|
||||
t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", expectedContents, s)
|
||||
normalizedString := normalizeWhiteSpace(s)
|
||||
if normalizedString != normalizedExpectedContent {
|
||||
t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", normalizedExpectedContent, normalizedString)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,12 +77,12 @@ func TestProvisionerPrepare_Defaults(t *testing.T) {
|
|||
t.Error("expected elevated_password to be empty")
|
||||
}
|
||||
|
||||
if p.config.ExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand)
|
||||
if p.config.ExecuteCommand != `powershell -executionpolicy bypass -file {{.Path}}` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ExecuteCommand)
|
||||
}
|
||||
|
||||
if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ElevatedExecuteCommand)
|
||||
if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass -file {{.Path}}` {
|
||||
t.Fatalf(`Default command should be 'powershell -executionpolicy bypass -file {{.Path}}', but got '%s'`, p.config.ElevatedExecuteCommand)
|
||||
}
|
||||
|
||||
if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` {
|
||||
|
|
@ -120,7 +123,7 @@ func TestProvisionerPrepare_DebugMode(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
command := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};Set-PsDebug -Trace 1;. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
|
||||
command := `powershell -executionpolicy bypass -file {{.Path}}`
|
||||
if p.config.ExecuteCommand != command {
|
||||
t.Fatalf(fmt.Sprintf(`Expected command should be '%s' but got '%s'`, command, p.config.ExecuteCommand))
|
||||
}
|
||||
|
|
@ -483,7 +486,8 @@ func TestProvisionerProvision_Inline(t *testing.T) {
|
|||
}
|
||||
|
||||
cmd := comm.StartCmd.Command
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1'; exit \$LastExitCode }"`)
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`)
|
||||
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
|
@ -503,7 +507,7 @@ func TestProvisionerProvision_Inline(t *testing.T) {
|
|||
}
|
||||
|
||||
cmd = comm.StartCmd.Command
|
||||
re = regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1'; exit \$LastExitCode }"`)
|
||||
re = regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/inlineScript.ps1`)
|
||||
matched = re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
|
@ -533,7 +537,7 @@ func TestProvisionerProvision_Scripts(t *testing.T) {
|
|||
}
|
||||
|
||||
cmd := comm.StartCmd.Command
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/script.ps1`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
|
@ -570,7 +574,7 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
|
|||
}
|
||||
|
||||
cmd := comm.StartCmd.Command
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/script.ps1`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
|
@ -595,11 +599,11 @@ func TestProvisionerProvision_SkipClean(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
SkipClean: true,
|
||||
LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`,
|
||||
LastExecutedCommandRegex: `powershell -executionpolicy bypass -file c:/Windows/Temp/script.ps1`,
|
||||
},
|
||||
{
|
||||
SkipClean: false,
|
||||
LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1'; exit \$LastExitCode }"`,
|
||||
LastExecutedCommandRegex: `powershell -executionpolicy bypass -file c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1`,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -917,7 +921,7 @@ func TestProvision_createCommandText(t *testing.T) {
|
|||
p.generatedData = make(map[string]interface{})
|
||||
cmd, _ := p.createCommandText()
|
||||
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
|
||||
re := regexp.MustCompile(`powershell -executionpolicy bypass -file c:/Windows/Temp/script.ps1`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
|
|
@ -934,6 +938,28 @@ func TestProvision_createCommandText(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvision_createCommandTextNoneExecutionPolicy(t *testing.T) {
|
||||
config := testConfig()
|
||||
config["remote_path"] = "c:/Windows/Temp/script.ps1"
|
||||
p := new(Provisioner)
|
||||
|
||||
comm := new(packersdk.MockCommunicator)
|
||||
p.communicator = comm
|
||||
config["execution_policy"] = ExecutionPolicyNone
|
||||
_ = p.Prepare(config)
|
||||
|
||||
// Non-elevated
|
||||
p.generatedData = make(map[string]interface{})
|
||||
|
||||
cmd, _ := p.createCommandText()
|
||||
re := regexp.MustCompile(`-file c:/Windows/Temp/script.ps1`)
|
||||
matched := re.MatchString(cmd)
|
||||
if !matched {
|
||||
t.Fatalf("Got unexpected command: %s", cmd)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestProvision_uploadEnvVars(t *testing.T) {
|
||||
p := new(Provisioner)
|
||||
comm := new(packersdk.MockCommunicator)
|
||||
|
|
@ -976,3 +1002,18 @@ func generatedData() map[string]interface{} {
|
|||
"PackerHTTPPort": commonsteps.HttpPortNotImplemented,
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeWhiteSpace(s string) string {
|
||||
// Replace multiple spaces/tabs with a single space
|
||||
re := regexp.MustCompile(`[\t ]+`)
|
||||
s = re.ReplaceAllString(s, " ")
|
||||
|
||||
// Trim leading/trailing spaces and newlines
|
||||
s = strings.TrimSpace(s)
|
||||
|
||||
// Normalize line breaks (remove excessive empty lines)
|
||||
s = strings.ReplaceAll(s, "\r\n", "\n") // Convert Windows line endings to Unix
|
||||
s = strings.ReplaceAll(s, "\r", "\n") // Convert old Mac line endings to Unix
|
||||
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"type": "powershell",
|
||||
"inline": ["invalid-cmdlet"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["#Requires -Version 10.0"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["exit 1"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["}}"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["$LASTEXITCODE=1"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["throw 'XXX'"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"script": "../../provisioner/powershell/test-fixtures/scripts/set_version_latest.ps1",
|
||||
"valid_exit_codes": ["0"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"elevated_user": "Administrator",
|
||||
"elevated_password": "{{.WinRMPassword}}",
|
||||
"inline": "Get-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
|
||||
"valid_exit_codes": ["0"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": "ping invalidhost",
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": "sc.exe start command",
|
||||
"valid_exit_codes": ["1060"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": "echo 'Hi testing echo'; invalid command!; echo 'Another valid command';",
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": ["$ErrorActionPreference='Stop'", "Get-Item 'C:\\nonexistent.txt'"],
|
||||
"valid_exit_codes": ["1"]
|
||||
},
|
||||
{
|
||||
"type": "powershell",
|
||||
"inline": [
|
||||
"try {",
|
||||
" invalid command",
|
||||
"} catch {",
|
||||
" exit 1",
|
||||
"}"
|
||||
],
|
||||
"valid_exit_codes": ["1"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<powershell>
|
||||
# Set administrator password
|
||||
net user Administrator SuperS3cr3t!!!!
|
||||
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
|
||||
|
||||
# First, make sure WinRM can't be connected to
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
|
||||
|
||||
# Delete any existing WinRM listeners
|
||||
winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null
|
||||
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null
|
||||
|
||||
# Disable group policies which block basic authentication and unencrypted login
|
||||
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowBasic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowUnencryptedTraffic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowBasic -Value 1
|
||||
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowUnencryptedTraffic -Value 1
|
||||
|
||||
|
||||
# Create a new WinRM listener and configure
|
||||
winrm create winrm/config/listener?Address=*+Transport=HTTP
|
||||
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
|
||||
winrm set winrm/config '@{MaxTimeoutms="7200000"}'
|
||||
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
|
||||
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
|
||||
winrm set winrm/config/service/auth '@{Basic="true"}'
|
||||
winrm set winrm/config/client/auth '@{Basic="true"}'
|
||||
|
||||
# Configure UAC to allow privilege elevation in remote shells
|
||||
$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
|
||||
$Setting = 'LocalAccountTokenFilterPolicy'
|
||||
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force
|
||||
|
||||
# Configure and restart the WinRM Service; Enable the required firewall exception
|
||||
Stop-Service -Name WinRM
|
||||
Set-Service -Name WinRM -StartupType Automatic
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
|
||||
Start-Service -Name WinRM
|
||||
</powershell>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Test fixture is a modified version of the example found at
|
||||
# https://www.powershellmagazine.com/2012/10/23/pstip-set-strictmode-why-should-you-care/
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$myNumbersCollection = 1..5
|
||||
if($myNumbersCollection -contains 3) {
|
||||
"collection contains 3"
|
||||
}
|
||||
else {
|
||||
"collection doesn't contain 3"
|
||||
}
|
||||
Loading…
Reference in a new issue