Skip to content

Commit

Permalink
Render consul templates using task env only
Browse files Browse the repository at this point in the history
When rendering a task consul template, ensure that only task environment
variables are used.

Currently, `consul-template` always falls back to host process
environment variables when key isn't a task env var[1].  Thus, we add
an empty entry for each host process env-var not found in task env-vars.

[1] https://github.com/hashicorp/consul-template/blob/bfa5d0e133688920afd1e012404f765182e3d5e0/template/funcs.go#L61-L75
  • Loading branch information
Mahmood Ali committed Aug 1, 2019
1 parent 19cdfb6 commit 8db90fc
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
16 changes: 15 additions & 1 deletion client/allocrunner/taskrunner/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ func templateRunner(config *TaskTemplateManagerConfig) (
}

// Set Nomad's environment variables
runner.Env = config.EnvBuilder.Build().All()
runner.Env = maskProcessEnv(config.EnvBuilder.Build().All())

// Build the lookup
idMap := runner.TemplateConfigMapping()
Expand All @@ -525,6 +525,20 @@ func templateRunner(config *TaskTemplateManagerConfig) (
return runner, lookup, nil
}

// maskProcessEnv masks away any environment variable not found in task env.
// It manipulates the parameter directly and returns it without copying.
func maskProcessEnv(env map[string]string) map[string]string {
procEnvs := os.Environ()
for _, e := range procEnvs {
ekv := strings.SplitN(e, "=", 2)
if _, ok := env[ekv[0]]; !ok {
env[ekv[0]] = ""
}
}

return env
}

// parseTemplateConfigs converts the tasks templates in the config into
// consul-templates
func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.TemplateConfig]*structs.Template, error) {
Expand Down
47 changes: 47 additions & 0 deletions client/allocrunner/taskrunner/template/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/taskenv"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
sconfig "github.com/hashicorp/nomad/nomad/structs/config"
Expand Down Expand Up @@ -1022,6 +1023,52 @@ func TestTaskTemplateManager_Signal_Error(t *testing.T) {
require.Contains(harness.mockHooks.KillEvent.DisplayMessage, "failed to send signals")
}

// TestTaskTemplateManager_FiltersProcessEnvVars asserts that we only render
// environment variables found in task env-vars and not read the nomad host
// process environment variables. nomad host process environment variables
// are to be treated the same as not found environment variables.
func TestTaskTemplateManager_FiltersEnvVars(t *testing.T) {
t.Parallel()

defer os.Setenv("NOMAD_TASK_NAME", os.Getenv("NOMAD_TASK_NAME"))
os.Setenv("NOMAD_TASK_NAME", "should be overriden by task")

testenv := "TESTENV_" + strings.ReplaceAll(uuid.Generate(), "-", "")
os.Setenv(testenv, "MY_TEST_VALUE")
defer os.Unsetenv(testenv)

// Make a template that will render immediately
content := `Hello Nomad Task: {{env "NOMAD_TASK_NAME"}}
TEST_ENV: {{ env "` + testenv + `" }}
TEST_ENV_NOT_FOUND: {{env "` + testenv + `_NOTFOUND" }}`
expected := fmt.Sprintf("Hello Nomad Task: %s\nTEST_ENV: \nTEST_ENV_NOT_FOUND: ", TestTaskName)

file := "my.tmpl"
template := &structs.Template{
EmbeddedTmpl: content,
DestPath: file,
ChangeMode: structs.TemplateChangeModeNoop,
}

harness := newTestHarness(t, []*structs.Template{template}, false, false)
harness.start(t)
defer harness.stop()

// Wait for the unblock
select {
case <-harness.mockHooks.UnblockCh:
case <-time.After(time.Duration(5*testutil.TestMultiplier()) * time.Second):
require.Fail(t, "Task unblock should have been called")
}

// Check the file is there
path := filepath.Join(harness.taskDir, file)
raw, err := ioutil.ReadFile(path)
require.NoError(t, err)

require.Equal(t, expected, string(raw))
}

// TestTaskTemplateManager_Env asserts templates with the env flag set are read
// into the task's environment.
func TestTaskTemplateManager_Env(t *testing.T) {
Expand Down

0 comments on commit 8db90fc

Please sign in to comment.