Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

override consul-template blacklist configuration #6075

Merged
merged 2 commits into from
Aug 12, 2019

Conversation

tgross
Copy link
Member

@tgross tgross commented Aug 5, 2019

By default consul-template allows any template rendering function it supports to be used. This PR drops the plugin and file functions by default for Nomad templates. Includes:

@tgross
Copy link
Member Author

tgross commented Aug 5, 2019

(I seemed to have screwed something up in the vendoring of the updated consul-template here so it's failing CI. Let me fix that 😊 )

@tgross tgross force-pushed the b-template-func-blacklist branch 2 times, most recently from 55fe5b7 to 6b07846 Compare August 5, 2019 20:57
// 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line and the change to the documentation suggest that this is supposed to be in the client config, but the change to the parsing show it in the top-level config. as such, right now it's not possible to change this to a non-default value of true.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, thanks for catching that.

@@ -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"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to move below into ClientConfig

Copy link
Contributor

@cgbaker cgbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verified that this is working in the protective sense... the error message returned by consul-template in the allocation status is somewhat unpleasant, although it gets the point across:

2019-08-05T21:01:46Z Killing Template failed: (dynamic): execute: template: :1:3: executing "" at <file "/tmp/foo">: error calling file: function is disabled

config parsing means that this protection cannot currently be disabled. otherwise, looks good to me.

@jippi
Copy link
Contributor

jippi commented Aug 6, 2019

Can we make this a feature flag? Especially for file, there is plenty of use-cases in the world where a template is kinda like this

template {
    destination = "pki.json"
    data = <<<EOF
{{ with secret "pki/issue/my-domain-dot-com" "common_name=foo.example.com" }}
{{ .Data | toJSON }}{{ end }}
EOF;
}

template {
    destination = "certificate.tls"
    data = <<<EOF
{{ file "pki.json" | parseJSON | .certificate }}
EOF;
}

template {
    destination = "stuff.tls"
    data = <<<EOF
{{ file "pki.json" | parseJSON | .other_field }}
EOF;
}

I wonder if a better long term fix would be to provide a list of folders where file would be allowed to read from, and default to /local - since it's very all-or-nothing breaking a safe-common pattern without being able to be protected from the root cause that made you implement this whitelisting of functions

For example, I would like to disable plugin but not file - current implementation do not allow for that

// 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would like to be able to disable plugin but keep file around - maybe expose a []string for the functions I want to blacklist manually as well?

Copy link
Contributor

@cgbaker cgbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i still can't reproduce the previous behavior with enable_insecure_template_functions = true, it looks like there is some conversion needed in:

func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) {

@tgross tgross force-pushed the b-template-func-blacklist branch from 3729c72 to 8608e30 Compare August 6, 2019 18:10
@tgross
Copy link
Member Author

tgross commented Aug 6, 2019

@cgbaker I'm still working on this but in the meantime I believe I've fixed the configuration problem at this point. If I build the current PR as make dev and use the following configuration file:

bind_addr = "0.0.0.0"
data_dir = "/tmp/nomad"
log_level = "DEBUG"

server {
  enabled = true
  bootstrap_expect = 1
}

client {
  enabled = true
  enable_insecure_template_functions = true
}

I can confirm the correct behavior when I toggle our boolean value.

Copy link
Contributor

@cgbaker cgbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@tgross
Copy link
Member Author

tgross commented Aug 6, 2019

Can we make this a feature flag?

Hello @jippi, thanks for your feedback on this! When I worked on this I had the same concern you do here that some operators would want to be able to be more selective about what functions they disallow. There’s a bit of a trade-off to make between configuration complexity and secure defaults. That being said, after seeing your example and having some other discussions I think I'm leaning towards having a more fine-grained control.

I wonder if a better long term fix would be to provide a list of folders where file would be allowed to read from, and default to /local - since it’s very all-or-nothing breaking a safe-common pattern without being able to be protected from the root cause that made you implement this whitelisting of functions

I would definitely like to see this myself! If we could sandbox consul-template to the same context as the task we wouldn’t really need to worry about the file function at all. But existing running jobs will be broken if we change the behavior, so we'll need to consider how to do this. I'm chatting with one of the consul-template developers about how the best way forward on that.

@tgross
Copy link
Member Author

tgross commented Aug 7, 2019

Just pushed a set of commits leveraging the work done in this draft PR hashicorp/consul-template#1249 for discussion. Demo of what this looks like:


default.hcl

bind_addr = "0.0.0.0"
data_dir = "/tmp/nomad"
log_level = "DEBUG"

server {
  enabled = true
  bootstrap_expect = 1
}

client {
  enabled = true
  template {
    function_blacklist = ["plugin"]
    disable_sandbox = false
  }
}

file-leak.nomad

job "example" {
  datacenters = ["dc1"]

  type = "service"

  group "cache" {
    count = 1

    task "redis" {
      driver = "docker"
      config {
        image = "redis:3.2"
        port_map {
          db = 6379
        }
      }
      resources {
        cpu    = 500 # 500 MHz
        memory = 256 # 256MB
        network {
          mbits = 10
          port "db" {}
        }
      }


      template {
        data          = "{{ file \"/etc/passwd\" }}"
        destination   = "local/file.yml"
      }
    }
  }
}

output:

    2019/08/07 11:24:04.940971 [ERR] (runner) watcher reported error: file(/tmp/nomad/alloc/a6dc1786-2e98-3fcf-7029-a24a97ab0ec6/redis/etc/passwd): stat /tmp/nomad/alloc/a6dc1786-2e98-3fcf-7029-a24a97ab0ec6/redis/etc/passwd: no such file or directory

@tgross tgross force-pushed the b-template-func-blacklist branch 2 times, most recently from e3ef88b to c4dfc5b Compare August 8, 2019 13:28
@tgross tgross added this to the 0.9.5 milestone Aug 8, 2019
@tgross
Copy link
Member Author

tgross commented Aug 8, 2019

We're getting a lot of timeouts on Travis builds here. I've opened #6094 to help mitigate some of that.

@tgross tgross force-pushed the b-template-func-blacklist branch from c4dfc5b to 613f7ef Compare August 8, 2019 18:36
@tgross
Copy link
Member Author

tgross commented Aug 8, 2019

@cgbaker @jippi I think I'm happy with where this has landed at this point. The configuration values and their defaults are:

client {
  template {
    function_blacklist = ["plugin"]
    disable_file_sandbox = false
  }
}

Although I know @jippi mentioned wanting to sandbox tasks to specific directories outside the task directory, we're going to punt on that for now and have a flag to disable the sandbox. We can return to this in later work and see if it makes sense to include, but we need the all-or-nothing flag for backwards compatibility. For now, this new configuration gives folks a bunch of different options depending on the level of protection they need:

  • function_blacklist = ["file", "plugin"]: disable the file function entirely
  • disable_file_sandbox = true: allow the file function and allow it access to arbitrary files on the client
  • disable_file_sandbox = false + docker { volume ...: use a docker bind mount to include specific files from the client into the task directory sandbox where the file function can read them.
  • disable_file_sandbox = false + docker volumes enabled=false: disallow docker bind mounts and sandbox the file function to the task directory.

What do we think?

@tgross tgross force-pushed the b-template-func-blacklist branch 2 times, most recently from 17e841d to e4b29e6 Compare August 8, 2019 19:38
@tgross
Copy link
Member Author

tgross commented Aug 8, 2019

Rebased this on master to pick up #6095 and hopefully bring test run times down.


- `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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"leak information" is too weak to describe plugin, so maybe we should expand with:

By default the plugin function is disallowed as it allows running arbitrary commands on the host as root (unless Nomad is configured to run as a non-root user).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@tgross
Copy link
Member Author

tgross commented Aug 9, 2019

Looks like we can avoid breaking existing uses of NOMAD_TASK_DIR in the file parameter of templates if we use the patch to consul-template in hashicorp/consul-template#1254.

@tgross tgross force-pushed the b-template-func-blacklist branch from bdafd59 to 9aa45a0 Compare August 9, 2019 19:42
@tgross tgross force-pushed the b-template-func-blacklist branch 2 times, most recently from cf5b484 to b932883 Compare August 12, 2019 15:03
@tgross tgross force-pushed the b-template-func-blacklist branch from b932883 to b61ced1 Compare August 12, 2019 18:40
Copy link
Contributor

@notnoop notnoop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm - but would be good to remove burstsushi casing.

vendor/vendor.json Show resolved Hide resolved
pulls in configuration option for blacklisting template functions from:
hashicorp/consul-template#1243
hashicorp/consul-template#1246

pulls in configuration option for file sandboxing from:
hashicorp/consul-template#1249
hashicorp/consul-template#1254

pulls in vault KVv2 read fixes from:
hashicorp/consul-template#1253
@tgross tgross force-pushed the b-template-func-blacklist branch from b61ced1 to c48f2f7 Compare August 12, 2019 18:48
When rendering a task template, the `plugin` function is no longer
permitted by default and will raise an error. An operator can opt-in
to permitting this function with the new `template.function_blacklist`
field in the client configuration.

When rendering a task template, path parameters for the `file`
function will be treated as relative to the task directory by
default. Relative paths or symlinks that point outside the task
directory will raise an error. An operator can opt-out of this
protection with the new `template.disable_file_sandbox` field in the
client configuration.
@tgross tgross force-pushed the b-template-func-blacklist branch from c48f2f7 to af389da Compare August 12, 2019 20:02
@tgross tgross merged commit ffb83e1 into master Aug 12, 2019
@tgross tgross deleted the b-template-func-blacklist branch August 12, 2019 20:34
@tgross
Copy link
Member Author

tgross commented Aug 12, 2019

This work has been cherry-picked into the release-095 branch.

@github-actions
Copy link

github-actions bot commented Feb 5, 2023

I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants