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

authenticate using ssh agent #424

Merged
merged 2 commits into from
Oct 10, 2014
Merged

Conversation

kyriakosoikonomakos
Copy link
Contributor

Introduce the ability for pygit2 to use the SSH agent for authentication.

Example use:
import pygit2
x = pygit2.credentials.SSHKeyFromAgent('git')
r = pygit2.clone_repository('ssh://git@github.com/some-org/some-repo', '/tmp/something', credentials=x)

@carlosmn
Copy link
Member

Neat, but the naming doesn't match the ssh keypair constructor we already have. The class for the full ssh keypair is Keypair, and this is about getting that from the agent, so this should either be KeypairFromAgent or Keypair should change.

Have you considered having a static method in Keypair to act as a constructor, so we can use it like Keypair.from_agent('git') since this is about working with a Keypair as well?

@kyriakosoikonomakos
Copy link
Contributor Author

@carlosmn does that look better?

@carlosmn
Copy link
Member

Yeah. Though you took both of my suggestions when I meant them as alternatives. Having simply KeypairFromAgent without Keypair.from_agent() is fine.

What I was thinking a an alternative to that was having Keypair.from_agent() (as @staticmethod) return a new Keypair with None keys so the if check happens on the key fields rather than on the type.

But having the KeypairFromAgent is maybe clearer in its usage, so having just that without from_agent() would work better.

@kyriakosoikonomakos
Copy link
Contributor Author

@carlosmn Done.

class KeypairFromAgent(Keypair):
def __init__(self, username):
self._username = username
super(KeypairFromAgent, self).__init__(username, None, None, None)
Copy link
Member

Choose a reason for hiding this comment

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

One of these lies is redundant. If we're going to rely on the superclass' constructor, then there's no need for us to store the username explicitly.

@ashb
Copy link
Contributor

ashb commented Sep 15, 2014

@carlosmn Thanks

I've removed that redundant line and rebased everything down to one commit (my personal preference since the overall change is small. If we want it back the commit pre-force push was 4b9fe1c)

@jbiel
Copy link

jbiel commented Sep 24, 2014

Thanks for this patch!

@ashb
Copy link
Contributor

ashb commented Sep 25, 2014

@carlosmn Anything outstanding to get this merged or do is it just a matter of you having the cycles to take a look (I know that feeling)?

err = C.git_cred_ssh_key_new(ccred, to_bytes(name), to_bytes(pubkey),
to_bytes(privkey), to_bytes(passphrase))

if isinstance(creds, KeypairFromAgent):
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather see this choose based on the values returned from .credential_tuple rather than based on inheritance. It's not too big a deal, but the idea behind these is that each instance tells us about what it's doing, rather than rely on the type.

Copy link
Contributor

Choose a reason for hiding this comment

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

We thought about this and weren't sure which way to go. The only thing useful we could detect is tuple[1:] are all None. We went with this way as this is what the Ruby libgit2 bindings do.

Happy to change this to trigger off pubkey & privkey being None instead if you'd prefer.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that's how I'd go. This is designed so you can use your own classes which get the data from wherever you need (disc, the user, a database, whatever), and there's no need for them to hang off of these classes, all they need to do is have this attribute with the data we need.

Copy link
Contributor

Choose a reason for hiding this comment

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

So something like this diff then?

@@ -455,9 +456,13 @@ def get_credentials(fn, url, username, allowed):

     elif cred_type == C.GIT_CREDTYPE_SSH_KEY:
        name, pubkey, privkey, passphrase = creds.credential_tuple
-        err = C.git_cred_ssh_key_new(ccred, to_bytes(name), to_bytes(pubkey),
-                                     to_bytes(privkey), to_bytes(passphrase))
-
+        if pubkey is None and privkey is None:
+            err = C.git_cred_ssh_key_from_agent(ccred, to_bytes(name))
+        else:
+            err = C.git_cred_ssh_key_new(ccred, to_bytes(name),
+                                         to_bytes(pubkey), to_bytes(privkey),
+                                         to_bytes(passphrase))
     else:
         raise TypeError("unsupported credential type")

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that should work just fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

I've made this change now.

@carlosmn
Copy link
Member

carlosmn commented Oct 7, 2014

Great, 👍

@jdavid
Copy link
Member

jdavid commented Oct 8, 2014

If it is good for @carlosmn it is good for me, could you merge @carlosmn ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants