From 613f7ef4a556fcc2f29c2e07ba60e7c133a0f40d Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Wed, 7 Aug 2019 08:47:29 -0400 Subject: [PATCH] client template configuration for file sandboxing --- .../taskrunner/template/template.go | 9 ++-- client/config/config.go | 53 +++++++++++-------- command/agent/agent.go | 3 +- command/agent/config.go | 32 ++++++++--- command/agent/config_test.go | 38 +++++++------ .../source/docs/configuration/client.html.md | 20 +++++-- 6 files changed, 99 insertions(+), 56 deletions(-) diff --git a/client/allocrunner/taskrunner/template/template.go b/client/allocrunner/taskrunner/template/template.go index 9e0da3835444..e22bea0ce4b4 100644 --- a/client/allocrunner/taskrunner/template/template.go +++ b/client/allocrunner/taskrunner/template/template.go @@ -573,12 +573,9 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[*ctconf.Templa ct.Contents = &tmpl.EmbeddedTmpl 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"} + ct.FunctionBlacklist = config.ClientConfig.TemplateConfig.FunctionBlacklist + if !config.ClientConfig.TemplateConfig.DisableSandbox { + ct.SandboxPath = &config.TaskDir } // Set the permissions diff --git a/client/config/config.go b/client/config/config.go index b33d91d34e93..e8c2d7db0944 100644 --- a/client/config/config.go +++ b/client/config/config.go @@ -201,9 +201,8 @@ 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 + // TemplateConfig includes configuration for template rendering + TemplateConfig *ClientTemplateConfig // BackwardsCompatibleMetrics determines whether to show methods of // displaying metrics for older versions, or to only show the new format @@ -252,6 +251,11 @@ type Config struct { AutoFetchCNIDir string } +type ClientTemplateConfig struct { + FunctionBlacklist []string + DisableSandbox bool +} + func (c *Config) Copy() *Config { nc := new(Config) *nc = *c @@ -266,26 +270,29 @@ 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, - EnableInsecureTemplateFunctions: 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, + TemplateConfig: &ClientTemplateConfig{ + FunctionBlacklist: []string{"plugin"}, + DisableSandbox: false, + }, + BackwardsCompatibleMetrics: false, + RPCHoldTimeout: 5 * time.Second, + AutoFetchCNI: false, } } diff --git a/command/agent/agent.go b/command/agent/agent.go index f5a40317604d..036feb5d8e70 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -469,7 +469,8 @@ 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 + conf.TemplateConfig.FunctionBlacklist = agentConfig.Client.TemplateConfig.FunctionBlacklist + conf.TemplateConfig.DisableSandbox = agentConfig.Client.TemplateConfig.DisableSandbox // Setup the node conf.Node = new(structs.Node) diff --git a/command/agent/config.go b/command/agent/config.go index d8bce6db450b..f7838ecfd7b5 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -242,9 +242,8 @@ 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"` + // TemplateConfig includes configuration for template rendering + TemplateConfig *ClientTemplateConfig `hcl:"template"` // ServerJoin contains information that is used to attempt to join servers ServerJoin *ServerJoin `hcl:"server_join"` @@ -276,6 +275,20 @@ type ClientConfig struct { AutoFetchCNIPluginsURL string `hcl:"auto_fetch_cni_plugins_url"` } +// ClientTemplateConfig is configuration on the client specific to template +// rendering +type ClientTemplateConfig struct { + + // FunctionBlacklist disables functions in consul-template that + // are unsafe because they expose information from the client host. + FunctionBlacklist []string `hcl:"function_blacklist"` + + // DisableSandbox allows templates to access arbitrary files on the + // client host. By default templates can access files only within + // the task directory. + DisableSandbox bool `hcl:"disable_file_sandbox"` +} + // ACLConfig is configuration specific to the ACL system type ACLConfig struct { // Enabled controls if we are enforce and manage ACLs @@ -685,7 +698,10 @@ func DevConfig() *Config { conf.Client.GCDiskUsageThreshold = 99 conf.Client.GCInodeUsageThreshold = 99 conf.Client.GCMaxAllocs = 50 - conf.Client.EnableInsecureTemplateFunctions = false + conf.Client.TemplateConfig = &ClientTemplateConfig{ + FunctionBlacklist: []string{"plugin"}, + DisableSandbox: false, + } conf.Telemetry.PrometheusMetrics = true conf.Telemetry.PublishAllocationMetrics = true conf.Telemetry.PublishNodeMetrics = true @@ -728,6 +744,10 @@ func DefaultConfig() *Config { RetryInterval: 30 * time.Second, RetryMaxAttempts: 0, }, + TemplateConfig: &ClientTemplateConfig{ + FunctionBlacklist: []string{"plugin"}, + DisableSandbox: false, + }, }, Server: &ServerConfig{ Enabled: false, @@ -1307,8 +1327,8 @@ func (a *ClientConfig) Merge(b *ClientConfig) *ClientConfig { result.DisableRemoteExec = b.DisableRemoteExec } - if b.EnableInsecureTemplateFunctions { - result.EnableInsecureTemplateFunctions = true + if b.TemplateConfig != nil { + result.TemplateConfig = b.TemplateConfig } // Add the servers diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 827f5670ccf2..d5d49bc4be5e 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -88,13 +88,16 @@ func TestConfig_Merge(t *testing.T) { Options: map[string]string{ "foo": "bar", }, - NetworkSpeed: 100, - CpuCompute: 100, - MemoryMB: 100, - MaxKillTimeout: "20s", - ClientMaxPort: 19996, - DisableRemoteExec: false, - EnableInsecureTemplateFunctions: true, + NetworkSpeed: 100, + CpuCompute: 100, + MemoryMB: 100, + MaxKillTimeout: "20s", + ClientMaxPort: 19996, + DisableRemoteExec: false, + TemplateConfig: &ClientTemplateConfig{ + FunctionBlacklist: []string{"plugin"}, + DisableSandbox: false, + }, Reserved: &Resources{ CPU: 10, MemoryMB: 10, @@ -246,15 +249,18 @@ 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, - EnableInsecureTemplateFunctions: true, + ChrootEnv: map[string]string{}, + ClientMaxPort: 20000, + ClientMinPort: 22000, + NetworkSpeed: 105, + CpuCompute: 105, + MemoryMB: 105, + MaxKillTimeout: "50s", + DisableRemoteExec: false, + TemplateConfig: &ClientTemplateConfig{ + FunctionBlacklist: []string{"plugin"}, + DisableSandbox: false, + }, 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 97fda5d1902e..1ac522d572a4 100644 --- a/website/source/docs/configuration/client.html.md +++ b/website/source/docs/configuration/client.html.md @@ -58,10 +58,6 @@ 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. @@ -151,6 +147,10 @@ driver) but will be removed in a future release. - `bridge_network_subnet` `(string: "172.26.66.0/23")` - Specifies the subnet which the client will use to allocate IP addresses from. +- `template` ([Template](#template-parameters): nil) - Specifies + controls on the behavior of task [`template`](/docs/job-specification/template.html) stanzas. + + ### `chroot_env` Parameters Drivers based on [isolated fork/exec](/docs/drivers/exec.html) implement file @@ -333,6 +333,18 @@ see the [drivers documentation](/docs/drivers/index.html). reserve on all fingerprinted network devices. Ranges can be specified by using a hyphen separated the two inclusive ends. + +### `template` Parameters + +- `function_blacklist` `([]string: ["plugin"])` - Specifies a list of template + rendering functions that should be disallowed in job specs because they can + leak information from the client host to templates. + +- `disable_file_sandbox` `(bool: false)` - Allows templates access to arbitrary + files on the client host via the `file` function. By default templates can + access files only within the task directory. + + ## `client` Examples ### Common Setup