Skip to content

Commit

Permalink
Use separate environment for every executed command
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Waltlova <[email protected]>
  • Loading branch information
andywaltlova committed Jul 31, 2023
1 parent 1050628 commit ed17941
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 24 deletions.
48 changes: 24 additions & 24 deletions src/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ func verifyYamlFile(yamlData []byte) bool {
return true
}

log.Infoln("Verifying yaml file...")
// --payload here will be a no-op because no upload is performed when using the verifier
// but, it will allow us to update the egg!

Expand Down Expand Up @@ -67,15 +66,31 @@ func verifyYamlFile(yamlData []byte) bool {
return true
}

func setEnvVariablesForCommand(cmd *exec.Cmd, variables map[string]string) *exec.Cmd {
// Set env variables
cmd.Env = os.Environ()
getEnvVarName := func(key string) string {
return fmt.Sprintf("RHC_WORKER_%s", strings.ToUpper(key))
}
for key, value := range variables {
prefixedKey := getEnvVarName(key)
envVarSetString := fmt.Sprintf("%s=%s", prefixedKey, value)
cmd.Env = append(cmd.Env, envVarSetString)
log.Infoln("Successfully set env variable ", envVarSetString)
}
return cmd
}

// Parses given yaml data.
// If signature is valid then extracts the bash script to temporary file,
// sets env variables if present and then runs the script.
// Return stdout of executed script or error message if the signature wasn't valid.
func processSignedScript(incomingContent []byte) string {
// Verify signature
log.Infoln("Verifying signature ...")
signatureIsValid := verifyYamlFile(incomingContent)
if !signatureIsValid {
errorMsg := "Signature of yaml file is invalid"
log.Errorln(errorMsg)
return errorMsg
}
log.Infoln("Signature of yaml file is valid")
Expand All @@ -88,25 +103,6 @@ func processSignedScript(incomingContent []byte) string {
return "Yaml couldn't be unmarshaled"
}

// Set env variables
getEnvVarName := func(key string) string {
return fmt.Sprintf("RHC_WORKER_%s", strings.ToUpper(key))
}
for key, value := range yamlContent.Vars.ContentVars {
prefixedKey := getEnvVarName(key)
err := os.Setenv(prefixedKey, value)
if err != nil {
log.Errorln(err)
} else {
log.Infoln("Successfully set env variable", prefixedKey, "=", value)
}
}
defer func() {
for key := range yamlContent.Vars.ContentVars {
os.Unsetenv(getEnvVarName(key))
}
}()

// NOTE: just debug to see the values
log.Debugln("Insights Signature:", yamlContent.Vars.InsightsSignature)
log.Debugln("Insights Signature Exclude:", yamlContent.Vars.InsightsSignatureExclude)
Expand All @@ -122,10 +118,14 @@ func processSignedScript(incomingContent []byte) string {
[]byte(yamlContent.Vars.Content), *config.TemporaryWorkerDirectory)
defer os.Remove(scriptFileName)

// Execute the script
log.Infoln("Executing bash script")
out, err := exec.Command("/bin/sh", scriptFileName).Output()
log.Infoln("Processing bash script ...")

// Execute script
log.Infoln("Executing bash script...")
cmd := exec.Command("/bin/sh", scriptFileName)
cmd = setEnvVariablesForCommand(cmd, yamlContent.Vars.ContentVars)

out, err := cmd.Output()
if err != nil {
log.Errorln("Failed to execute script: ", err)
return ""
Expand Down
76 changes: 76 additions & 0 deletions src/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"os"
"os/exec"
"testing"
)

Expand Down Expand Up @@ -87,3 +88,78 @@ func TestVerifyYamlFile(t *testing.T) {
t.Errorf("Expected %v, but got %v", expectedResult, result)
}
}

// Helper function to check if two string slices are equal
// NOTE: the == operator checks if both slices refer to the same underlying array, not if their elements are equal
func areStringSlicesEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}

func TestSetEnvVariablesForCommand(t *testing.T) {
testCases := []struct {
name string
variables map[string]string
expected []string
anotherCmdVariables map[string]string // Same variables with different values for another command
}{
{
name: "SettingVariables",
variables: map[string]string{
"VAR1": "value1",
"VAR2": "value2",
},
expected: []string{
"RHC_WORKER_VAR1=value1",
"RHC_WORKER_VAR2=value2",
},
anotherCmdVariables: map[string]string{
"VAR1": "another_value1",
},
},
{
name: "EmptyVariables",
variables: nil,
expected: nil, // Expect no changes to command's environment in this case
anotherCmdVariables: map[string]string{
"VAR2": "another_value2",
},
},
// Add more test cases as needed
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
originalEnv := os.Environ()
// Create the first dummy command
cmd := exec.Command("echo", "Hello, World!")
anotherCmd := exec.Command("echo", "Bye, World!")

// Call the functions to set env variables for the commands
setEnvVariablesForCommand(cmd, tc.variables)
setEnvVariablesForCommand(anotherCmd, tc.anotherCmdVariables)

// Check if the global environment variables are unchanged
if !areStringSlicesEqual(originalEnv, os.Environ()) {
t.Error("Global environment variables have been modified.")
}

// Check if the first command's environment variables have been set correctly
if !areStringSlicesEqual(cmd.Env, append(os.Environ(), tc.expected...)) {
t.Errorf("Command's environment variables are incorrect. Got: %v, Expected: %v", cmd.Env, append(os.Environ(), tc.expected...))
}

// Check if the second command's environment variables are NOT same as for first command
if areStringSlicesEqual(anotherCmd.Env, append(os.Environ(), tc.expected...)) {
t.Errorf("Command's environment variables are incorrect. Got: %v, Expected: %v", cmd.Env, append(os.Environ(), tc.expected...))
}
})
}
}

0 comments on commit ed17941

Please sign in to comment.