From a74feb09012c079aca115365351e47c0fe204571 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Thu, 16 Jul 2015 02:07:08 +0200 Subject: [PATCH] Add support for SSH credentials from memory. --- ext/rugged/rugged_cred.c | 49 ++++++++++++++++++++++++++++----------- lib/rugged/credentials.rb | 10 ++++++++ test/online/clone_test.rb | 10 ++++++++ test/online/fetch_test.rb | 10 ++++++++ test/test_helper.rb | 9 +++++++ 5 files changed, 75 insertions(+), 13 deletions(-) diff --git a/ext/rugged/rugged_cred.c b/ext/rugged/rugged_cred.c index eeebf06d4..43ee42437 100644 --- a/ext/rugged/rugged_cred.c +++ b/ext/rugged/rugged_cred.c @@ -29,6 +29,7 @@ VALUE rb_mRuggedCred; VALUE rb_cRuggedCredUserPassword; VALUE rb_cRuggedCredSshKey; VALUE rb_cRuggedCredSshKeyFromAgent; +VALUE rb_cRuggedCredSshKeyFromMemory; VALUE rb_cRuggedCredDefault; static void rugged_cred_extract_userpass(git_cred **cred, VALUE rb_credential) @@ -47,8 +48,10 @@ static void rugged_cred_extract_userpass(git_cred **cred, VALUE rb_credential) ); } -static void rugged_cred_extract_ssh_key(git_cred **cred, VALUE rb_credential) +static void rugged_cred_extract_ssh_key(git_cred **cred, VALUE rb_credential, int memory) { + int error; + VALUE rb_username = rb_iv_get(rb_credential, "@username"); VALUE rb_publickey = rb_iv_get(rb_credential, "@publickey"); VALUE rb_privatekey = rb_iv_get(rb_credential, "@privatekey"); @@ -62,17 +65,26 @@ static void rugged_cred_extract_ssh_key(git_cred **cred, VALUE rb_credential) if (!NIL_P(rb_passphrase)) Check_Type(rb_passphrase, T_STRING); - rugged_exception_check( - git_cred_ssh_key_new(cred, + if (memory) { + error = git_cred_ssh_key_memory_new(cred, StringValueCStr(rb_username), NIL_P(rb_publickey) ? NULL : StringValueCStr(rb_publickey), StringValueCStr(rb_privatekey), NIL_P(rb_passphrase) ? NULL : StringValueCStr(rb_passphrase) - ) - ); + ); + } else { + error = git_cred_ssh_key_new(cred, + StringValueCStr(rb_username), + NIL_P(rb_publickey) ? NULL : StringValueCStr(rb_publickey), + StringValueCStr(rb_privatekey), + NIL_P(rb_passphrase) ? NULL : StringValueCStr(rb_passphrase) + ); + } + + rugged_exception_check(error); } -static void rugged_credential_extract_ssh_key_from_agent(git_cred **cred, VALUE rb_credential) +static void rugged_cred_extract_ssh_key_from_agent(git_cred **cred, VALUE rb_credential) { VALUE rb_username = rb_iv_get(rb_credential, "@username"); @@ -117,7 +129,17 @@ void rugged_cred_extract(git_cred **cred, int allowed_types, VALUE rb_credential if (!(allowed_types & GIT_CREDTYPE_SSH_KEY)) rb_raise(rb_eArgError, "Invalid credential type"); - rugged_cred_extract_ssh_key(cred, rb_credential); + rugged_cred_extract_ssh_key(cred, rb_credential, 0); + } else if (rb_obj_is_kind_of(rb_credential, rb_cRuggedCredSshKeyFromMemory)) { + if (allowed_types & GIT_CREDTYPE_USERNAME) { + rugged_cred_extract_username(cred, rb_credential); + return; + } + + if (!(allowed_types & GIT_CREDTYPE_SSH_KEY)) + rb_raise(rb_eArgError, "Invalid credential type"); + + rugged_cred_extract_ssh_key(cred, rb_credential, 1); } else if (rb_obj_is_kind_of(rb_credential, rb_cRuggedCredSshKeyFromAgent)) { if (allowed_types & GIT_CREDTYPE_USERNAME) { rugged_cred_extract_username(cred, rb_credential); @@ -127,7 +149,7 @@ void rugged_cred_extract(git_cred **cred, int allowed_types, VALUE rb_credential if (!(allowed_types & GIT_CREDTYPE_SSH_KEY)) rb_raise(rb_eArgError, "Invalid credential type"); - rugged_credential_extract_ssh_key_from_agent(cred, rb_credential); + rugged_cred_extract_ssh_key_from_agent(cred, rb_credential); } else if (rb_obj_is_kind_of(rb_credential, rb_cRuggedCredDefault)) { if (!(allowed_types & GIT_CREDTYPE_DEFAULT)) rb_raise(rb_eArgError, "Invalid credential type"); @@ -139,10 +161,11 @@ void rugged_cred_extract(git_cred **cred, int allowed_types, VALUE rb_credential void Init_rugged_cred(void) { - rb_mRuggedCred = rb_define_module_under(rb_mRugged, "Credentials"); + rb_mRuggedCred = rb_define_module_under(rb_mRugged, "Credentials"); - rb_cRuggedCredUserPassword = rb_define_class_under(rb_mRuggedCred, "UserPassword", rb_cObject); - rb_cRuggedCredSshKey = rb_define_class_under(rb_mRuggedCred, "SshKey", rb_cObject); - rb_cRuggedCredSshKeyFromAgent = rb_define_class_under(rb_mRuggedCred, "SshKeyFromAgent", rb_cObject); - rb_cRuggedCredDefault = rb_define_class_under(rb_mRuggedCred, "Default", rb_cObject); + rb_cRuggedCredUserPassword = rb_define_class_under(rb_mRuggedCred, "UserPassword", rb_cObject); + rb_cRuggedCredSshKey = rb_define_class_under(rb_mRuggedCred, "SshKey", rb_cObject); + rb_cRuggedCredSshKeyFromAgent = rb_define_class_under(rb_mRuggedCred, "SshKeyFromAgent", rb_cObject); + rb_cRuggedCredSshKeyFromMemory = rb_define_class_under(rb_mRuggedCred, "SshKeyFromMemory", rb_cObject); + rb_cRuggedCredDefault = rb_define_class_under(rb_mRuggedCred, "Default", rb_cObject); } diff --git a/lib/rugged/credentials.rb b/lib/rugged/credentials.rb index a68f8683e..07ed683d5 100644 --- a/lib/rugged/credentials.rb +++ b/lib/rugged/credentials.rb @@ -32,6 +32,16 @@ def call(url, username_from_url, allowed_types) end end + class SshKeyFromMemory + def initialize(options) + @username, @publickey, @privatekey, @passphrase = options[:username], options[:publickey], options[:privatekey], options[:passphrase] + end + + def call(url, username_from_url, allowed_types) + self + end + end + # A "default" credential usable for Negotiate mechanisms like NTLM or # Kerberos authentication class Default diff --git a/test/online/clone_test.rb b/test/online/clone_test.rb index 51d876849..e3006138d 100644 --- a/test/online/clone_test.rb +++ b/test/online/clone_test.rb @@ -22,6 +22,16 @@ def test_clone_over_ssh_with_credentials end end + def test_clone_over_ssh_with_credentials_from_memory + Dir.mktmpdir do |dir| + repo = Rugged::Repository.clone_at(ENV['GITTEST_REMOTE_SSH_URL'], dir, { + credentials: ssh_key_credential_from_memory + }) + + assert_instance_of Rugged::Repository, repo + end + end + def test_clone_over_ssh_with_credentials_from_agent Dir.mktmpdir do |dir| repo = Rugged::Repository.clone_at(ENV['GITTEST_REMOTE_SSH_URL'], dir, { diff --git a/test/online/fetch_test.rb b/test/online/fetch_test.rb index 6af8ea0fa..7db9e04c6 100644 --- a/test/online/fetch_test.rb +++ b/test/online/fetch_test.rb @@ -49,6 +49,16 @@ def test_fetch_over_ssh_with_credentials }) end + def test_fetch_over_ssh_with_credentials_from_memory + reset_remote_repo + + @repo.remotes.create("origin", ENV['GITTEST_REMOTE_SSH_URL']) + + @repo.fetch("origin", { + credentials: ssh_key_credential_from_memory + }) + end + def test_fetch_over_ssh_with_credentials_from_agent reset_remote_repo diff --git a/test/test_helper.rb b/test/test_helper.rb index 9126cdda8..3ffa4c0d1 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -87,6 +87,15 @@ def ssh_key_credential }) end + def ssh_key_credential_from_memory + Rugged::Credentials::SshKeyFromMemory.new({ + username: ENV["GITTEST_REMOTE_SSH_USER"], + publickey: ENV["GITTEST_REMOTE_SSH_PUBKEY"] ? File.read(ENV["GITTEST_REMOTE_SSH_PUBKEY"]) : nil, + privatekey: ENV["GITTEST_REMOTE_SSH_KEY"] ? File.read(ENV["GITTEST_REMOTE_SSH_KEY"]) : nil, + passphrase: ENV["GITTEST_REMOTE_SSH_PASSPHASE"], + }) + end + def ssh_key_credential_from_agent Rugged::Credentials::SshKeyFromAgent.new({ username: ENV["GITTEST_REMOTE_SSH_USER"]