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

vault: fix token revocation during workflow migration #19689

Merged
merged 4 commits into from
Jan 10, 2024

Conversation

lgfa29
Copy link
Contributor

@lgfa29 lgfa29 commented Jan 9, 2024

When transitioning from the legacy token-based workflow to the new JWT workflow for Vault the previous code would instantiate a no-op Vault if the server configuration had a default_identity block.

This no-op client returned an error for some of its operations were called, such as LookupToken and RevokeTokens. The original intention was that, in the new JWT workflow, none of these methods should be called, so returning an error could help surface potential bugs.

But the RevokeTokens and MarkForRevocation methods are called even in the JWT flow. When a leadership transition happens, the new server looks for unused Vault accessors from state and tries to revoke them. Similarly, the RevokeTokens method is called every time the Node.UpdataStatus and Node.UpdateAlloc RPCs are made by clients, as the Nomad server tries to find unused Vault tokens for the node/alloc.

Since the new JWT flow does not require Nomad servers to contact Vault, calling RevokeTokens and MarkForRevocation is not able to complete without a Vault address and token, so this commit changes the logic to use the no-op Vault client when one of them is not passed. It also updates the client itself to not error if these methods are called, but rather raise a warning log so operators can be made aware that there are Vault tokens created by Nomad that have not been force-expired.

There are also updates to the documentation of the migration process. When migrating an existing cluster to the new workload identity based flow, Nomad operators must first upgrade the Nomad version without removing any of the existing Vault configuration. Doing so can prevent Nomad servers from managing and cleaning-up existing Vault tokens during a leadership transition and node or alloc updates.

Operators must also resubmit all jobs with a vault block so they are updated with an identity for Vault. Skipping this step may cause allocations to fail if their Vault token expires (if, for example, the Nomad client stops running for TTL/2) or if they are rescheduled, since the new client will try to follow the legacy flow which will fail if the Nomad server configuration for Vault has already been updated to remove the Vault address and token.

nomad/server.go Outdated Show resolved Hide resolved
nomad/vault_noop.go Outdated Show resolved Hide resolved
Comment on lines +765 to +766
* Resubmit Nomad jobs that need access to Vault to redeploy them with a new
workload identity for Vault.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to think of ways we could help with this. Two ideas I had were:

  1. A command that looks for the following artifacts and tell users if their clusters are ready for the migration.
  • jobs with vault blocks (and maybe templates with Vault-related functions? A vault block is not always required to access Vault) but no Vault identities.
  • unused VaultAccessors in state store (and potentially clean them without needing a leadership transition)
  1. Some kind of metric that operators can monitor and wait until it reaches zero. But I'm not sure yet exactly what to measure.

Copy link
Member

Choose a reason for hiding this comment

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

I like the idea of a command... maybe we could bake this into a -check flag for nomad setup vault?

A metric would be nice, but the only reasonable place for it would be in the state store and we'd have to repopulate it during snapshot restore. Kind of messy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool! I will try to think a bit more where to place the command. I was thinking somewhere under nomad operator to indicate that this may require a management token since it needs to look all over the state store.

It could also be used for other upgrade checks in the future.

@lgfa29 lgfa29 requested review from pkazmierczak and tgross January 9, 2024 19:56
Copy link
Member

@tgross tgross left a comment

Choose a reason for hiding this comment

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

LGTM once the comments I've made are resolved.

nomad/server.go Outdated Show resolved Hide resolved
nomad/vault_noop.go Outdated Show resolved Hide resolved
Comment on lines +765 to +766
* Resubmit Nomad jobs that need access to Vault to redeploy them with a new
workload identity for Vault.
Copy link
Member

Choose a reason for hiding this comment

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

I like the idea of a command... maybe we could bake this into a -check flag for nomad setup vault?

A metric would be nice, but the only reasonable place for it would be in the state store and we'd have to repopulate it during snapshot restore. Kind of messy.

lgfa29 added 3 commits January 9, 2024 22:17
When transitioning from the legacy token-based workflow to the new JWT
workflow for Vault the previous code would instantiate a no-op Vault if
the server configuration had a `default_identity` block.

This no-op client returned an error for some of its operations were
called, such as `LookupToken` and `RevokeTokens`. The original intention
was that, in the new JWT workflow, none of these methods should be
called, so returning an error could help surface potential bugs.

But the `RevokeTokens` and `MarkForRevocation` methods _are_ called even
in the JWT flow. When a leadership transition happens, the new server
looks for unused Vault accessors from state and tries to revoke them.
Similarly, the `RevokeTokens` method is called every time the
`Node.UpdataStatus` and `Node.UpdateAlloc` RPCs are made by clients, as
the Nomad server tries to find unused Vault tokens for the node/alloc.

Since the new JWT flow does not require Nomad servers to contact Vault,
calling `RevokeTokens` and `MarkForRevocation` is not able to complete
without a Vault token, so this commit changes the logic to use the no-op
Vault client when no token is configured. It also updates the client
itself to not error if these methods are called, but to rather just log
so operators can be made aware that there are Vault tokens created by
Nomad that have not been force-expired.
When migrating an existing cluster to the new workload identity based
flow, Nomad operators must first upgrade the Nomad version without
removing any of the existing Vault configuration. Doing so can prevent
Nomad servers from managing and cleaning-up existing Vault tokens during
a leadership transition and node or alloc updates.

Operators must also resubmit all jobs with a `vault` block so they are
updated with an `identity` for Vault. Skipping this step may cause
allocations to fail if their Vault token expires (if, for example, the
Nomad client stops running for TTL/2) or if they are rescheduled, since
the new client will try to follow the legacy flow which will fail if the
Nomad server configuration for Vault has already been updated to remove
the Vault address and token.
@Lord-Y
Copy link

Lord-Y commented Jan 15, 2024

We just hit this problem. We had rollback our config without workload identity. We'll wait for the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/1.7.x backport to 1.7.x release line
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants