From bdcc95f989a30078419c56bec10ce1a13fbf1010 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Tue, 7 Apr 2020 01:32:58 -0700 Subject: [PATCH] fix execution policy parser to not interfere with legit integers, and add tests (#8997) --- provisioner/powershell/execution_policy.go | 10 ++ provisioner/powershell/provisioner.go | 7 ++ provisioner/powershell/provisioner_test.go | 109 +++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/provisioner/powershell/execution_policy.go b/provisioner/powershell/execution_policy.go index 5941aba3c..c79b2f72c 100644 --- a/provisioner/powershell/execution_policy.go +++ b/provisioner/powershell/execution_policy.go @@ -4,6 +4,7 @@ package powershell import ( "reflect" + "strconv" ) // ExecutionPolicy setting to run the command(s). @@ -27,5 +28,14 @@ func StringToExecutionPolicyHook(f reflect.Kind, t reflect.Kind, data interface{ } raw := data.(string) + // It's possible that the thing being read is not supposed to be an + // execution policy; if the string provided is actally an int, just return + // the int. + i, err := strconv.Atoi(raw) + if err == nil { + return i, nil + } + // If it can't just be cast to an int, try to parse string into an + // execution policy. return ExecutionPolicyString(raw) } diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 679f99c13..fb8083134 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -188,6 +188,13 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } } + if p.config.ExecutionPolicy > 7 { + errs = packer.MultiErrorAppend(errs, fmt.Errorf(`Invalid execution `+ + `policy provided. Please supply one of: "bypass", "allsigned",`+ + ` "default", "remotesigned", "restricted", "undefined", `+ + `"unrestricted", "none".`)) + } + if errs != nil { return errs } diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 152905bb8..edd05c096 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -3,6 +3,7 @@ package powershell import ( "bytes" "context" + "fmt" "io/ioutil" "os" "regexp" @@ -11,6 +12,7 @@ import ( "time" "github.com/hashicorp/packer/packer" + "github.com/stretchr/testify/assert" ) func testConfig() map[string]interface{} { @@ -564,6 +566,113 @@ func TestProvisioner_createFlattenedElevatedEnvVars_windows(t *testing.T) { } } +func TestProvisionerCorrectlyInterpolatesValidExitCodes(t *testing.T) { + type testCases struct { + Input interface{} + Expected []int + } + validExitCodeTests := []testCases{ + {"0", []int{0}}, + {[]string{"0"}, []int{0}}, + {[]int{0, 12345}, []int{0, 12345}}, + {[]string{"0", "12345"}, []int{0, 12345}}, + {"0,12345", []int{0, 12345}}, + } + + for _, tc := range validExitCodeTests { + p := new(Provisioner) + config := testConfig() + config["valid_exit_codes"] = tc.Input + err := p.Prepare(config) + + if err != nil { + t.Fatalf("Shouldn't have had error interpolating exit codes") + } + assert.ElementsMatchf(t, p.config.ValidExitCodes, tc.Expected, + fmt.Sprintf("expected exit codes to be: %#v, got %#v.", p.config.ValidExitCodes, tc.Expected)) + } +} + +func TestProvisionerCorrectlyInterpolatesExecutionPolicy(t *testing.T) { + type testCases struct { + Input interface{} + Expected ExecutionPolicy + ErrExpected bool + } + tests := []testCases{ + { + Input: "bypass", + Expected: ExecutionPolicy(0), + ErrExpected: false, + }, + { + Input: "allsigned", + Expected: ExecutionPolicy(1), + ErrExpected: false, + }, + { + Input: "default", + Expected: ExecutionPolicy(2), + ErrExpected: false, + }, + { + Input: "remotesigned", + Expected: ExecutionPolicy(3), + ErrExpected: false, + }, + { + Input: "restricted", + Expected: ExecutionPolicy(4), + ErrExpected: false, + }, + { + Input: "undefined", + Expected: ExecutionPolicy(5), + ErrExpected: false, + }, + { + Input: "unrestricted", + Expected: ExecutionPolicy(6), + ErrExpected: false, + }, + { + Input: "none", + Expected: ExecutionPolicy(7), + ErrExpected: false, + }, + { + Input: "0", // User can supply a valid number for policy, too + Expected: 0, + ErrExpected: false, + }, + { + Input: "invalid", + Expected: 0, + ErrExpected: true, + }, + { + Input: "100", // If number is invalid policy, reject. + Expected: 100, + ErrExpected: true, + }, + } + + for _, tc := range tests { + p := new(Provisioner) + config := testConfig() + config["execution_policy"] = tc.Input + err := p.Prepare(config) + + if (err != nil) != tc.ErrExpected { + t.Fatalf("Either err was expected, or shouldn't have happened: %#v", tc) + } + if err == nil { + assert.Equal(t, p.config.ExecutionPolicy, tc.Expected, + fmt.Sprintf("expected %#v, got %#v.", p.config.ExecutionPolicy, tc.Expected)) + } + } +} + func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) { var flattenedEnvVars string config := testConfig()