Prompt MFA just once for tctl get tokens#64751
Conversation
| mfaRequired := rc.withSecrets && slices.ContainsFunc(rc.refs, func(r services.Ref) bool { | ||
|
|
||
| withSecrets := rc.withSecrets || slices.ContainsFunc(rc.refs, func(r services.Ref) bool { | ||
| // tokens cannot be retrieved without secrets. |
There was a problem hiding this comment.
Should this be the case even for delegated tokens?
There was a problem hiding this comment.
Yes, every token is secret today. Sadly the token kind conflates 3 things:
- dynamic join tokens
- user token
- static tokens
The delegated tokens are an edge case case of the dynamic token. So we must always consider all tokens secret by default. This is what the provision token RPCs are doing, they enforce MFA on read.
On the client-side, tctl has to do the MFA, else it will be forced by the server 3 times instead of once, even for delegated tokens. The "withSecrets" part is not really the point here, we are more interested in the side effect that all secret reads require MFA.
In the future, I'd like to change the handler.RequireMFA() function to take handler.RequireMFA(verb) so we can differentiate between MFA on read (token, CA certificates, user --with-sercets, ...) and MFA on write (roles). However this won't be backported to v18, at least now, so I think @Joerger 's fix is the best thing to do here to fix the issue.
Changelog: Fix an issue where
tctl get tokenswould prompt for admin MFA three times rather than once.tctl get tokensis an edge case in the Admin MFA get requests as the resource is inherently a secret and does not require aWithSecretsoption in the rpc. This edge case is now covered in the automated tests.This edge case bug was dormant before #57772 due to the fact that tokens are the only resource effected. Before v18.1.5, this bug can still be reproduced by calling
tctl get tokens,tokensManual Test Plan
tctl get tokensprompts for MFA once