diff --git a/provisioner/powershell/elevated.go b/provisioner/powershell/elevated.go index d2c23f757..6e0faa3d6 100644 --- a/provisioner/powershell/elevated.go +++ b/provisioner/powershell/elevated.go @@ -5,16 +5,17 @@ import ( ) type elevatedOptions struct { - User string - Password string - TaskName string - TaskDescription string - EncodedCommand string + User string + Password string + TaskName string + TaskDescription string + LogFile string + XMLEscapedCommand string } var elevatedTemplate = template.Must(template.New("ElevatedCommand").Parse(` $name = "{{.TaskName}}" -$log = "$env:SystemRoot\Temp\$name.out" +$log = [System.Environment]::ExpandEnvironmentVariables("{{.LogFile}}") $s = New-Object -ComObject "Schedule.Service" $s.Connect() $t = $s.NewTask($null) @@ -53,7 +54,7 @@ $t.XmlText = @' cmd - /c powershell.exe -EncodedCommand {{.EncodedCommand}} > %SYSTEMROOT%\Temp\{{.TaskName}}.out 2>&1 + /c {{.XMLEscapedCommand}} diff --git a/provisioner/powershell/powershell.go b/provisioner/powershell/powershell.go deleted file mode 100644 index 086e3e554..000000000 --- a/provisioner/powershell/powershell.go +++ /dev/null @@ -1,54 +0,0 @@ -package powershell - -import ( - "encoding/base64" - "encoding/binary" - "unicode/utf16" - "unicode/utf8" - - "golang.org/x/text/encoding/unicode" -) - -func convertUtf8ToUtf16LE(message string) (string, error) { - utf16le := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM) - utfEncoder := utf16le.NewEncoder() - ut16LeEncodedMessage, err := utfEncoder.String(message) - - return ut16LeEncodedMessage, err -} - -// UTF16BytesToString converts UTF-16 encoded bytes, in big or little endian byte order, -// to a UTF-8 encoded string. -func UTF16BytesToString(b []byte, o binary.ByteOrder) string { - utf := make([]uint16, (len(b)+(2-1))/2) - for i := 0; i+(2-1) < len(b); i += 2 { - utf[i/2] = o.Uint16(b[i:]) - } - if len(b)/2 < len(utf) { - utf[len(utf)-1] = utf8.RuneError - } - return string(utf16.Decode(utf)) -} - -func powershellEncode(message string) (string, error) { - utf16LEEncodedMessage, err := convertUtf8ToUtf16LE(message) - if err != nil { - return "", err - } - - // Base64 encode the command - input := []uint8(utf16LEEncodedMessage) - return base64.StdEncoding.EncodeToString(input), nil -} - -func powershellDecode(messageBase64 string) (retour string, err error) { - messageUtf16LeByteArray, err := base64.StdEncoding.DecodeString(messageBase64) - - if err != nil { - return "", err - } - - message := UTF16BytesToString(messageUtf16LeByteArray, binary.LittleEndian) - - return message, nil -} diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index fd967ce86..4297acf08 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -5,6 +5,7 @@ package powershell import ( "bufio" "bytes" + "encoding/xml" "errors" "fmt" "io/ioutil" @@ -112,7 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } if p.config.EnvVarFormat == "" { - p.config.EnvVarFormat = `$env:%s="%s"; ` + p.config.EnvVarFormat = `$env:%s=\"%s\"; ` } if p.config.ElevatedEnvVarFormat == "" { @@ -120,11 +121,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } if p.config.ExecuteCommand == "" { - p.config.ExecuteCommand = `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode` + p.config.ExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"` } if p.config.ElevatedExecuteCommand == "" { - p.config.ElevatedExecuteCommand = `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; . {{.Vars}}; &'{{.Path}}'; exit $LastExitCode` + p.config.ElevatedExecuteCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` } if p.config.Inline != nil && len(p.config.Inline) == 0 { @@ -389,25 +390,8 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro return "", fmt.Errorf("Error processing command: %s", err) } - commandText, err := p.generateCommandLineRunner(command) - if err != nil { - return "", fmt.Errorf("Error generating command line runner: %s", err) - } - - return commandText, err -} - -func (p *Provisioner) generateCommandLineRunner(command string) (commandText string, err error) { - log.Printf("Building command line for: %s", command) - - base64EncodedCommand, err := powershellEncode(command) - if err != nil { - return "", fmt.Errorf("Error encoding command: %s", err) - } - - commandText = "powershell -executionpolicy bypass -encodedCommand " + base64EncodedCommand - - return commandText, nil + // Return the interpolated command + return command, nil } func (p *Provisioner) createCommandTextPrivileged() (command string, err error) { @@ -449,20 +433,42 @@ func (p *Provisioner) createCommandTextPrivileged() (command string, err error) func (p *Provisioner) generateElevatedRunner(command string) (uploadedPath string, err error) { log.Printf("Building elevated command wrapper for: %s", command) - // generate command var buffer bytes.Buffer - base64EncodedCommand, err := powershellEncode(command) + // Output from the elevated command cannot be returned directly to + // the Packer console. In order to be able to view output from elevated + // commands and scripts an indirect approach is used by which the + // commands output is first redirected to file. The output file is then + // 'watched' by Packer while the elevated command is running and any + // content appearing in the file is written out to the console. + // Below the portion of command required to redirect output from the + // command to file is built and appended to the existing command string + taskName := fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()) + // Only use %ENVVAR% format for environment variables when setting + // the log file path; Do NOT use $env:ENVVAR format as it won't be + // expanded correctly in the elevatedTemplate + logFile := `%SYSTEMROOT%\Temp\` + taskName + ".out" + command += fmt.Sprintf(" > %s 2>&1", logFile) + + // elevatedTemplate wraps the command in a single quoted XML text + // string so we need to escape characters considered 'special' in XML. + err = xml.EscapeText(&buffer, []byte(command)) if err != nil { - return "", fmt.Errorf("Error encoding command: %s", err) + return "", fmt.Errorf("Error escaping characters special to XML in command %s: %s", command, err) } + escapedCommand := buffer.String() + log.Printf("Command [%s] converted to [%s] for use in XML string", command, escapedCommand) + + buffer.Reset() + // Generate command err = elevatedTemplate.Execute(&buffer, elevatedOptions{ - User: p.config.ElevatedUser, - Password: p.config.ElevatedPassword, - TaskDescription: "Packer elevated task", - TaskName: fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()), - EncodedCommand: base64EncodedCommand, + User: p.config.ElevatedUser, + Password: p.config.ElevatedPassword, + TaskName: taskName, + TaskDescription: "Packer elevated task", + LogFile: logFile, + XMLEscapedCommand: escapedCommand, }) if err != nil { diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 3b3d8fa46..e7e64d52e 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -79,12 +79,12 @@ func TestProvisionerPrepare_Defaults(t *testing.T) { t.Error("expected elevated_password to be empty") } - if p.config.ExecuteCommand != `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode` { - t.Fatalf(`Default command should be "if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode", but got %s`, p.config.ExecuteCommand) + if p.config.ExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"` { + t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand) } - if p.config.ElevatedExecuteCommand != `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; . {{.Vars}}; &'{{.Path}}'; exit $LastExitCode` { - t.Fatalf(`Default command should be "if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; . {{.Vars}}; &'{{.Path}}'; exit $LastExitCode", but got %s`, p.config.ElevatedExecuteCommand) + if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` { + t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ElevatedExecuteCommand) } if p.config.ValidExitCodes == nil { @@ -413,23 +413,9 @@ func TestProvisionerProvision_Inline(t *testing.T) { t.Fatal("should not have error") } - expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode` - expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiAGkAcwBvACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiAHYAbQB3AGEAcgBlACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAGkAbgBsAGkAbgBlAFMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==` - expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand ` - expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded - - actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1) - actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix) - if err != nil { - t.Fatal("should not have error when base64 decoding") - } - - if actualCommandDecoded != expectedCommand { - t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded) - } - - if comm.StartCmd.Command != expectedCommandEncoded { - t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command) + expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode }"` + if comm.StartCmd.Command != expectedCommand { + t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command) } envVars := make([]string, 2) @@ -444,23 +430,9 @@ func TestProvisionerProvision_Inline(t *testing.T) { t.Fatal("should not have error") } - expectedCommand = `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR="BAZ"; $env:FOO="BAR"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode` - expectedCommandBase64Encoded = `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AEIAQQBSAD0AIgBCAEEAWgAiADsAIAAkAGUAbgB2ADoARgBPAE8APQAiAEIAQQBSACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABFAFIAXwBUAFkAUABFAD0AIgBpAHMAbwAiADsAIAAkAGUAbgB2ADoAUABBAEMASwBFAFIAXwBCAFUASQBMAEQAXwBOAEEATQBFAD0AIgB2AG0AdwBhAHIAZQAiADsAIAAmACcAYwA6AC8AVwBpAG4AZABvAHcAcwAvAFQAZQBtAHAALwBpAG4AbABpAG4AZQBTAGMAcgBpAHAAdAAuAHAAcwAxACcAOwBlAHgAaQB0ACAAJABMAGEAcwB0AEUAeABpAHQAQwBvAGQAZQA=` - expectedCommandPrefix = `powershell -executionpolicy bypass -encodedCommand ` - expectedCommandEncoded = expectedCommandPrefix + expectedCommandBase64Encoded - - actualCommandWithoutPrefix = strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1) - actualCommandDecoded, err = powershellDecode(actualCommandWithoutPrefix) - if err != nil { - t.Fatal("should not have error when base64 decoding") - } - - if actualCommandDecoded != expectedCommand { - t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded) - } - - if comm.StartCmd.Command != expectedCommandEncoded { - t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command) + expectedCommand = `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR=\"BAZ\"; $env:FOO=\"BAR\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode }"` + if comm.StartCmd.Command != expectedCommand { + t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command) } } @@ -483,24 +455,11 @@ func TestProvisionerProvision_Scripts(t *testing.T) { t.Fatal("should not have error") } - expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode` - expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiAGYAbwBvAHQAeQBwAGUAIgA7ACAAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAF8ATgBBAE0ARQA9ACIAZgBvAG8AYgB1AGkAbABkACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAHMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==` - expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand ` - expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded - - actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1) - actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix) - if err != nil { - t.Fatal("should not have error when base64 decoding") - } - - if actualCommandDecoded != expectedCommand { - t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded) + expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"footype\"; $env:PACKER_BUILD_NAME=\"foobuild\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"` + if comm.StartCmd.Command != expectedCommand { + t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command) } - if comm.StartCmd.Command != expectedCommandEncoded { - t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command) - } } func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { @@ -529,23 +488,9 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { t.Fatal("should not have error") } - expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR="BAZ"; $env:FOO="BAR"; $env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode` - expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AEIAQQBSAD0AIgBCAEEAWgAiADsAIAAkAGUAbgB2ADoARgBPAE8APQAiAEIAQQBSACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABFAFIAXwBUAFkAUABFAD0AIgBmAG8AbwB0AHkAcABlACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiAGYAbwBvAGIAdQBpAGwAZAAiADsAIAAmACcAYwA6AC8AVwBpAG4AZABvAHcAcwAvAFQAZQBtAHAALwBzAGMAcgBpAHAAdAAuAHAAcwAxACcAOwBlAHgAaQB0ACAAJABMAGEAcwB0AEUAeABpAHQAQwBvAGQAZQA=` - expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand ` - expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded - - actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1) - actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix) - if err != nil { - t.Fatal("should not have error when base64 decoding") - } - - if actualCommandDecoded != expectedCommand { - t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded) - } - - if comm.StartCmd.Command != expectedCommandEncoded { - t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command) + expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR=\"BAZ\"; $env:FOO=\"BAR\"; $env:PACKER_BUILDER_TYPE=\"footype\"; $env:PACKER_BUILD_NAME=\"foobuild\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"` + if comm.StartCmd.Command != expectedCommand { + t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command) } } @@ -588,7 +533,6 @@ func TestProvisioner_createFlattenedElevatedEnvVars_windows(t *testing.T) { t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars) } } - } func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) { @@ -603,11 +547,11 @@ func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) { {"FOO==bar"}, // User env var with value starting with equals } expected := []string{ - `$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `, - `$env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `, - `$env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `, - `$env:FOO="bar=baz"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `, - `$env:FOO="=bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `, + `$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `, + `$env:FOO=\"bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `, + `$env:BAZ=\"qux\"; $env:FOO=\"bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `, + `$env:FOO=\"bar=baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `, + `$env:FOO=\"=bar\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; `, } p := new(Provisioner) @@ -635,27 +579,17 @@ func TestProvision_createCommandText(t *testing.T) { p.communicator = comm _ = p.Prepare(config) + // Defaults provided by Packer + p.config.PackerBuildName = "vmware" + p.config.PackerBuilderType = "iso" + // Non-elevated cmd, _ := p.createCommandText() - expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=""; $env:PACKER_BUILD_NAME=""; &'c:/Windows/Temp/script.ps1';exit $LastExitCode` - expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAHMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==` - expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand ` - expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded - - actualCommandWithoutPrefix := strings.Replace(cmd, expectedCommandPrefix, "", -1) - - actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix) - if err != nil { - t.Fatal("should not have error when base64 decoding") - } - - if actualCommandDecoded != expectedCommand { - t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded) - } + expectedCommand := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode }"` - if cmd != expectedCommandEncoded { - t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, cmd) + if cmd != expectedCommand { + t.Fatalf("Expected Non-elevated command: %s, got %s", expectedCommand, cmd) } // Elevated diff --git a/website/source/docs/provisioners/powershell.html.md b/website/source/docs/provisioners/powershell.html.md index 765760ad9..f085a6e82 100644 --- a/website/source/docs/provisioners/powershell.html.md +++ b/website/source/docs/provisioners/powershell.html.md @@ -56,7 +56,12 @@ Optional parameters: endings (if there are any). By default this is false. - `elevated_execute_command` (string) - The command to use to execute the elevated - script. By default this is `powershell if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; . {{.Vars}}; &'{{.Path}}'; exit $LastExitCode`. + script. By default this is as follows: + + ``` powershell + powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }" + ``` + The value of this is treated as [configuration template](/docs/templates/engine.html). There are two available variables: `Path`, which is the path to the script to run, and @@ -68,7 +73,12 @@ Optional parameters: as well, which are covered in the section below. - `execute_command` (string) - The command to use to execute the script. By - default this is `powershell if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode`. + default this is as follows: + + ``` powershell + powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode }" + ``` + The value of this is treated as [configuration template](/docs/templates/engine.html). There are two available variables: `Path`, which is the path to the script to run, and