Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- extra/device2yaml.rb: fix \r being removed at end of line (@robertcheramy)
- perle: remove trailing \r (the device sends \r\r\n) (@robertcheramy)
- Reintroduce support for Ruby 3.0. Fixes #3688 (@robertcheramy)
- githubrepo: fix authentication with ssh-agent not working. Fixes #3420 (@robertcheramy)


## [0.35.0 - 2025-12-04]
Expand Down
3 changes: 2 additions & 1 deletion lib/oxidized/hook/githubrepo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def fetch_and_merge_remote(repo, creds)
private

def credentials(node)
Proc.new do |_url, username_from_url, _allowed_types| # rubocop:disable Style/Proc
proc do |_url, username_from_url, _allowed_types|
git_user = cfg.has_key?('username') ? cfg.username : (username_from_url || 'git')
if cfg.has_key?('password')
logger.debug "Authenticating using username and password as '#{git_user}'"
Expand All @@ -96,6 +96,7 @@ def credentials(node)
logger.debug "Authenticating using ssh keys as '#{git_user}'"
rugged_sshkey(git_user: git_user, privkey: cfg.privatekey, pubkey: pubkey)
elsif cfg.has_key?('remote_repo') &&
cfg.remote_repo.respond_to?(:has_key?) &&
cfg.remote_repo.has_key?(node.group) &&
cfg.remote_repo[node.group].has_key?('privatekey')
pubkey = cfg.remote_repo[node.group].has_key?('publickey') ? cfg.remote_repo[node.group].publickey : nil
Expand Down
115 changes: 115 additions & 0 deletions spec/hook/githubrepo_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,119 @@
end
end
end

describe '#credentials' do
before do
@node = mock('node')
@node.stubs(:group).returns('gr1')
@node.stubs(:name).returns('test_node')
@cfg = Oxidized.config.output.push_to_remote
end

it "returns UserPassword when username and password are configured" do
@cfg.username = 'testuser'
@cfg.password = '****'
@cfg.remote_repo = 'https://example.com/test/repo.git'

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)
result = credproc.call('https://example.com/test/repo.git', 'git',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::UserPassword
_(result.instance_variable_get(:@username)).must_equal 'testuser'
_(result.instance_variable_get(:@password)).must_equal '****'
end

it "returns UserPassword with url user when only password is configured" do
@cfg.password = '****'
@cfg.remote_repo = 'oxidized@example.com/test/repo.git'

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)
result = credproc.call('oxidized@example.com/test/repo.git', 'oxidized',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::UserPassword
_(result.instance_variable_get(:@username)).must_equal 'oxidized'
_(result.instance_variable_get(:@password)).must_equal '****'
end

it "returns UserPassword when only password is configured" do
@cfg.password = '****'
@cfg.remote_repo = 'https://example.com/test/repo.git'

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)
result = credproc.call('https://example.com/test/repo.git', nil,
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::UserPassword
_(result.instance_variable_get(:@username)).must_equal 'git'
_(result.instance_variable_get(:@password)).must_equal '****'
end

it "returns SshKey with both public and private keys" do
@cfg.privatekey = '/path/to/private_key'
@cfg.publickey = 'public_key'
@cfg.remote_repo = 'g@example.com/repo.git'
File.expects(:expand_path).with('/path/to/private_key').returns('/path/to/private_key')
File.expects(:expand_path).with('public_key').returns('/expanded/public_key')

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)

result = credproc.call('g@example.com/repo.git', 'g',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::SshKey
_(result.instance_variable_get(:@username)).must_equal 'g'
_(result.instance_variable_get(:@privatekey)).must_equal '/path/to/private_key'
_(result.instance_variable_get(:@publickey)).must_equal '/expanded/public_key'
end

it "returns SshKey with a private key only" do
@cfg.privatekey = '/path/to/private_key'
@cfg.remote_repo = 'g@example.com/repo.git'
File.expects(:expand_path).with('/path/to/private_key').returns('/path/to/private_key')
File.expects(:expand_path).with('/path/to/private_key.pub').returns('/path/to/private_key.pub')

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)

result = credproc.call('g@example.com/repo.git', 'g',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::SshKey
_(result.instance_variable_get(:@username)).must_equal 'g'
_(result.instance_variable_get(:@privatekey)).must_equal '/path/to/private_key'
_(result.instance_variable_get(:@publickey)).must_equal '/path/to/private_key.pub'
end

it "returns SshKey with group-specific SSH keys" do
@cfg.remote_repo.routers.url = 'g@example.com/routers.git'
@cfg.remote_repo.routers.privatekey = '/path/to/private_key'
@cfg.remote_repo.routers.publickey = '/path/to/public_key'
@node.stubs(:group).returns('routers')
File.expects(:expand_path).with('/path/to/private_key').returns('/path/to/private_key')
File.expects(:expand_path).with('/path/to/public_key').returns('/path/to/public_key')

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)

result = credproc.call('g@example.com/routers.git', 'g',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::SshKey
_(result.instance_variable_get(:@username)).must_equal 'g'
_(result.instance_variable_get(:@privatekey)).must_equal '/path/to/private_key'
_(result.instance_variable_get(:@publickey)).must_equal '/path/to/public_key'
end

it "returns SshKeyFromAgent if no password or private key are defined" do
@cfg.remote_repo = 'g@example.com/repo.git'

gr.cfg = @cfg
credproc = gr.send(:credentials, @node)

result = credproc.call('g@example.com/repo.git', 'g',
%i[ssh_key plaintext])
_(result).must_be_instance_of Rugged::Credentials::SshKeyFromAgent
_(result.instance_variable_get(:@username)).must_equal 'g'
end
end
end