diff --git a/src/runner.go b/src/runner.go index e1553c7..d70c773 100644 --- a/src/runner.go +++ b/src/runner.go @@ -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! @@ -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") @@ -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) @@ -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 "" diff --git a/src/runner_test.go b/src/runner_test.go index 31c48c8..d43f178 100644 --- a/src/runner_test.go +++ b/src/runner_test.go @@ -2,6 +2,7 @@ package main import ( "os" + "os/exec" "testing" ) @@ -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 variabes 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...)) + } + }) + } +}