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

Add LibGit2 CredentialPayload struct #23189

Merged
merged 5 commits into from
Aug 16, 2017
Merged

Add LibGit2 CredentialPayload struct #23189

merged 5 commits into from
Aug 16, 2017

Conversation

omus
Copy link
Member

@omus omus commented Aug 9, 2017

Part of #20725.

Created the LibGit2.CredentialPayload structure which allows us to keep track of state between multiple credential callbacks. Currently, the payload allows us to:

  • Parse the url_ptr once
  • Simplify authenticate_ssh and authenticate_userpass signatures

A future PR will extend this to remove callback state information from all AbstractCredentials including:

@omus omus added the libgit2 The libgit2 library or the LibGit2 stdlib module label Aug 9, 2017
credid = "ssh://$(p.host)"
creds = get_creds!(unsafe_get(p.cache), credid, creds)
end
p.credential = Nullable(creds)
Copy link
Member Author

@omus omus Aug 9, 2017

Choose a reason for hiding this comment

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

Previously, if user supplied a UserPasswordCredentials type and SSH was one of the allowed types we would just skip SSH authentication. The PR code changes this to attempt to first attempt to do an SSH authentication then do a user/password authentication. In the process the passed in user credentials will be overwritten and not used.

We may want to revise the logic further to better support when authentication can use either SSH or user/password but I'd like to avoid trying doing that at the moment as I don't have any real-world examples of this behaviour.

Copy link
Contributor

Choose a reason for hiding this comment

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

That seems unintuitive, wouldn't UserPasswordCredentials only be passed if the user expected them to be used?

Are any of the methods here visible externally, would this need deprecations anywhere?

Copy link
Member Author

@omus omus Aug 9, 2017

Choose a reason for hiding this comment

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

That seems unintuitive, wouldn't UserPasswordCredentials only be passed if the user expected them to be used?

Yes, the user should be expecting them to be used but it is possible they cannot be used. Let me go over a quick example. If you run:

LibGit2.clone("ssh://[email protected]/user/my-private-repo.git", payload=Nullable(LibGit2.UserPasswordCredentials("foo", "bar")))

The credential callback will be requesting making a request for SSH credentials. But since the user passed in UserPasswordCredentials we can't do anything with these and we need to ignore these credentials (PR behaviour) or abend (original behaviour).

In a completely hypothetical scenario where the allowed_types mask stated that either a SSH credential or user/pass credential could be returned (I have yet to see this) and we ran the same code above we would end up prompting the user for SSH credentials even though we could just try using the passed in UserPassCredentials. This is the scenario I was referring to in my earlier comment.

Are any of the methods here visible externally, would this need deprecations anywhere?

I don't think any deprecations are required as the change now falls back to prompting the user for credentials instead of abending when the explicit credential fails.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there still a way to force error-on-bad-credentials behavior? prompting could be a bad idea in some non-interactive uses

Copy link
Member Author

@omus omus Aug 9, 2017

Choose a reason for hiding this comment

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

I have a PR in the pipeline which will allow the option of disallowing prompting for all credentials. For now however I'll try to restore the original abending behaviour for this PR.

@omus
Copy link
Member Author

omus commented Aug 10, 2017

I'm currently testing the existing behaviour and noticed something strange. If you provide an explicit user/pass credential and the callback expects an SSH credential you get a warning about the credential being incompatible. However, if you supply a SSH credential and the callback expects a user/pass credential the callback will end up ignoring the explicit credential.

I'll make sure to make this behaviour consistent.

@omus
Copy link
Member Author

omus commented Aug 12, 2017

For now however I'll try to restore the original abending behaviour for this PR.

I've revised the PR to restore the original abort behaviour when the explicit credentials fail. In order to make sure I've kept the original behaviour I wrote several new tests to capture the existing behaviour with explicit credentials and the credential cache.

I'm currently testing the existing behaviour and noticed something strange. If you provide an explicit user/pass credential and the callback expects an SSH credential you get a warning about the credential being incompatible. However, if you supply a SSH credential and the callback expects a user/pass credential the callback will end up ignoring the explicit credential.

I'll make sure to make this behaviour consistent.

Explicit credentials which don't match the requested authentication method now always error the same way.

@@ -183,12 +185,16 @@ Matches the [`git_remote_callbacks`](https://libgit2.github.com/libgit2/#HEAD/ty
payload::Ptr{Void}
end

function RemoteCallbacks(credentials::Ptr{Void}, payload::Ref{Nullable{AbstractCredentials}})
RemoteCallbacks(credentials=credentials, payload=pointer_from_objref(payload))
function RemoteCallbacks(credentials_cb::Ptr{Void}, payload::Ref{Payload})
Copy link
Contributor

Choose a reason for hiding this comment

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

should this be Ref{<:Payload} ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure. I can also change the constructor below to use Ref(...) instead of Ref{Payload}(...)

@omus
Copy link
Member Author

omus commented Aug 15, 2017

Any additional comments? I think I'll merge this later tomorrow.

LibGit2 credential callback now always uses a CredentialPayload struct
which allows us keep callback state separate from credentials.
Implementation at this point is minimal to allow us to more thoroughly
test the existing behaviour.
The two code paths for handling the the SSH and username/password
`allowed_types` differ enough that some bugs have cropped up. These
changes make the two code paths nearly identical which should remove
any inconsistences.
@omus
Copy link
Member Author

omus commented Aug 15, 2017

Rebased just to test against Circle CI. Will merge after the CI finishes

@omus
Copy link
Member Author

omus commented Aug 16, 2017

So much for all my green check marks. Prior to rebasing only Circle CI was failing due to the lack of configuration file. The latest has a unrelated failures on AppVeyor and the Travis CI on Mac had a failure with spawn. Going ahead with merge.

@omus omus merged commit be74e58 into master Aug 16, 2017
@omus omus deleted the cv/credential-payload branch August 16, 2017 01:07
@StefanKarpinski
Copy link
Sponsor Member

Since @travis-ci has been such a disaster lately, we should consider it ok as long as Circle CI or Travis passes, not both. We should probably see about getting Mac testing on Circle CI.

@tkelman
Copy link
Contributor

tkelman commented Aug 16, 2017

most of the mac failures we hit are julia bugs and would happen anywhere

@tkelman
Copy link
Contributor

tkelman commented Aug 16, 2017

circle also doesn't currently support multi os matrix builds the way travis does, as I understand it. they may add support for that at some future time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libgit2 The libgit2 library or the LibGit2 stdlib module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants