From 6b0784687fe941069db5facb313a35d09a59c4a6 Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Fri, 2 Aug 2019 15:20:14 -0400 Subject: [PATCH] override consul-template blacklist configuration Includes agent-level configuration option for enabling rendering w/ insecure template functions. --- .../taskrunner/template/template.go | 17 +++-- client/config/config.go | 43 +++++++------ command/agent/config.go | 8 +++ command/agent/config_test.go | 62 ++++++++++--------- .../source/docs/configuration/client.html.md | 4 ++ 5 files changed, 80 insertions(+), 54 deletions(-) diff --git a/client/allocrunner/taskrunner/template/template.go b/client/allocrunner/taskrunner/template/template.go index fe1338c40b9..9e0da383544 100644 --- a/client/allocrunner/taskrunner/template/template.go +++ b/client/allocrunner/taskrunner/template/template.go @@ -545,11 +545,11 @@ func maskProcessEnv(env map[string]string) map[string]string { // parseTemplateConfigs converts the tasks templates in the config into // consul-templates -func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.TemplateConfig]*structs.Template, error) { +func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[*ctconf.TemplateConfig]*structs.Template, error) { allowAbs := config.ClientConfig.ReadBoolDefault(hostSrcOption, true) taskEnv := config.EnvBuilder.Build() - ctmpls := make(map[ctconf.TemplateConfig]*structs.Template, len(config.Templates)) + ctmpls := make(map[*ctconf.TemplateConfig]*structs.Template, len(config.Templates)) for _, tmpl := range config.Templates { var src, dest string if tmpl.SourcePath != "" { @@ -574,6 +574,13 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.Templat ct.LeftDelim = &tmpl.LeftDelim ct.RightDelim = &tmpl.RightDelim + // By default we pass a blacklist of functions to prevent + // task operators from bypassing client-task isolation. + // This protection can be disabled by the client config. + if !config.ClientConfig.EnableInsecureTemplateFunctions { + ct.FunctionBlacklist = []string{"plugin", "file"} + } + // Set the permissions if tmpl.Perms != "" { v, err := strconv.ParseUint(tmpl.Perms, 8, 12) @@ -585,7 +592,7 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.Templat } ct.Finalize() - ctmpls[*ct] = tmpl + ctmpls[ct] = tmpl } return ctmpls, nil @@ -594,7 +601,7 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.Templat // newRunnerConfig returns a consul-template runner configuration, setting the // Vault and Consul configurations based on the clients configs. func newRunnerConfig(config *TaskTemplateManagerConfig, - templateMapping map[ctconf.TemplateConfig]*structs.Template) (*ctconf.Config, error) { + templateMapping map[*ctconf.TemplateConfig]*structs.Template) (*ctconf.Config, error) { cc := config.ClientConfig conf := ctconf.DefaultConfig() @@ -603,7 +610,7 @@ func newRunnerConfig(config *TaskTemplateManagerConfig, flat := ctconf.TemplateConfigs(make([]*ctconf.TemplateConfig, 0, len(templateMapping))) for ctmpl := range templateMapping { local := ctmpl - flat = append(flat, &local) + flat = append(flat, local) } conf.Templates = &flat diff --git a/client/config/config.go b/client/config/config.go index 06bc96d4b9f..b33d91d34e9 100644 --- a/client/config/config.go +++ b/client/config/config.go @@ -201,6 +201,10 @@ type Config struct { // DisableRemoteExec disables remote exec targeting tasks on this client DisableRemoteExec bool + // EnableInsecureTemplateFunctions enables templates to include functions + // that are unsafe because they expose information from the client host. + EnableInsecureTemplateFunctions bool + // BackwardsCompatibleMetrics determines whether to show methods of // displaying metrics for older versions, or to only show the new format BackwardsCompatibleMetrics bool @@ -262,25 +266,26 @@ func (c *Config) Copy() *Config { // DefaultConfig returns the default configuration func DefaultConfig() *Config { return &Config{ - Version: version.GetVersion(), - VaultConfig: config.DefaultVaultConfig(), - ConsulConfig: config.DefaultConsulConfig(), - LogOutput: os.Stderr, - Region: "global", - StatsCollectionInterval: 1 * time.Second, - TLSConfig: &config.TLSConfig{}, - LogLevel: "DEBUG", - GCInterval: 1 * time.Minute, - GCParallelDestroys: 2, - GCDiskUsageThreshold: 80, - GCInodeUsageThreshold: 70, - GCMaxAllocs: 50, - NoHostUUID: true, - DisableTaggedMetrics: false, - DisableRemoteExec: false, - BackwardsCompatibleMetrics: false, - RPCHoldTimeout: 5 * time.Second, - AutoFetchCNI: false, + Version: version.GetVersion(), + VaultConfig: config.DefaultVaultConfig(), + ConsulConfig: config.DefaultConsulConfig(), + LogOutput: os.Stderr, + Region: "global", + StatsCollectionInterval: 1 * time.Second, + TLSConfig: &config.TLSConfig{}, + LogLevel: "DEBUG", + GCInterval: 1 * time.Minute, + GCParallelDestroys: 2, + GCDiskUsageThreshold: 80, + GCInodeUsageThreshold: 70, + GCMaxAllocs: 50, + NoHostUUID: true, + DisableTaggedMetrics: false, + DisableRemoteExec: false, + EnableInsecureTemplateFunctions: false, + BackwardsCompatibleMetrics: false, + RPCHoldTimeout: 5 * time.Second, + AutoFetchCNI: false, } } diff --git a/command/agent/config.go b/command/agent/config.go index 2f804855319..e3dc76e2e5c 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -108,6 +108,10 @@ type Config struct { // for security bulletins DisableAnonymousSignature bool `hcl:"disable_anonymous_signature"` + // EnableInsecureTemplateFunctions enables templates to include functions + // that are unsafe because they expose information from the client host. + EnableInsecureTemplateFunctions bool `hcl:"enable_insecure_template_functions"` + // Consul contains the configuration for the Consul Agent and // parameters necessary to register services, their checks, and // discover the current Nomad servers. @@ -667,6 +671,7 @@ func DevConfig() *Config { conf.DevMode = true conf.EnableDebug = true conf.DisableAnonymousSignature = true + conf.EnableInsecureTemplateFunctions = false conf.Consul.AutoAdvertise = helper.BoolToPtr(true) if runtime.GOOS == "darwin" { conf.Client.NetworkInterface = "lo0" @@ -825,6 +830,9 @@ func (c *Config) Merge(b *Config) *Config { if b.DisableAnonymousSignature { result.DisableAnonymousSignature = true } + if b.EnableInsecureTemplateFunctions { + result.EnableInsecureTemplateFunctions = true + } // Apply the telemetry config if result.Telemetry == nil && b.Telemetry != nil { diff --git a/command/agent/config_test.go b/command/agent/config_test.go index d4fea75110a..5e497bc75d9 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -41,21 +41,22 @@ func TestConfig_Merge(t *testing.T) { } c2 := &Config{ - Region: "global", - Datacenter: "dc1", - NodeName: "node1", - DataDir: "/tmp/dir1", - PluginDir: "/tmp/pluginDir1", - LogLevel: "INFO", - LogJson: false, - EnableDebug: false, - LeaveOnInt: false, - LeaveOnTerm: false, - EnableSyslog: false, - SyslogFacility: "local0.info", - DisableUpdateCheck: helper.BoolToPtr(false), - DisableAnonymousSignature: false, - BindAddr: "127.0.0.1", + Region: "global", + Datacenter: "dc1", + NodeName: "node1", + DataDir: "/tmp/dir1", + PluginDir: "/tmp/pluginDir1", + LogLevel: "INFO", + LogJson: false, + EnableDebug: false, + LeaveOnInt: false, + LeaveOnTerm: false, + EnableSyslog: false, + SyslogFacility: "local0.info", + DisableUpdateCheck: helper.BoolToPtr(false), + DisableAnonymousSignature: false, + EnableInsecureTemplateFunctions: true, + BindAddr: "127.0.0.1", Telemetry: &Telemetry{ StatsiteAddr: "127.0.0.1:8125", StatsdAddr: "127.0.0.1:8125", @@ -189,21 +190,22 @@ func TestConfig_Merge(t *testing.T) { } c3 := &Config{ - Region: "global", - Datacenter: "dc2", - NodeName: "node2", - DataDir: "/tmp/dir2", - PluginDir: "/tmp/pluginDir2", - LogLevel: "DEBUG", - LogJson: true, - EnableDebug: true, - LeaveOnInt: true, - LeaveOnTerm: true, - EnableSyslog: true, - SyslogFacility: "local0.debug", - DisableUpdateCheck: helper.BoolToPtr(true), - DisableAnonymousSignature: true, - BindAddr: "127.0.0.2", + Region: "global", + Datacenter: "dc2", + NodeName: "node2", + DataDir: "/tmp/dir2", + PluginDir: "/tmp/pluginDir2", + LogLevel: "DEBUG", + LogJson: true, + EnableDebug: true, + LeaveOnInt: true, + LeaveOnTerm: true, + EnableSyslog: true, + SyslogFacility: "local0.debug", + DisableUpdateCheck: helper.BoolToPtr(true), + DisableAnonymousSignature: true, + EnableInsecureTemplateFunctions: true, + BindAddr: "127.0.0.2", Telemetry: &Telemetry{ StatsiteAddr: "127.0.0.2:8125", StatsdAddr: "127.0.0.2:8125", diff --git a/website/source/docs/configuration/client.html.md b/website/source/docs/configuration/client.html.md index 8e50f53404c..97fda5d1902 100644 --- a/website/source/docs/configuration/client.html.md +++ b/website/source/docs/configuration/client.html.md @@ -58,6 +58,10 @@ driver) but will be removed in a future release. - `disable_remote_exec` `(bool: false)` - Specifies if the client should disable remote task execution to tasks running on this client. +- `enable_insecure_template_functions` `(bool: false)` - Specifies if the client + should enable template rendering functions that can leak information from the + client host to templates. + - `meta` `(map[string]string: nil)` - Specifies a key-value map that annotates with user-defined metadata.