diff options
author | Bryan McLellan <btm@loftninjas.org> | 2019-05-13 16:01:51 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-13 16:01:51 -0400 |
commit | db18ba559e44e919f320e36f8ed62eb19c77676a (patch) | |
tree | 8fdf014ef29494fc382506592a41049f946aab41 | |
parent | 8c986011e05aaf6043bcb8fe82f04a5ea7472a64 (diff) | |
parent | 0a1a78f404dcd2c8f1405e9e5af26dd80155ff6b (diff) | |
download | chef-db18ba559e44e919f320e36f8ed62eb19c77676a.tar.gz |
Merge pull request #8524 from chef/btm/retry-fingerprint
Use new Net:SSH host key verify values
-rw-r--r-- | RELEASE_NOTES.md | 3 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap.rb | 48 | ||||
-rw-r--r-- | spec/unit/knife/bootstrap_spec.rb | 4 |
3 files changed, 33 insertions, 22 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6531e522db..510fc71e08 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -204,12 +204,13 @@ In order to accommodate a combined bootstrap that supports both SSH and WinRM, s | --connection-user | user to authenticate as, regardless of protocol | | --connection-password| Password to authenticate as, regardless of protocol | | --connection-port | port to connect to, regardless of protocol | +| --ssh-verify-host-key VALUE | Verify host key. Default is 'always'. Valid values are 'accept', 'accept\_new', 'accept\_new\_or\_local\_tunnel', and 'never'. | #### Changed Flags | Flag | New Option | Notes | |-----:|:-----------|:------| -| --[no-]host-key-verify |--[no-]ssh-verify-host-key| | +| --[no-]host-key-verify |--ssh-verify-host-key VALUE | See above for valid values. | | --forward-agent | --ssh-forward-agent| | | --session-timeout MINUTES | --session-timeout SECONDS|New for ssh, existing for winrm. The unit has changed from MINUTES to SECONDS for consistency with other timeouts.| | --ssh-password | --connection-password | | diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index e143ebfe31..04eabc3c83 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -31,15 +31,6 @@ class Chef SUPPORTED_CONNECTION_PROTOCOLS = %w{ssh winrm}.freeze WINRM_AUTH_PROTOCOL_LIST = %w{plaintext kerberos ssl negotiate}.freeze - # @param opt_arry [Array] - # - # @return [String] a friendly quoted list of items complete with "and" - def self.friendly_opt_list(opt_array) - opts = opt_array.map { |x| "'#{x}'" } - return opts.join(" and ") if opts.size < 3 - opts[0..-2].join(", ") + " and " + opts[-1] - end - # Common connectivity options option :connection_user, short: "-U USERNAME", @@ -59,7 +50,8 @@ class Chef option :connection_protocol, short: "-o PROTOCOL", long: "--connection-protocol PROTOCOL", - description: "The protocol to use to connect to the target node. Supports: #{friendly_opt_list(SUPPORTED_CONNECTION_PROTOCOLS)}." + description: "The protocol to use to connect to the target node.", + in: SUPPORTED_CONNECTION_PROTOCOLS option :max_wait, short: "-W SECONDS", @@ -88,7 +80,7 @@ class Chef option :winrm_auth_method, short: "-w AUTH-METHOD", long: "--winrm-auth-method AUTH-METHOD", - description: "The WinRM authentication method to use. Valid choices are #{friendly_opt_list(WINRM_AUTH_PROTOCOL_LIST)}.", + description: "The WinRM authentication method to use.", proc: Proc.new { |protocol| Chef::Config[:knife][:winrm_auth_method] = protocol }, in: WINRM_AUTH_PROTOCOL_LIST @@ -146,9 +138,9 @@ class Chef description: "The SSH identity file used for authentication." option :ssh_verify_host_key, - long: "--[no-]ssh-verify-host-key", - description: "Verify host key, enabled by default.", - boolean: true + long: "--ssh-verify-host-key VALUE", + description: "Verify host key. Default is 'always'.", + in: %w{always accept_new accept_new_or_local_tunnel never} # # bootstrap options @@ -162,7 +154,7 @@ class Chef option :channel, long: "--channel CHANNEL", - description: "Install from the given channel. Valid values are 'stable, 'current', and 'unstable'. Default is 'stable'", + description: "Install from the given channel. Default is 'stable'.", default: "stable", in: %w{stable current unstable} @@ -550,6 +542,7 @@ class Chef $stdout.sync = true register_client connect! + unless client_builder.client_path.nil? bootstrap_context.client_pem = client_builder.client_path end @@ -599,6 +592,24 @@ class Chef ui.info("Connecting to #{ui.color(server_name, :bold)}") opts = connection_opts.dup do_connect(opts) + rescue Train::Transports::SSHFailed => e + if e.message =~ /fingerprint (\S+) is unknown for "(.+)"/ + fingerprint = $1 + hostname, ip = $2.split(",") + # TODO: convert the SHA256 base64 value to hex with colons + # 'ssh' example output: + # RSA key fingerprint is e5:cb:c0:e2:21:3b:12:52:f8:ce:cb:00:24:e2:0c:92. + # ECDSA key fingerprint is 5d:67:61:08:a9:d7:01:fd:5e:ae:7e:09:40:ef:c0:3c. + puts "The authenticity of host '#{hostname} (#{ip})' can't be established." + puts "fingerprint is #{fingerprint}." + ui.confirm("Are you sure you want to continue connecting") # will exit 3 on N + # FIXME: this should save the key to known_hosts but doesn't appear to be + config[:ssh_verify_host_key] = :accept_new + connection_opts(reset: true) + retry + end + + raise e rescue Train::Error => e require "net/ssh" if e.cause && e.cause.class == Net::SSH::AuthenticationFailed @@ -781,8 +792,8 @@ class Chef # @return a configuration hash suitable for connecting to the remote # host via train - def connection_opts - return @connection_opts unless @connection_opts.nil? + def connection_opts(reset: false) + return @connection_opts unless @connection_opts.nil? || reset == true @connection_opts = {} @connection_opts.merge! base_opts @connection_opts.merge! host_verify_opts @@ -824,8 +835,7 @@ class Chef { self_signed: config_value(:winrm_no_verify_cert) === true } elsif ssh? # Fall back to the old knife config key name for back compat. - { verify_host_key: config_value(:ssh_verify_host_key, - :host_key_verify, true) === true } + { verify_host_key: config_value(:ssh_verify_host_key, :host_key_verify, "always") } else {} end diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index 5280e3b64b..c45604b7d1 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -1131,7 +1131,7 @@ describe Chef::Knife::Bootstrap do logger: Chef::Log, keys_only: false, sudo: false, - verify_host_key: true, + verify_host_key: "always", non_interactive: true, } end @@ -1229,7 +1229,7 @@ describe Chef::Knife::Bootstrap do expect(knife.host_verify_opts).to eq( { verify_host_key: false } ) end it "provides a correct default when no option given" do - expect(knife.host_verify_opts).to eq( { verify_host_key: true } ) + expect(knife.host_verify_opts).to eq( { verify_host_key: "always" } ) end end end |