-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Improve Vault integration and validation #2226
Conversation
Check the capabilities of the Vault token to ensure it is valid and also allow targetting of a role that the token is not from.
// Nomad does not have to be created from this role but must have "update" | ||
// capability on "auth/token/create/<create_from_role>". If this value is | ||
// unset and the token is created from a role, the value is defaulted to the | ||
// role the token is from. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? What is the use case, ever, for using a role to create a token to use the role?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backwards compatibility, we are in a point release, would break peoples configs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has anyone actually set it up like this? There has never been a need for this to be the required setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was no other option which is what started this all 👍 If one was using role based tokens, they would be hit by the behavior change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was always an option, well before the first release with Vault integration.
v.tokenData = &data | ||
|
||
// The criteria that must be met for the token to be valid are as follows: | ||
// 1) If token is non-root or is but has a creation ttl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tokens should never be root unless Nomad is in dev mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't restrict people to that. That is an organizational decision not one Nomad will enforce on people. We just highly discourage it in our docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use a root token and would really like to keep doing that... we only use vault for ease of storage, not for the hardcore security and ACL level stuff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dadgar Per our original discussions around implementation it was never supposed to be allowed outside of dev mode in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jippi You should still not use root tokens, if for no other reason than that they are quite difficult to generate at this point. Just use a periodic token with policies giving all privileges to /*.
// capabilities the token does have as well as any error that occured. | ||
func (v *vaultClient) hasCapability(path string, required []string) (bool, []string, error) { | ||
caps, err := v.client.Sys().CapabilitiesSelf(path) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"root"
in the required slice should be conditional on Nomad being in dev mode.
vaultTokenRenewPath = "auth/token/renew-self" | ||
|
||
// vaultTokenLookupPath is the path used to lookup a token | ||
vaultTokenLookupPath = "auth/token/lookup" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add auth/token/lookup-self
as a lookup possibility. Most tokens can be looked up using that path as it's in the default
policy, so if auth/token/lookup
doesn't work you should use that instead (and probably prefer it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this to limit the set of policies we have to document as Nomad requiring since we can reuse that for both looking our own token up and incoming tokens. But since I guard that validation (https://github.com/hashicorp/nomad/pull/2226/files#diff-87a4c76eca3de54716c55ba6b8c06475R682) I agree. Will make the change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using lookup-self
can be a good secondary option. I agree that keeping lookup
there is not an issue.
return v.config.Role | ||
} | ||
|
||
return v.tokenData.Role |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioned above why it is like this for now
@@ -602,6 +762,12 @@ func (v *vaultClient) validateRole(role string) error { | |||
multierror.Append(&mErr, fmt.Errorf("Role must have a non-zero period to make tokens periodic.")) | |||
} | |||
|
|||
for _, d := range data.DisallowedPolicies { | |||
if d == "default" { | |||
multierror.Append(&mErr, fmt.Errorf("Role can not disallow allow default policy")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good catch! That was for me while I was testing something!
// a) Must have read capability for "auth/token/roles/<role_name" (Can just attemp a read) | ||
// b) Must have update capability for path "auth/token/create/<role_name>" | ||
// c) Role must: | ||
// 1) Not allow orphans |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing that this is copypasta from Asana but you probably mean must allow orphans. Or should allow orphans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was not changing this behavior in this PR. Down the line we may want to relax this constraint and let the operator decide if they would like to allow orphans. But for now we are not allowing it so that when Nomad revokes a token the whole tree is revoked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By extension this means that if Nomad's token becomes invalid all jobs also now have invalid tokens. This is not the suggested operational model that we tell people to use; we recommend orphan periodic tokens for services. There is no reason to artificially impose this upon administrators; they should be free to use their own judgement, especially since you're already requiring periodic tokens.
// c) Role must: | ||
// 1) Not allow orphans | ||
// 2) Must allow tokens to be renewed | ||
// 3) Must not have an explicit max TTL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can limit job length, allowing an explicit max TTL is a decent idea as an additional check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not a bad idea for those who want it but for now I am keeping it at being a periodic token with no max TTL. We can revisit in another PR/release
// 2) Must allow tokens to be renewed | ||
// 3) Must not have an explicit max TTL | ||
// 4) Must have non-zero period | ||
// 5) If not configured against a role, the token must be root |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not configured against a role, you still shouldn't require a root token. There's no need. You could require a token that has sudo
capability against auth/token/create
. Or you could just try to make a token and see if it works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was based on your own suggestion:
5a) Don't require this, it's nearly the same as requiring a root token.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. Don't require a root token. You also shouldn't require a sudo token, but if you insist that you really must have something with super high privileges on that endpoint, make it a sudo token so that you aren't encouraging people to pass in root tokens.
What you should do instead is to just try making the token, and it will work or it will not. There's no reason to be running these checks.
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. |
This PR: