From 708d50513480b876f2520d4e5c3dfa01fdc1f748 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Fri, 13 Sep 2024 10:18:27 +0545 Subject: [PATCH] feat: hide os shell envs --- shell/shell.go | 10 ++++-- shell/shell_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 shell/shell_test.go diff --git a/shell/shell.go b/shell/shell.go index a57fdae4..c618edec 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -38,14 +38,16 @@ type Artifact struct { } type ExecDetails struct { - Error error `json:"-"` Stdout string `json:"stdout"` Stderr string `json:"stderr"` ExitCode int `json:"exitCode"` Path string `json:"path"` Args []string `json:"args"` + // Any extra details about the command execution, e.g. git commit id, etc. - Extra map[string]any `json:"extra,omitempty"` + Extra map[string]any `json:"extra,omitempty"` + + Error error `json:"-" yaml:"-"` Artifacts []artifacts.Artifact `json:"-" yaml:"-"` } @@ -72,9 +74,11 @@ func Run(ctx context.Context, exec Exec) (*ExecDetails, error) { return nil, ctx.Oops().Wrap(err) } + // Set to a non-nil empty slice to prevent access to current environment variables + cmd.Env = []string{} if len(envParams.envs) != 0 { ctx.Logger.V(6).Infof("using environment %s", logger.Pretty(envParams.envs)) - cmd.Env = append(os.Environ(), envParams.envs...) + cmd.Env = append(cmd.Env, envParams.envs...) } if envParams.mountPoint != "" { diff --git a/shell/shell_test.go b/shell/shell_test.go new file mode 100644 index 00000000..f9efc192 --- /dev/null +++ b/shell/shell_test.go @@ -0,0 +1,77 @@ +package shell + +import ( + "strings" + "testing" + + "github.com/flanksource/duty/context" + "github.com/flanksource/duty/types" + "github.com/samber/lo" +) + +func TestEnv(t *testing.T) { + testData := []struct { + name string + exec Exec + expectedVars []string + }{ + { + name: "access custom env vars", + exec: Exec{ + Script: "env", + EnvVars: []types.EnvVar{ + {Name: "mc_test_secret", ValueStatic: "abcdef"}, + }, + }, + expectedVars: []string{"mc_test_secret=abcdef"}, + }, + { + name: "access multiple custom env vars", + exec: Exec{ + Script: "env", + EnvVars: []types.EnvVar{ + {Name: "mc_test_secret_key", ValueStatic: "abc"}, + {Name: "mc_test_secret_id", ValueStatic: "xyz"}, + }, + }, + expectedVars: []string{"mc_test_secret_key=abc", "mc_test_secret_id=xyz"}, + }, + { + name: "no access to process env", + exec: Exec{ + Script: "env", + }, + expectedVars: []string{}, + }, + } + + ctx := context.New() + for _, td := range testData { + t.Run(td.name, func(t *testing.T) { + result, err := Run(ctx, td.exec) + if err != nil { + t.Fatalf("failed to run command %s", err) + } + + if result.ExitCode != 0 { + t.Errorf("unexpected non-zero exit code: %d", result.ExitCode) + } + + if result.Stderr != "" { + t.Errorf("unexpected stderr: %s", result.Stderr) + } + + envVars := strings.Split(result.Stdout, "\n") + + // These env vars are always made available. + envVars = lo.Filter(envVars, func(v string, _ int) bool { + key, _, _ := strings.Cut(v, "=") + return key != "PWD" && key != "SHLVL" && key != "_" + }) + + if !lo.Every(envVars, td.expectedVars) || !lo.Every(td.expectedVars, envVars) { + t.Errorf("expected %s, got %s", td.expectedVars, envVars) + } + }) + } +}