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

implement SshKeyFromMemory #797

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

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

This will work as long as we keep compiling against libssh2 which itself is built aginst openssl, but otherwise we'll start seeing errors in test.

})
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