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

fix(credential)!: Fallback when an auth method isn't available on the current machine #13558

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

epage
Copy link
Contributor

@epage epage commented Mar 7, 2024

What does this PR try to resolve?

This changes cargo-credential-libsecret to report UrlNotSupported errors when libsecret can't be loaded. This was also extended to token-from-stdout when the process can't be spawned.

The goal with this change is to make it easier to support a
cross-platform, cross-machine config file.
Before, someone couldn't enable libsecret for the machines that
supported it and then fallback to something else on machines that don't.

After this change, we should be able to fallback to other providers.

To help with debugability, we preserve the "libsecret can't be loaded"
message by reporting the first "rich" UrlNotSupported error message.
This is a newly invented construct as part of this PR.

This was discussed on
zulip
and in the cargo team meeting.

This is to improve the cross-platform config support in an effort to
deprecate having config be unset as part of #13343

How should we test and review this PR?

Additional information

Compatibility

  • Breaking: cargo-credential's Error went from an enum to an opaque struct with a separate ErrorKind
  • cargo-credential json messages can now contain more, optional fields
  • cargo-credential-libsecret will no longer hard error if libsecret can't be loaded

epage added 10 commits March 5, 2024 21:12
This isn't really providing much and gets in the way of tweaking the
errors.
BREAKING CHANGE: `Error` because an opaque type with the enum broken out
into `ErrorKind`
- To construct an error from an `ErrorKind`, you can use `Into`.
- To wrap an existing error, use `Error::other`
This changes cargo-credential-libsecret to report `UrlNotSupported` errors when `libsecret` can't be loaded.

The goal with this change is to make it easier to support a
cross-platform, cross-machine config file.
Before, someone couldn't enable `libsecret` for the machines that
supported it and then fallback to something else on machines that don't.

After this change, we should be able to fallback to other providers.

To help with debugability, we preserve the "`libsecret` can't be loaded"
message by reporting the first "rich" `UrlNotSupported` error message.
This is a newly invented construct as part of this PR.

This was discussed on
[zulip](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/reg.20auth.20and.20libsecret)
and in the cargo team meeting.

This is to improve the cross-platform config support in an effort to
deprecate having config be unset as part of rust-lang#13343
Like with `libsecret` not being present, process spawn errors can be
treated as an indication that that config entry isn't relevant for the
current machine and we should try other entries.

If there is nothing else to fallback to, we'll still report this error.
@rustbot
Copy link
Collaborator

rustbot commented Mar 7, 2024

r? @ehuss

rustbot has assigned @ehuss.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-credential-provider Area: credential provider for storing and retreiving credentials A-documenting-cargo-itself Area: Cargo's documentation A-registry-authentication Area: registry authentication and authorization (authn authz) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 7, 2024
@epage epage added T-cargo Team: Cargo and removed A-documenting-cargo-itself Area: Cargo's documentation S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. A-credential-provider Area: credential provider for storing and retreiving credentials A-registry-authentication Area: registry authentication and authorization (authn authz) labels Mar 7, 2024
@epage
Copy link
Contributor Author

epage commented Mar 7, 2024

r? @arlosi

@rustbot rustbot assigned arlosi and unassigned ehuss Mar 7, 2024
@epage epage force-pushed the secret-fallback branch from da59163 to 368444f Compare March 7, 2024 22:22
@rustbot rustbot added A-credential-provider Area: credential provider for storing and retreiving credentials A-documenting-cargo-itself Area: Cargo's documentation A-registry-authentication Area: registry authentication and authorization (authn authz) labels Mar 7, 2024
@epage epage force-pushed the secret-fallback branch from 368444f to 0f3b391 Compare March 7, 2024 22:38
let mut child = cmd
.spawn()
.context("failed to spawn credential process")
.map_err(|err| Error::from(err).with_kind(ErrorKind::UrlNotSupported))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a comment saying why UrlNotSupported is used here. (So that we get the behavior of attempting further providers).

@@ -72,7 +72,6 @@ os_info = "3.7.0"
pasetors = { version = "0.6.8", features = ["v3", "paserk", "std", "serde"] }
pathdiff = "0.2"
percent-encoding = "2.3"
pkg-config = "0.3.30"
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see this referenced anywhere else in the change. Is it just an unneeded dependency?

Err::<(), _>(e)
.with_context(|| {
format!(
"credential provider `{}` could not handle the request",
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please add a UI test so we can see the output when there are multiple failed providers?

})
}
Err(e) => match e.kind() {
cargo_credential::ErrorKind::UrlNotSupported => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure that the UrlNotSupported error makes sense for "non-fatal" errors. It was intended to indicate that the provider only supports some registry urls (like a provider only for a specific type of registry). It then grew to also be used for the platform-specific providers on the wrong platform - and that still made some sense since they are providers that don't work with any registry.

This use case of non-fatal (continuable) error is much further from that intent. However, I'm not sure what the right solution is.

Here are some other options:

  1. Make all errors "non-fatal" and continue trying providers for all error types
  2. Keep the existing behavior, but add an option in the global credential providers config to mark a provider as "optional"
  3. Add a new error type of OtherContinuable that that works as you've implemented it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Talked about this in office hours

Add an alternative to Other that is Backtrack

  • Backtrack will need an MSRV note in docs
  • Maybe add an alias for Other that is Critical
    • Be careful about forcing MSRV bump

As for whether every error could have a message, this was a bit unclear.

  • url-not-supported: doesn't need it
  • not-found: doesn't need it
  • operation-not-supported: could benefit from it because a login failure on a provider that doesn't support it could give a better message saying why.

In the end, we decided that since the code was written, we should just move forward with a message on each one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For message printing:

  • On error (everything backtracked):
    • Print every provider that backtracked and the message
  • On success (a provider matched)
    • In extra verbose, print the providers that backtracked and the message

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we're doing a breaking change, we should also do #13615

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@arlosi will do that breaking change after this is merged but within the same release

@@ -177,6 +181,10 @@ available.
{"Err":{
// Error: The credential could not be found in the provider.
"kind":"not-found"
// (Optional) Error message string to be displayed
"message": "free form string error message",
Copy link
Contributor

Choose a reason for hiding this comment

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

Do these messages from NotFound errors show anywhere?

@bors
Copy link
Contributor

bors commented Mar 25, 2024

☔ The latest upstream changes (presumably #13577) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Mar 25, 2024
@rustbot
Copy link
Collaborator

rustbot commented Dec 20, 2024

☔ The latest upstream changes (possibly 081d7ba) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-credential-provider Area: credential provider for storing and retreiving credentials A-documenting-cargo-itself Area: Cargo's documentation A-registry-authentication Area: registry authentication and authorization (authn authz) S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. T-cargo Team: Cargo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants