diff --git a/internal/pkg/pdkshell/env_var.go b/internal/pkg/pdkshell/env_var.go new file mode 100644 index 00000000..b446b9b8 --- /dev/null +++ b/internal/pkg/pdkshell/env_var.go @@ -0,0 +1,51 @@ +package pdkshell + +import ( + "strings" + + "github.com/rs/zerolog/log" +) + +var osUtil osHelpers + +func init() { + osUtil = osHelpersImpl{} +} + +// There are a number of ENV VARs that need to be unset on POSIX systems before execution: +// https://github.com/puppetlabs/pdk-vanagon/blob/0aa54c9129b137c2deabb0a417d59215df36fd91/resources/files/posix/pdk_env_wrapper +func getEnvVarsToUnset() []string { + return []string{ + "GEM_HOME", + "GEM_PATH", + "DLN_LIBRARY_PATH", + "RUBYLIB", + "RUBYLIB_PREFIX", + "RUBYOPT", + "RUBYPATH", + "RUBYSHELL", + "LD_LIBRARY_PATH", + "LD_PRELOAD", + } +} + +func validEnvVar(envVar string) (valid bool) { + for _, illegalEnvVar := range getEnvVarsToUnset() { + if strings.HasPrefix(envVar, illegalEnvVar) { + log.Trace().Msgf("Dropping ENV VAR: %s", envVar) + return false + } + } + log.Trace().Msgf("Permitting ENV VAR: %s", envVar) + return true +} + +func getEnvironVars() []string { + env := []string{} + for _, envVar := range osUtil.Environ() { + if validEnvVar(envVar) { + env = append(env, envVar) + } + } + return env +} diff --git a/internal/pkg/pdkshell/env_var_test.go b/internal/pkg/pdkshell/env_var_test.go new file mode 100644 index 00000000..090ae4a1 --- /dev/null +++ b/internal/pkg/pdkshell/env_var_test.go @@ -0,0 +1,45 @@ +package pdkshell + +import ( + "reflect" + "testing" +) + +type osHelpersImplMock struct{} + +var mockedEnvironReturn []string + +func (osHelpersImplMock) Environ() []string { + return mockedEnvironReturn +} + +func Test_getEnvironVars(t *testing.T) { + + osUtil = osHelpersImplMock{} + + tests := []struct { + name string + mockedEnvironReturn []string + want []string + }{ + { + name: "Drops ENV VAR to unset and passes through permitted", + mockedEnvironReturn: []string{"GEM_HOME=/foo/bar", "VALID_VAR=/baz/qux"}, + want: []string{"VALID_VAR=/baz/qux"}, + }, + { + name: "Handles multiple instances of the same ENV VAR to be dropped", + mockedEnvironReturn: []string{"RUBYPATH=/foo/bar", "VALID_VAR=/baz/qux", "RUBYPATH=/foo/bar/bizz/buzz"}, + want: []string{"VALID_VAR=/baz/qux"}, + }, + } + + for _, tt := range tests { + mockedEnvironReturn = tt.mockedEnvironReturn + t.Run(tt.name, func(t *testing.T) { + if got := getEnvironVars(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("getEnvironVars() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/pkg/pdkshell/os_utils.go b/internal/pkg/pdkshell/os_utils.go new file mode 100644 index 00000000..3d934019 --- /dev/null +++ b/internal/pkg/pdkshell/os_utils.go @@ -0,0 +1,13 @@ +package pdkshell + +import "os" + +type osHelpers interface { + Environ() []string +} + +type osHelpersImpl struct{} + +func (osHelpersImpl) Environ() []string { + return os.Environ() +} diff --git a/internal/pkg/pdkshell/pdkshell.go b/internal/pkg/pdkshell/pdkshell.go index 673e7299..dbb8d083 100644 --- a/internal/pkg/pdkshell/pdkshell.go +++ b/internal/pkg/pdkshell/pdkshell.go @@ -26,7 +26,7 @@ func Execute(args []string) (int, error) { i := getPDKInfo() executable := buildExecutable(i.RubyExecutable) args = buildCommandArgs(args, i.RubyExecutable, i.PDKExecutable) - env := os.Environ() + env := getEnvironVars() env = append(env, fmt.Sprintf("SSL_CERT_DIR=%s", i.CertDirectory), fmt.Sprintf("SSL_CERT_FILE=%s", i.CertPemFile)) cmd := &exec.Cmd{ Path: executable, @@ -37,6 +37,8 @@ func Execute(args []string) (int, error) { Env: env, } + log.Trace().Msgf("PATH: %s", os.Getenv("PATH")) + log.Trace().Msgf("ENV: %s", env) log.Trace().Msgf("args: %s", args) if err := cmd.Run(); err != nil { log.Fatal().Msgf("pdk failed with '%s'\n", err)