-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
clientv3: allow setting JWT directly #16803
base: main
Are you sure you want to change the base?
Conversation
176ae2b
to
04a3a2e
Compare
I also added support for passing a token rather than a username and password in etcdctl. I can split this into a separate PR that depends on this one if needed; leaving it here for now though since it's a relatively small change. |
The failing test here appears to be unrelated to this 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.
Hey @mcrute - Thanks for raising this idea.
Overall at first glance this seems reasonable. Can you please add a test for this new direct jwt authentication so we can ensure it doesn't break in future? Thanks!
a8b6623
to
fc8027a
Compare
Hi @jmhbnz, sure thing! I've added some tests for the functionality. Let me know if there's anything else needed to get this merged. |
Thanks @mcrute - Quick heads up the etcd team are pretty busy at kubecon this week so there might be a minor delay getting this new feature reviewed. I will take another look when I get some quiet focus time hopefully end of the week 🙏🏻 |
Thanks @jmhbnz, I appreciate it. Would really like to get this merged so let me know if there's anything I can do to help move it along. Have a nice KubeCon! |
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.
LGTM - Thanks @mcrute.
Would you mind please rebasing this pr onto latest changes in main
as I notice make verify
is failing on this branch (for an unrelated issue I believe which has since been fixed in main
.).
fc8027a
to
d398cf0
Compare
Thanks for the review, I've rebased main under this so hopefully we'll get a green test run. |
/ok-to-test |
/test pull-etcd-unit-test |
Looking at the failing test. I don't see how it's immediately related to this change but it's an auth test so I'm suspicious. |
d398cf0
to
b597d28
Compare
Found the issue. Unconditionally setting |
Gentle ping @serathius & @ahrtr, I think this one is ready for maintainer review. @mcrute If we go ahead with this we will probably want to update some documentation on github.com/etcd-io/website , perhaps under: |
Once this is merged I'll create a PR for the docs. I learned a ton digging through this functionality and definitely would like to make sure others can use it with less effort required. |
I think we need to add an e2e test as well. |
Have had some time constraints but I'll post an update soon. Adding validation + test case for credential mixes as well as an e2e test validating that standalone token auth works. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions. |
Discussed during sig-etcd triage meeting @mcrute do you have time to rebase this pr and add the e2e test? Would be great to get this merged. Thanks! |
@jmhbnz I'm planning to pick this back up this week, have been distracted by other priorities but would very much like to get this finished and merged. |
b597d28
to
3201b9d
Compare
Ping @serathius & @ahrtr. Do you have a moment to review (and hopefully merge) this PR? I think that it's complete and incorporates all of the feedback. |
What will happen if such a client call Authenticate? |
There will be no change in behavior from the current state of the code. If the server has only a public key it will fail with an error because it will not be able to Although my reading of the code is that this would be a pretty odd case for someone to do this since |
bbd74da
to
5688b78
Compare
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files
... and 23 files with indirect coverage changes @@ Coverage Diff @@
## main #16803 +/- ##
==========================================
+ Coverage 68.81% 68.83% +0.01%
==========================================
Files 420 420
Lines 35490 35504 +14
==========================================
+ Hits 24422 24438 +16
+ Misses 9637 9634 -3
- Partials 1431 1432 +1 Continue to review full report in Codecov by Sentry.
|
5688b78
to
aa851eb
Compare
Rebasing this was a terrible idea 😭. Undoing that bad decision and hopefully these new, unrelated, tests failures disappear. |
aa851eb
to
3c4aaa6
Compare
Please rebase this PR, because it is based on a commit of 3 weeks ago. We ran into conflict which wasn't detected by github. Two generic comments/questions,
|
3c4aaa6
to
729dbbe
Compare
Once I have a clean run of all the tests I'll rebase. The first rebase introduced a lot of seemingly spurious failures and I would like to make sure I've got completely working and tested code before digging into those.
Yes, we use some code similar to this for application configuration and secret bootstrapping. The application runner injects a pre-signed etcd token into the application environment when it starts then a library within the application discovers etcd (using DNS SRV records), connects with the injected token, and reads its configuration and secrets from etcd. There is a separate controller that handles token lifetimes by creating new tokens and passing them to applications over a pre-defined key in etcd so the application can update the token for their etcd connection before expiration (it's a little more complicated than that but that's the general workflow).
At least for our use-case that should be okay. We swap tokens well in advance of their expiration. Although having this functionality would be a good safety measure. |
Looks like the build was clean. Going to push the rebase now for testing. |
etcd supports using signed JWTs in a verify-only mode where the server has access to only a public key and therefore can not create tokens but can validate them. For this to work a client must not call Authenticate and must instead submit a pre-signed JWT with their request. The server will validate this token, extract the username from it, and may allow the client access. This change allows setting the JWT directly and not setting a username and password. If a JWT is provided the client will no longer call Authenticate, which would not work anyhow. It also provides a public method UpdateAuthToken to allow a user of the client to update their auth token, for example, if it expires. In this flow all token lifecycle management is handled outside of the client as a concern of the client user. Signed-off-by: Mike Crute <[email protected]>
Signed-off-by: Mike Crute <[email protected]>
Signed-off-by: Mike Crute <[email protected]>
729dbbe
to
4f46fb4
Compare
@ahrtr all right, I've got all the requested changes incorporated and we've got a clean build with the rebase! Let me know if there's anything else you'd like to see or if we're good to merge this. Thanks. |
If the application doesn't update the token before expiration in time for whatever reason, then you won't have any chance to know the One possible solution is to loosen the access control on AuthStatus so that you can always get the latest authRevision no matter whether or not you have a valid token, Line 70 in 3aa56a7
Refer to, etcd/server/etcdserver/apply/apply_auth.go Lines 175 to 176 in 3aa56a7
Also we need to update the doc to clarify the use case/workflow for this change. |
Just checking back in on this. I'm open to removing loosening the access control on I will also update the docs but since those are in a different repo I was planning to do that after this was merged. Do you want me to open a PR against the docs as well and cross-link them? I'd really like to get this shipped in September, if possible, so we can stop vendoring a fork of this library. |
Overall this is a valid & minor change (only client side change) to me. Followups,
It's hard to track all these tasks across PRs. Could you raise a ticket to track them? |
@@ -376,6 +384,10 @@ func newClient(cfg *Config) (*Client, error) { | |||
creds = credentials.NewTransportCredential(cfg.TLS) | |||
} | |||
|
|||
if cfg.Token != "" && (cfg.Username != "" || cfg.Password != "") { | |||
return nil, errors.New("Username/Password and Token configurations are mutually exclusive") |
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.
Minor observation/question: thinking about the work we have been doing with errors, does setting this error as an exported variable make sense? Would it be valuable? WDYT @ahrtr?
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.
Sounds like a good suggestion.
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.
Given the number of follow-ups we have for this pull request, and the time it has been open, I think it's okay to do this in a follow-up PR.
// Token is a JWT used for authentication instead of a password. | ||
Token string `json:"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.
Given that this will be exported and it may be difficult to change the name later on, I feel like "Token" may be too generic. Would "JWT" be a better name (more implementation specific)?
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.
Theoretically, it can be any token types that are supported by etcd. The etcdserver just delegates to the related token provider to parse the token based on the token type configured in --auth-token
.
But in practice, it's JWT for now. So suggest to keep using 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.
LGTM. Thanks, Mike.
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ivanvc, jmhbnz, mcrute The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
etcd supports using signed JWTs in a verify-only mode where the server has access to only a public key and therefore can not create tokens but can validate them. For this to work a client must not call Authenticate and must instead submit a pre-signed JWT with their request. The server will validate this token, extract the username from it, and may allow the client access.
This change allows setting the JWT directly and not setting a username and password. If a JWT is provided the client will no longer call Authenticate, which would not work anyhow. It also provides a public method UpdateAuthToken to allow a user of the client to update their auth token, for example, if it expires.
In this flow all token lifecycle management is handled outside of the client as a concern of the client user.