Skip to content

Commit

Permalink
Merge pull request #165 from chef/ap/add-agent-login
Browse files Browse the repository at this point in the history
Try to use ssh agent if no password or key files have been specified
  • Loading branch information
chris-rock authored Nov 29, 2016
2 parents 0404986 + 0d3702d commit 7cca326
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 9 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ end

group :tools do
gem 'pry', '~> 0.10'
gem 'rb-readline'
gem 'license_finder'
gem 'github_changelog_generator', '~> 1'
end
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ train = Train.create('ssh',
host: '1.2.3.4', port: 22, user: 'root', key_files: '/vagrant')
```

If you don't specify the `key_files` and `password` options, SSH agent authentication will be attempted. For example:

```ruby
require 'train'
train = Train.create('ssh', host: '1.2.3.4', port: 22, user: 'root')
```

**WinRM**

```ruby
Expand Down
28 changes: 22 additions & 6 deletions lib/train/transports/ssh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@ def validate_options(options)
super(options)

key_files = Array(options[:key_files])
if key_files.empty? and options[:password].nil?
fail Train::ClientError,
'You must configure at least one authentication method for SSH:'\
' Password or key.'
end

options[:auth_methods] ||= ['none']

unless key_files.empty?
Expand All @@ -100,6 +94,17 @@ def validate_options(options)
options[:auth_methods].push('password', 'keyboard-interactive')
end

if options[:auth_methods] == ['none']
if ssh_known_identities.empty?
fail Train::ClientError,
'You must configure at least one authentication method for SSH:'\
' Agent, Key or Password.'
else
logger.debug('[SSH] Using Agent keys as no password or key file have been specified')
options[:auth_methods].push('publickey')
end
end

if options[:pty]
logger.warn('[SSH] PTY requested: stderr will be merged into stdout')
end
Expand All @@ -108,6 +113,17 @@ def validate_options(options)
self
end

# Creates an SSH Authentication KeyManager instance and saves it for
# potential future reuse.
#
# @return [Hash] hash of SSH Known Identities
# @api private
def ssh_known_identities
# Force KeyManager to load the key(s)
@manager ||= Net::SSH::Authentication::KeyManager.new(nil).each_identity {}
@manager.known_identities
end

# Builds the hash of options needed by the Connection object on
# construction.
#
Expand Down
26 changes: 23 additions & 3 deletions test/unit/transports/ssh_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def detect_family
password: rand.to_s,
key_files: rand.to_s,
}}
let(:cls_agent) { cls.new({ host: rand.to_s }) }

describe 'default options' do
let(:ssh) { cls.new({ host: 'dummy' }) }
Expand Down Expand Up @@ -84,6 +85,26 @@ def detect_family
"root@#{conf[:host]}",
])
end

it 'sets the right auth_methods when password is specified' do
conf[:key_files] = nil
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "password", "keyboard-interactive"]
end

it 'sets the right auth_methods when keys are specified' do
conf[:password] = nil
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "publickey"]
end

it 'sets the right auth_methods for agent auth' do
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
cls_agent.connection.method(:options).call[:auth_methods].must_equal ['none', 'publickey']
end

it 'works with ssh agent auth' do
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
cls_agent.connection
end
end

describe 'converting connection to string for logging' do
Expand Down Expand Up @@ -111,9 +132,8 @@ def detect_family
end

it 'does not like key and password == nil' do
conf.delete(:password)
conf.delete(:key_files)
proc { cls.new(conf).connection }.must_raise Train::ClientError
cls_agent.stubs(:ssh_known_identities).returns({})
proc { cls_agent.connection }.must_raise Train::ClientError
end

it 'wont connect if it is not possible' do
Expand Down

0 comments on commit 7cca326

Please sign in to comment.