From 8608e30095b3394bd45a6f5b44fdf5c74b6d7aca 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/agent.go | 1 + command/agent/config.go | 9 ++++ command/agent/config_test.go | 30 +++++++------ .../source/docs/configuration/client.html.md | 4 ++ 6 files changed, 66 insertions(+), 38 deletions(-) diff --git a/client/allocrunner/taskrunner/template/template.go b/client/allocrunner/taskrunner/template/template.go index fe1338c40b9c..9e0da3835444 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 06bc96d4b9f7..b33d91d34e93 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/agent.go b/command/agent/agent.go index 0b8ce9269563..f5a40317604d 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -469,6 +469,7 @@ func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) { conf.ClientMaxPort = uint(agentConfig.Client.ClientMaxPort) conf.ClientMinPort = uint(agentConfig.Client.ClientMinPort) conf.DisableRemoteExec = agentConfig.Client.DisableRemoteExec + conf.EnableInsecureTemplateFunctions = agentConfig.Client.EnableInsecureTemplateFunctions // Setup the node conf.Node = new(structs.Node) diff --git a/command/agent/config.go b/command/agent/config.go index 2f8048553192..d8bce6db450b 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -242,6 +242,10 @@ type ClientConfig struct { // DisableRemoteExec disables remote exec targeting tasks on this client DisableRemoteExec bool `hcl:"disable_remote_exec"` + // EnableInsecureTemplateFunctions enables templates to include functions + // that are unsafe because they expose information from the client host. + EnableInsecureTemplateFunctions bool `hcl:"enable_insecure_template_functions"` + // ServerJoin contains information that is used to attempt to join servers ServerJoin *ServerJoin `hcl:"server_join"` @@ -681,6 +685,7 @@ func DevConfig() *Config { conf.Client.GCDiskUsageThreshold = 99 conf.Client.GCInodeUsageThreshold = 99 conf.Client.GCMaxAllocs = 50 + conf.Client.EnableInsecureTemplateFunctions = false conf.Telemetry.PrometheusMetrics = true conf.Telemetry.PublishAllocationMetrics = true conf.Telemetry.PublishNodeMetrics = true @@ -1302,6 +1307,10 @@ func (a *ClientConfig) Merge(b *ClientConfig) *ClientConfig { result.DisableRemoteExec = b.DisableRemoteExec } + if b.EnableInsecureTemplateFunctions { + result.EnableInsecureTemplateFunctions = true + } + // Add the servers result.Servers = append(result.Servers, b.Servers...) diff --git a/command/agent/config_test.go b/command/agent/config_test.go index d4fea75110a3..827f5670ccf2 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -88,12 +88,13 @@ func TestConfig_Merge(t *testing.T) { Options: map[string]string{ "foo": "bar", }, - NetworkSpeed: 100, - CpuCompute: 100, - MemoryMB: 100, - MaxKillTimeout: "20s", - ClientMaxPort: 19996, - DisableRemoteExec: false, + NetworkSpeed: 100, + CpuCompute: 100, + MemoryMB: 100, + MaxKillTimeout: "20s", + ClientMaxPort: 19996, + DisableRemoteExec: false, + EnableInsecureTemplateFunctions: true, Reserved: &Resources{ CPU: 10, MemoryMB: 10, @@ -245,14 +246,15 @@ func TestConfig_Merge(t *testing.T) { "foo": "bar", "baz": "zip", }, - ChrootEnv: map[string]string{}, - ClientMaxPort: 20000, - ClientMinPort: 22000, - NetworkSpeed: 105, - CpuCompute: 105, - MemoryMB: 105, - MaxKillTimeout: "50s", - DisableRemoteExec: false, + ChrootEnv: map[string]string{}, + ClientMaxPort: 20000, + ClientMinPort: 22000, + NetworkSpeed: 105, + CpuCompute: 105, + MemoryMB: 105, + MaxKillTimeout: "50s", + DisableRemoteExec: false, + EnableInsecureTemplateFunctions: true, Reserved: &Resources{ CPU: 15, MemoryMB: 15, diff --git a/website/source/docs/configuration/client.html.md b/website/source/docs/configuration/client.html.md index 8e50f53404c4..97fda5d1902e 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.