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

Add file and file_perms parameter to job's vault stanza #11905

Closed
wants to merge 2 commits into from

Conversation

grembo
Copy link
Contributor

@grembo grembo commented Jan 22, 2022

At the moment, secrets/vault_token is written using the nomad
process' umask, which - by default - is 0022, which results in
writing the vault_token world-readable (0644 / rw-r--r--).

This patch aims to address this by allowing to change the
permissions used from the default 666 (before umask).

The name file_perms was chosen to distinguish this from the
parameter perms in the template stanza (as templates always
operate on files, while Vault tokens are about permissions as
well, which would've been confusing otherwise).

Example of use:

vault {
    policies = ["nomad-tls-policy"]
    change_mode = "noop"
    file_perms = "600"
}

The patch also adds the file parameter, which controls if
secrets/vault_token is written at all.

The Vault token is always written to <task_dir>/private/vault_token,
private being a new directory to hold private secrets data not to be
shared with the chroot and also not to be shared with Nomad UI.

If file is set to true (the default), it is also written to
<task_dir>/secrets/vault_token, using the permissions configured
in file_perms.

There are two rationales for this design:

  1. Have one authoritative place where vault_token exists.
  2. Don't read vault_token from a place that operates on a lower
    security level on Nomad restart. Ultimately, secrets/vault_token
    could have been altered in unfortunate or malicious ways from within
    the chroot. This was the primary reason to add an additional write
    operation instead of just modifying tokenPath depending on the
    value of file.

Resolves #11900

At the moment, `/secrets/vault_token` is written using the nomad
process' umask, which - by default - is `0022`, which results in
writing the vault_token world-readable (`0644` / `rw-r--r--`).

This patch aims to address this by allowing to change the
permissions used from the default `666` (before umask).

The name `file_perms` was chosen to distinguish this from the
parameter `perms` in the `template` stanza (as templates always
operate on files, while Vault tokens are about permissions as
well, which would've been confusing otherwise).

Example of use:

    vault {
        policies = ["nomad-tls-policy"]
        change_mode = "noop"
        file_perms = "600"
    }

I tried to extend unit tests to include basic checks for the
feature, not sure if this is sufficient, though.

Resolves hashicorp#11900
@grembo
Copy link
Contributor Author

grembo commented Jan 22, 2022

A few force-pushes later the only failing test seems unrelated (and is marked FLAKY since Jan 12th):

TestAutopilot_RollingUpdate
1 test failed  out of 2304

This parameter controls whether the Vault token is actually
written to `secrets/vault_token`.

The Vault token is always written to `<task_dir>/private/vault_token`,
`private` being a new directory to hold private secrets data not to be
shared with the chroot and also not to be shared with Nomad UI.

If `file` is set to `true` (the default), it is also written to
`<task_dir>/secrets/vault_token`, using the permissions configured
in `file_perms`.

There are two rationales for this design:

1. Have one authoritative place where `vault_token` exists.
2. Don't read `vault_token` from a place that operates on a lower
   security level on Nomad restart. Ultimately, `secrets/vault_token`
   could have been altered in unfortunate or malicious ways from within
   the chroot. This was the primary reason to add an additional write
   operation instead of just modifying `tokenPath` depending on the
   value of `file`.

Open questions:
- Is creating a separate `private` directory worth the overhead?
@grembo grembo changed the title Add file_perms parameter to job's vault stanza Add file and file_perms parameter to job's vault stanza Jan 25, 2022
@grembo grembo changed the title Add file and file_perms parameter to job's vault stanza Add file and file_perms parameter to job's vault stanza Jan 25, 2022
@hashicorp-cla
Copy link

hashicorp-cla commented Mar 12, 2022

CLA assistant check
All committers have signed the CLA.

@grembo
Copy link
Contributor Author

grembo commented Mar 12, 2022

[![CLA assistant check]
Have you signed the CLA already but the status is still pending? Recheck it.

Hi @hashicorp-cla @lgfa29 @tgross,

I already signed the CLA in early January as part of #11783, so I don't think signing it again should be necessary.

Please see here for when I signed it.

Screenshot from #11783:
issue11783_signed_cla

The HashiCorp OAuth app still shows as authorized in my github settings:

authorized_auth_hashi

@tgross
Copy link
Member

tgross commented Mar 14, 2022

Sorry about that @grembo. The CLA bot went a bit wild over the weekend across all our repos. 😊 Should be fixed now.

@grembo
Copy link
Contributor Author

grembo commented May 31, 2022

@tgross Any updates on this?

In practice we ended up only using file = false, so we never store the vault token issued based on the vault stanza inside of the container. If the container requires a token, we issue it using a consul template stanza in the job description, which gives us full control over file permissions.

Based on this approach, we can issue all kinds of credentials (including vault tokens) to the container, without giving anything within the container the power to issue additional credentials itself, which is quite important to us.

So if it helps to move things forward, I could reduce this PR to only contain file (bool), which would still scratch out itch.

I can also share more about our setup, in case there are open questions.

@tgross
Copy link
Member

tgross commented May 31, 2022

@grembo sorry this never got marked for triage. I've marked it as such so that someone will take a look. At first glance I'm not sure this is the right approach. Why make the value configurable at all if you're putting the token in its own directory? I feel like this is handing operators a footgun.

@grembo
Copy link
Contributor Author

grembo commented May 31, 2022

@grembo sorry this never got marked for triage. I've marked it as such so that someone will take a look. At first glance I'm not sure this is the right approach. Why make the value configurable at all if you're putting the token in its own directory? I feel like this is handing operators a footgun.

@tgross Just to re-iterate the motivation: The goal is to store the token in a separate directory that is not accessible from inside the container.

If file is configured to true (the default), it is additionally written to /secrets inside of the container - the only reason I did this is so that the behavior of nomad would be backwards compatible, as this reflects the status quo of nomad, see also [0] for related thoughts on env.

If payload backwards compatibility is not an issue - ultimately, job definitions can probably be altered to mimic the current behavior - I would be totally happy to change the patch so that it only consists of nomad always writing the vault token to <task_dir>/private/vault_token without adding any configuration options to also copy it into the container, reducing the size of the patch considerably.

If some compatibility is required, changing file's (and potentially env's) default to false might present some middle-ground.


[0] Detour: This is also in line with nomad writing VAULT_TOKEN into the tasks environment, which has to be explicitly disabled by setting env = false in the vault stanza. With the current iteration if the patch, this is how our vault stanza looks like:

      vault {
        policies = ["tls-policy", "nomad-job-policy"]
        change_mode = "noop"
        env = false
        file = false
      }

which allows us to do things like:

      template {
        data = <<-EOH
          {{ with secret "pki_int/issue/nomad-task"
          "common_name=my.service.consul" "ttl=90m"
          "alt_names=localhost" "ip_sans=127.0.0.1"}}
          {{ .Data.certificate }}
          {{ .Data.private_key }}
          {{ .Data.issuing_ca }}
          {{ end }}
        EOH
        destination = "${NOMAD_SECRETS_DIR}/my.crt"
        change_mode = "noop"
        perms = "600"
      }

@tgross
Copy link
Member

tgross commented May 31, 2022

@grembo sorry I didn't notice there was already an extensive discussion in #11900 about this. This goal

The goal is to store the token in a separate directory that is not accessible from inside the container.

doesn't seen to be in evidence in that discussion though? Let's move this discussion about the overall design over to the issue though. I'll let @schmichael and @lgfa29 take it from there.

@grembo
Copy link
Contributor Author

grembo commented May 31, 2022

@grembo sorry I didn't notice there was already an extensive discussion in #11900 about this. This goal

The goal is to store the token in a separate directory that is not accessible from inside the container.

doesn't seen to be in evidence in that discussion though? Let's move this discussion about the overall design over to the issue though. I'll let @schmichael and @lgfa29 take it from there.

@tgross Yeah, originally #11900 was about changing /secrets/vault_token's file permissions, I only realized later that moving the file completely out of the way is a much cleaner solution and actually what we require. In the discussion in #11900 we also stumbled over the fact that task directories are world-readable (including files in any task's /secrets directory), which might have come to the surprise of some and introduced an additional topic into the discussion.

Hence my idea to split this PR/the issue and reduce the scope it handles, so it becomes single-topic and actionable.

@grembo grembo mentioned this pull request May 31, 2022
5 tasks
@grembo grembo marked this pull request as draft June 12, 2022 17:22
@grembo
Copy link
Contributor Author

grembo commented Jul 6, 2022

Closing this pull request in favor of #13343, which is smaller in scope.

@grembo grembo closed this Jul 6, 2022
@github-actions
Copy link

github-actions bot commented Nov 4, 2022

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 Nov 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

vault_token is written to /secrets world-readable
3 participants