-
Notifications
You must be signed in to change notification settings - Fork 325
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
NET-1721: Automatic ACL bootstrap with Vault secrets backend #1920
Conversation
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 is great stuff Paul. I love the secrets backend abstraction! I left a few minor nits/comments/questions.
ctx: c.ctx, | ||
clientset: c.clientset, | ||
k8sNamespace: c.flagK8sNamespace, | ||
// TODO: should these use the global.acls.bootstrapToken.{secretName,secretKey}? |
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 think that is reasonable and intuitive since there's nothing Vault-specific about the bootstrap token fields. It feels to me like the behavior for Vault and K8s should be the same. Is there a good reason not to do this? Would it break any existing behavior/assumptions?
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 think I can't change this (yet) because it may break existing deployments.
- If ACLs are pre-bootstrapped, then I would specify the k8s secret containing the bootstrap token in the Helm values, and server-acl-init reads from the specified secret
- If server-acl-init automatically bootstrapped ACLs, then it writes the token to the hard-coded secret (
<prefix>-bootstrap-acl-token
).
If we change the secret name, then server-acl-init would fail to find the bootstrap token in case 2. (I'm not clear how much of a problem this is if server-acl-init has already run once? But there are lots of upgrade scenarios to think through that it feels dangerous to do with my current limited understanding)
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.
To make k8s and Vault secrets backends more consistent, I updated the secrets backends to use the given secret name, if provided, or else use a default secret name. This applies to both k8s and Vault.
I also removed the -bootstrap-token-file
flag and the mounts/files that were used for the k8s and Vault secrets. Instead, the secret is read by server-acl-init directly from the secrets backend API (k8s or vault).
This should not be a breaking change because if a secret exists and contains the token, then that token is used (same as before). If the secret is empty, then we proceed with ACL bootstrapping and update the secret (previously, server-acl-init would error out).
Let me know what you think, and cc @thisisnotashwin for your thoughts on this
Does this PR need to consider the case when the server agents are external (e.g., on VMs, in HCP, on a different k8s cluster)? Would the user set manageSystemACLs to Happy to follow up over Zoom, not sure I've articulated this well. I just want to make sure we've considered how this might work in the context where the Consul server agents aren't in the current k8s cluster. |
This should work the same as before w.r.t whether servers are external or not. The ACL bootstrapping logic was already there. This just changes where the bootstrap token can be written (i.e. can also store it in Vault).
Right. If no bootstrap token provided, it will attempt to ACL bootstrap. If it tries to bootstrap a cluster that is already ACL bootstrapped, then server-acl-init will fail. You'll have to go and update the Helm values to set the bootstrap token. |
{{- if .Values.global.secretsBackend.vault.enabled }} | ||
{{- if .Values.global.secretsBackend.vault.agentAnnotations }} | ||
- name: VAULT_NAMESPACE | ||
value: {{ get (tpl .Values.global.secretsBackend.vault.agentAnnotations . | fromYaml) "vault.hashicorp.com/namespace" }} |
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 ended up being semi-ugly. To specify a Vault namespace for the Vault agent, you add a vault.hashicorp.com/namespace
annotation. With the Consul helm chart, this is specified in the "extra" global.secretsBackend.vault.agentAnnotations
. So I had to parses the Vault namespace from those extra annotations.
When talking through the Vault agent, even though it uses the namespace for injected secrets/templates, the agent doesn't scope API requests to that namespace I guess. So this needs to be explicitly specified for the Vault client used by server-acl-init when reading/writing secrets in the Vault API.
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.
great work here bud!! sorry for the late review.
Added backport/1.1.0.x to this PR. If you feel this should be back ported to other versions, please add labels and ensure the docs are updated for each branch. Thanks! |
61fe6f8
to
0c43247
Compare
Is this ready to merge? |
With the Vault secrets backend, server-acl-init now: * Runs the Vault agent as a sidecar * Bootstraps ACLs if the Vault bootstrap token is empty or not found, and writes the bootstrap token back to Vault via the Vault agent This adds the Vault SDK to the control-plane binary. This added 1 MB to the binary size (74MB to 75MB)
Co-authored-by: Chris Thain <32781396+cthain@users.noreply.github.com>
* The Kubernetes backend will write the bootstrap token to the user-provided secret if that secret is empty. The Vault behavior is the same. * The Vault backend writes to a default secret name if the secretName and secretKey are not set in the helm chart values. * Pass the Vault namespace to server-acl-init server-acl-init reads the secret directly from k8s or Vault. * Remove -bootstrap-token-file flag from server-acl-init and remove the * Remove the volume/mount for that. And update all the tests for that. Remove the bootstrap token secret injection / template the Vault agent.
0c43247
to
583d545
Compare
Support automatic ACL bootstrapping with the Vault secrets backend With the Vault secrets backend, server-acl-init now: * Runs the Vault agent as a sidecar * Bootstraps ACLs if the Vault bootstrap token is empty or not found, and writes the bootstrap token back to Vault via the Vault agent The Kubernetes backend will write the bootstrap token to the user-provided secret if that secret is empty. The Vault behavior is the same. The Vault backend writes to a default secret name if the secretName and secretKey are not set in the helm chart values. server-acl-init reads the secret directly from k8s or Vault. * Remove -bootstrap-token-file flag from server-acl-init and remove the * Remove the volume/mount for bootstrap token --------- Co-authored-by: Chris Thain <32781396+cthain@users.noreply.github.com>
Changes proposed in this PR:
This updates server-acl-init to support automatic ACL bootstrapping when using the Vault secrets backend.
In order to accomplish this, the server-acl-init job runs the Vault agent as a sidecar (in addition to running as an init container). If the bootstrap token is not found in Vault, then server-acl-init will proceed with ACL bootstrapping and write the token back to Vault.
Because server-acl-init writes to Vault via the Vault agent, server-acl-init doesn't have to worry specifying a Vault token or TLS config that it would normally need to talk to the Vault servers.
This adds the Vault SDK to the control-plane binary, which is +1 MB to the consul-k8s-control-plane binary size (74MB to 75MB).
Related to #1176
How I've tested this PR:
Acceptance tests
How I expect reviewers to test this PR:
👀
Checklist: