-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Final LibGit2 credential callback changes #23770
Conversation
Interesting, this code is no longer broken on Windows: if Sys.iswindows() && LibGit2.version() >= v"0.26.0"
# see #22681 and https://github.com/libgit2/libgit2/pull/4055
@test_broken ex.code == LibGit2.Error.EAUTH
@test ex.code == LibGit2.Error.ERROR
else
@test ex.code == LibGit2.Error.EAUTH
end
|
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 don't see any obvious logical issues with the code, just some style and organizational suggestions.
base/libgit2/callbacks.jl
Outdated
response = Base.prompt("Private key location for '$prompt_url'", | ||
default=privatekey) | ||
default=creds.prvkey) |
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.
Same indentation issues as previous PR.
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've addressed this by renaming prompt_url
to just url
which means I can fit this keyword on a single line.
base/libgit2/callbacks.jl
Outdated
p.remaining_prompts <= 0 && return prompt_limit() | ||
end | ||
|
||
if !modified |
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.
Couldn't you just move this into the if-block above (e.g., elseif !modified
)? That might make the code easier to follow.
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 purposefully did this as I can see the if
above turning into a while
loop. Originally this is what was done in #20725.
base/libgit2/callbacks.jl
Outdated
function authenticate_ssh(libgit2credptr::Ptr{Ptr{Void}}, p::CredentialPayload, username_ptr) | ||
creds = Base.get(p.credential)::SSHCredentials | ||
modified = false |
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.
Some of these modified
changes seem like they could simplified (e.g., You could probably just have modified = p.first_pass && isfilled(creds)
at the beginning).
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.
It may be better if I drop modified
and just do a comparison between the initial credentials and the current credentials. I'll do some checks.
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 idea of doing the comparison won't work. If a user were to enter the same invalid credentials twice in a row they would get an "All authentication methods have failed" error. The name modified
isn't quite the right term as this just verifying that a new authentication method has been attempted.
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 reworked this a little bit. I've ended up changing modified
to revised
. I think this term is better suited for the current behaviour. As for revised = p.first_pass && isfilled(creds)
I've decided to keep the if
block as it matches the way revised
is used in the reset of the code.
base/libgit2/callbacks.jl
Outdated
if Sys.iswindows() | ||
response = Base.winprompt( | ||
"Please enter your credentials for '$prompt_url'", "Credentials required", | ||
isempty(creds.user) ? p.username : creds.user; prompt_username=true) |
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'd be inclined to move the ternary out of the if-block and put the remaining code into an user_auth_prompt
function.
base/libgit2/callbacks.jl
Outdated
end | ||
|
||
if isempty(passphrase) && is_passphrase_required(privatekey) | ||
# Ask for a passphrase when the private key exists and requires a passphrase | ||
if isempty(creds.pass) && is_passphrase_required(creds.prvkey) | ||
if Sys.iswindows() | ||
response = Base.winprompt( |
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.
Move prompt logic into ssh_auth_prompt
?
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.
Separating these into new functions hasn't turned out well. I've decided to stick with the status quo.
Ok, I worked my way through the AppVeyor issue. As it turns out the commit "Error when credentials are not modified" corrects the broken test. In this commit we throw a EAUTH error from the callback when the credentials are not filled. I'll update the libgit2-online tests to reflect this but I also think it could be reasonable to remove the "with empty credentials" test. |
The temporary credential object is independent from any cached or stored credential until it is explicitly approved.
Credentials should be used when they are filled in and alternatives should be tried when they are not. These changes allow use to enable the commented out tests which use invalid credentials. Note when prompting is disabled we now attempt to authenticate using the default ~/.ssh/id_rsa key.
Previously if the public key file exists and the private key was correct we could get into a scenario where we would never prompt for the public key to be changed.
Note the prompt limit is an EAUTH error since hitting the prompt limit should cause saved credential to be rejected.
062b293
to
597ce0b
Compare
During the investigation on changing how |
The PR should be ready to go now. I think this should be merged rather than squashed to keep the history understandable. I've run the LibGit2 tests locally on each commit. |
Found a minor issue with the LibGit2 library I'll patch yet. |
Without setting an error message the message will be whatever error message came before.
The test has been superseded by all of the new credential_loop tests.
According to the LibGit2 authentication guide (https://libgit2.github.com/docs/guides/authentication/) the callback is suppose to be retried if the server doesn't accept the credentials. In the case where we use SSH and the passphrase is invalid LibGit2 would just give a generic: GitError(Code:ERROR, Class:SSH, Failed to authenticate SSH session: Callback returned error)
Allows the user to confirm they want to use the default private key. During development it was noticed that the username was only being filled in if prompting was allowed.
597ce0b
to
23d2fd2
Compare
After digging into the LibGit2 issue the problem turned out to bug where the credential callback loop is aborted if the SSH passphrase is incorrect. Addressing this now makes Additionally, after doing more experimenting with |
PR for the LibGit2 patch: libgit2/libgit2#4357 |
Should be the last round of bugfixes and minor features to the LibGit2 credential callback system before I move onto integrating git credential helpers. There are quite a few small changes in this PR including:
CredentialPayload
's credential field is now used a temporary storage. We can safely do this without accidentally modifying cached credentials because of LibGit2 credential approval/rejection #23711isfilled
function which verifies a credential is ready to be used in authenticationmodified
check which allows us to abort when all authentication methods have failedAdditionally, at this point I think the
credential_loop
tests cover our testing of the SSH code paths. The ancient "SSH" testset has been removed which fixes #18403, #18306.Part of #20725.