Skip to content

Commit

Permalink
implement SshKeyFromMemory
Browse files Browse the repository at this point in the history
fixes libgit2gh-796

libgit2 already supports it.
  • Loading branch information
ccutrer committed May 9, 2019
1 parent 33873e5 commit dff2b6a
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 5 deletions.
47 changes: 42 additions & 5 deletions ext/rugged/rugged_cred.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern VALUE rb_mRugged;
VALUE rb_mRuggedCred;
VALUE rb_cRuggedCredUserPassword;
VALUE rb_cRuggedCredSshKey;
VALUE rb_cRuggedCredSshKeyFromMemory;
VALUE rb_cRuggedCredSshKeyFromAgent;
VALUE rb_cRuggedCredDefault;

Expand Down Expand Up @@ -55,6 +56,31 @@ static void rugged_cred_extract_ssh_key(git_cred **cred, VALUE rb_credential)
);
}

static void rugged_cred_extract_ssh_key_from_memory(git_cred **cred, VALUE rb_credential)
{
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");
VALUE rb_passphrase = rb_iv_get(rb_credential, "@passphrase");

Check_Type(rb_username, T_STRING);
Check_Type(rb_privatekey, T_STRING);

if (!NIL_P(rb_publickey))
Check_Type(rb_publickey, T_STRING);
if (!NIL_P(rb_passphrase))
Check_Type(rb_passphrase, T_STRING);

rugged_exception_check(
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)
)
);
}

static void rugged_credential_extract_ssh_key_from_agent(git_cred **cred, VALUE rb_credential)
{
VALUE rb_username = rb_iv_get(rb_credential, "@username");
Expand Down Expand Up @@ -101,6 +127,16 @@ void rugged_cred_extract(git_cred **cred, int allowed_types, VALUE rb_credential
rb_raise(rb_eArgError, "Invalid credential type");

rugged_cred_extract_ssh_key(cred, rb_credential);
} 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_from_memory(cred, rb_credential);
} else if (rb_obj_is_kind_of(rb_credential, rb_cRuggedCredSshKeyFromAgent)) {
if (allowed_types & GIT_CREDTYPE_USERNAME) {
rugged_cred_extract_username(cred, rb_credential);
Expand All @@ -122,10 +158,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_cRuggedCredSshKeyFromMemory = rb_define_class_under(rb_mRuggedCred, "SshKeyFromMemory", rb_cObject);
rb_cRuggedCredSshKeyFromAgent = rb_define_class_under(rb_mRuggedCred, "SshKeyFromAgent", rb_cObject);
rb_cRuggedCredDefault = rb_define_class_under(rb_mRuggedCred, "Default", rb_cObject);
}
13 changes: 13 additions & 0 deletions lib/rugged/credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def call(url, username_from_url, allowed_types)
end

# A ssh key credential object that can optionally be passphrase-protected
# publickey and privatekey are filenames that will be opened to load the key
class SshKey
def initialize(options)
@username, @publickey, @privatekey, @passphrase = options[:username], options[:publickey], options[:privatekey], options[:passphrase]
Expand All @@ -27,6 +28,18 @@ def call(url, username_from_url, allowed_types)
end
end

# A ssh key credential object that can optionally be passphrase-protected
# publickey and privatekey are string that are the actual contents of the key
class SshKeyFromMemory
def initialize(options)
@username, @publickey, @privatekey, @passphrase = options[:username], options[:publickey], options[:privatekey], options[:passphrase]
end

def call(*)
self
end
end

class SshKeyFromAgent
def initialize(options)
@username = options[:username]
Expand Down
10 changes: 10 additions & 0 deletions test/online/clone_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ def test_clone_over_ssh_with_credentials
end
end

def test_clone_over_ssh_with_credentials
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, {
Expand Down
8 changes: 8 additions & 0 deletions test/online/fetch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ def test_fetch_over_ssh_with_credentials
})
end

def test_fetch_over_ssh_with_credentials_from_memory
@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
@repo.remotes.create("origin", ENV['GITTEST_REMOTE_SSH_URL'])

Expand Down
9 changes: 9 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ def ssh_key_credential
})
end

def ssh_key_credential_from_memory
Rugged::Credentials::SshKeyFromMemory.new({
username: ENV["GITTEST_REMOTE_SSH_USER"],
publickey: File.read(ENV["GITTEST_REMOTE_SSH_PUBKEY"]),
privatekey: File.read(ENV["GITTEST_REMOTE_SSH_KEY"]),
passphrase: ENV["GITTEST_REMOTE_SSH_PASSPHASE"],
})
end

def ssh_key_credential_from_agent
Rugged::Credentials::SshKeyFromAgent.new({
username: ENV["GITTEST_REMOTE_SSH_USER"]
Expand Down

0 comments on commit dff2b6a

Please sign in to comment.