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 support for SSH credentials from memory. #501

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
49 changes: 36 additions & 13 deletions ext/rugged/rugged_cred.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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");
Expand All @@ -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");

Expand Down Expand Up @@ -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);
Expand All @@ -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");
Expand All @@ -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);
}
10 changes: 10 additions & 0 deletions lib/rugged/credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
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_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, {
Expand Down
10 changes: 10 additions & 0 deletions test/online/fetch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down