-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fetching cargo registry tokens from external processes #2730
Conversation
Cool, please do add this! Unifying everything in GNOME keyrings and the likes is really nice. |
a1ed3d7
to
0471313
Compare
macOS Keychain has access controls per application, and enforces that by verifying signature of the calling application. The problem is, if you run a subprocess that uses Keychain, the Keychain will use identity of the subprocess. That breaks the chain of trust of the Keychain, because this way any application can just call the subprocess to get the token. So regardless of this method, for macOS I'd prefer the solution mentioned in the alternatives section. |
Didn't know about that, but still, this PR would be an improvement because the users will be prompted every time the token is needed (if they don't "always allow"), providing a small layer of protection. Does Keychain require binaries to be signed to identify the requesting process? In that case, an RFC adding explicit Keychain support would also need to figure out the signing on our infra. |
@kornelski I think it'd be great if cargo had built-in OS specific backends for secret storage on operating systems that have some sort of keychain abstraction. However, that seems like an orthogonal nice-to-have, and there are several places I could see using something like this particular PR. One is "cloud shell" environments where tokens can be encrypted using the cloud's KMS service, and an OAuth credential used to talk to the KMS to decrypt tokens prior to use (logging each usage to an audit log). As a sidebar and not-too-serious suggestion, there are also ways to circumvent the Keychain Services identity delegation-to-a-subprocess problem with megahax (instead of spawning a subprocess, you can load it into memory with |
@pietroalbini That "allow/always allow" window pops up on unsigned executables or when the signature doesn't match. @tarcieri I get usefulness of having easy extensibility. I just wanted to point out that for proper macOS integration it's not entirely sufficient. |
@kornelski as a separate issue, adding Keychain Services-backed secret storage to cargo (and abstractions for multiple token providers) is something I'd be interested in helping work on. |
Renamed the configuration entry to |
As far as I can see we are not required to promise that I recommend making explicit in the RFC whether the subprocess will inherit
That is, the subprocesses' |
How do we call the command without running it through a shell though?
Good points! Clarified that stderr and stdin will be inherited, while stdout will be captured to read the token. |
One thing that's worth pointing out is that Cargo already has support for invoking external processes to get credential information, it just only uses it for git authentication. The "credential helper" support that is located in It'd be great if that basically ended up being the same as whatever Cargo uses natively, and Cargo could be refactored to literally share the same code as well. One downside of the implementation in |
Do you mean reusing/sharing just the code used to call the process or the whole git credential helper protocol? I feel like the protocol itself is a bit overkill for what we want to do here.
Yeah, git2's approach of calling Thinking about it a bit more, @lukaslueg's idea of just skipping the shell could work if we define in the RFC that the command will be split according to the POSIX standard. There is a crate that already implements the splitting code according to that. |
First and foremost this is an educated opinion, but: I would rather avoid having a string that cargo will execute by calling a hoped-for-to-be-there shell and just hand stuff to it. Splitting the string does not require much code, is easily tested and does not rot. As an alternative, I don't think
|
@pietroalbini ah yeah to clarify I mean mostly to bring up what Cargo does today as an example of how Cargo's already doing this in some capacity. If the git protocol makes sense for us we could adopt it pretty easily, but if it doesn't make sense then I don't see any reason we should bend over backwards to do so. We have, in rustc and cargo, avoided any form of shell escaping in all (afaik) ways of passing multiple arguments. I'd personally like to continue doing so, and the general solution we have is that there's a convenience "give me a bunch of arguments quickly" option which splits on whitespace, and then there's a "give me one argument at a time" interface which does no splitting. (e.g. It's also worth pointing out that git provides a default built-in credential cache (I think it's like |
For the shell selection, a new attribute might work. ( just thinking outload without knowing too much detail about the subject) This way it has a non hard coded configuration that is separated from the actual parameters and cross platform. |
b746def
to
020f794
Compare
Updated the RFC to reflect @lukaslueg's idea. |
issued to let the user know about that. | ||
|
||
The `token-from-process` key accepts either a string containing the binary to | ||
call or a list containing the binary name and the arguments to provide to 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.
FWIW Cargo's intepretation of this today is that a bare string is a whitespace-separated list of arguments and a list of strings is the exact list of arguments. We'll probably want to stay consistent with the rest of Cargo in that respect?
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.
My worry about splitting by whitespace is it just breaks in unexpected ways if people wants to use a shell:
token-from-process = 'bash -c "echo foo | head -n 1"'
With some CLI password managers this is going to be really common, and splitting ["bash", "-c", "\"echo", "foo", "|", "head" "-n", "1\""]
is just unintuitive. I'd prefer to either properly split quotes (by using crates like shlex) or just not split at all.
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's possible, yes, but I think it's more important to either to stay consistent with Cargo or fully commit to some form of parsing.
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.
Personally I'd prefer to just commit to split like a POSIX shell. It's not that complex and there is already an implementation available in the shlex crate.
Ugh, your reply was lost in the notifications... Sorry for the delay responding.
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 understand, yes, but i personally at least feel that using shlex is a local optimum which misses how nothing else in Rust uses shlex. For example -C link-args
, RUSTFLAGS
, etc. Nothing across our tooling which accepts multiple arguments has ever used shell escapes, and this seems like a pretty odd case to be the first one to use 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 would second the objection to shlex
or any other parsing.
I'd actually prefer to prohibit "single string with whitespace splitting" and only allow a list of arguments, but if we don't want to do that, then let's be consistent with the rest of Cargo.
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.
@joshtriplett so, is the current text of the RFC what you'd like?
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.
Ping @joshtriplett?
Do you foresee this being something we would want to have interact with 2fa? e.g. if the process that generates your TOTP token were on the same machine |
I'd love to have something like this for an eventual 2FA support in Cargo as well (I store my TOTP tokens on my YubiKey), but I think it's outside the scope of this RFC as there is no need for Cargo to request TOTPs at the moment. |
Sounds fine. Might be worth mentioning it under "Future Possibilities" or at least calling out that this doesn't introduce any incompatibilities there since it's the most likely addition to happen for auth in the near future |
Done! |
Hey @pietroalbini, sorry it took so long to follow up on this. I was wondering if we could add an "action" argument to the command which would pass "get", "store", or "erase" as an argument? It would just be added as the last argument to the command. It would have similar semantics as other tools. I believe that is how Docker, git, and a few other tools work. This would allow |
@ehuss I see merits in both approaches:
Personally I'd prefer the first approach (as it would integrate better with my personal tooling), but I don't see why the two of them couldn't coexist? |
It seems to me like it'd be fine to have a wrapper script to adapt the "cargo protocol" to a password manager's protocol. I think we'll want the flexibility in the future as well to tweak this over time with new capabilities rather than having to reinvent something new each time. |
I have update the RFC with the extension of optionally allowing a credential process to take an "action" that should make it more user-friendly. Specifically:
|
I'm going to propose to merge this. I'm happy with the proposed design, and there hasn't otherwise been much more feedback. I think it will be useful to move forward to an implementation to get more scrutiny on it, and overall I think it could be a very useful feature. @rfcbot fcp merge |
Team member @ehuss has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
This comment has been minimized.
This comment has been minimized.
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
Huzzah! The @rust-lang/cargo team has decided to accept this RFC. To track further discussion, subscribe to the tracking issue here: |
Rendered
This RFC proposes a new cargo configuration key to fetch registry tokens from external processes, allowing to store them in password managers or other secret storage systems:
Thanks @Eh2406 for the feedback on the draft!