Skip to content

Commit 8013da4

Browse files
committed
Offer only the deployment key when ssh-ing to instances
Net::SSH fills in identity sources the caller does not name: every IdentityFile from ~/.ssh/config, which it tries ahead of :key_data, and every identity held by a reachable ssh-agent. On a workstation with a 'Host *' block or a loaded agent that is enough extra identities to exhaust the target sshd's MaxAuthTries, so the server disconnects and the example dies with 'Too many authentication failures'. Pin the identity set to the key BATs was given. :keys_only on its own does not do it: it filters agent identities but leaves the ones the config file contributed, so :keys has to be cleared as well. Parsing of ~/.ssh/config stays on, so directives such as ProxyJump and Port keep working.
1 parent 31057b3 commit 8013da4

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

lib/bat/bosh_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ def ssh(host, user, command, options = {})
6363
raise 'Need to set ssh :private_key' if options[:private_key].nil?
6464
ssh_options[:key_data] = [options[:private_key]]
6565

66+
# Offer the deployment's key and nothing else. Net::SSH otherwise adds
67+
# every IdentityFile from ~/.ssh/config, which it tries before :key_data,
68+
# plus every identity loaded in the ssh-agent. Enough extra identities
69+
# exhaust the target sshd's MaxAuthTries and it disconnects the example
70+
# with "Too many authentication failures". :keys_only alone is not
71+
# enough: it filters agent identities but not the config file's.
72+
ssh_options[:keys] = []
73+
ssh_options[:keys_only] = true
74+
ssh_options[:use_agent] = false
75+
6676
@logger.info("--> ssh options: #{ssh_options.inspect}")
6777

6878
if options[:gateway_host] && options[:gateway_username]

spec/bat/bosh_helper_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@
4949
end
5050
end
5151

52+
describe '#ssh' do
53+
it 'offers the given private key and no other identity' do
54+
captured = nil
55+
allow(Net::SSH).to receive(:start) { |_host, _user, options| captured = options }
56+
57+
bosh_helper.ssh('10.0.0.1', 'vcap', 'echo hello', private_key: 'private')
58+
59+
expect(captured[:key_data]).to eq(['private'])
60+
expect(captured[:keys]).to eq([])
61+
expect(captured[:keys_only]).to be(true)
62+
expect(captured[:use_agent]).to be(false)
63+
end
64+
end
65+
5266
describe 'persistent_disk' do
5367
let(:job_name) { 'some-job' }
5468
let(:job_index) { 'some-index' }

0 commit comments

Comments
 (0)