communicators/ssh: insert random key, remove insecure key

This commit is contained in:
Mitchell Hashimoto 2014-10-24 09:58:18 -07:00
parent f4dec575ed
commit 94b2a8a56b
5 changed files with 89 additions and 10 deletions

View File

@ -620,6 +620,10 @@ module Vagrant
error_key(:ssh_invalid_shell) error_key(:ssh_invalid_shell)
end end
class SSHInsertKeyUnsupported < VagrantError
error_key(:ssh_insert_key_unsupported)
end
class SSHIsPuttyLink < VagrantError class SSHIsPuttyLink < VagrantError
error_key(:ssh_is_putty_link) error_key(:ssh_is_putty_link)
end end

View File

@ -11,6 +11,7 @@ require 'net/scp'
require 'vagrant/util/ansi_escape_code_remover' require 'vagrant/util/ansi_escape_code_remover'
require 'vagrant/util/file_mode' require 'vagrant/util/file_mode'
require 'vagrant/util/keypair'
require 'vagrant/util/platform' require 'vagrant/util/platform'
require 'vagrant/util/retryable' require 'vagrant/util/retryable'
@ -88,6 +89,8 @@ module VagrantPlugins
raise raise
rescue Vagrant::Errors::SSHKeyBadPermissions rescue Vagrant::Errors::SSHKeyBadPermissions
raise raise
rescue Vagrant::Errors::SSHInsertKeyUnsupported
raise
rescue Vagrant::Errors::VagrantError => e rescue Vagrant::Errors::VagrantError => e
# Ignore it, SSH is not ready, some other error. # Ignore it, SSH is not ready, some other error.
end end
@ -142,20 +145,41 @@ module VagrantPlugins
# If we used a password, then insert the insecure key # If we used a password, then insert the insecure key
ssh_info = @machine.ssh_info ssh_info = @machine.ssh_info
if ssh_info[:password] && ssh_info[:private_key_path].empty? insert = ssh_info[:password] && ssh_info[:private_key_path].empty?
@logger.info("Inserting insecure key to avoid password") ssh_info[:private_key_path].each do |pk|
@machine.ui.info(I18n.t("vagrant.inserting_insecure_key")) if insecure_key?(pk)
@machine.guest.capability( insert = true
:insert_public_key, @machine.ui.detail("\n"+I18n.t("vagrant.inserting_insecure_detected"))
Vagrant.source_root.join("keys", "vagrant.pub").read.chomp) break
end
end
if insert
# If we don't have the power to insert/remove keys, then its an error
cap = @machine.guest.capability?(:insert_public_key) &&
@machine.guest.capability?(:remove_public_key)
raise Vagrant::Errors::SSHInsertKeyUnsupported if !cap
_pub, priv, openssh = Vagrant::Util::Keypair.create
@logger.info("Inserting key to avoid password: #{openssh}")
@machine.ui.detail("\n"+I18n.t("vagrant.inserting_random_key"))
@machine.guest.capability(:insert_public_key, openssh)
# Write out the private key in the data dir so that the # Write out the private key in the data dir so that the
# machine automatically picks it up. # machine automatically picks it up.
@machine.data_dir.join("private_key").open("w+") do |f| @machine.data_dir.join("private_key").open("w+") do |f|
f.write(Vagrant.source_root.join("keys", "vagrant").read) f.write(priv)
end end
@machine.ui.info(I18n.t("vagrant.inserted_key")) # Remove the old key if it exists
@machine.ui.detail(I18n.t("vagrant.inserting_remove_key"))
@machine.guest.capability(
:remove_public_key,
Vagrant.source_root.join("keys", "vagrant.pub").read.chomp)
# Done, restart.
@machine.ui.detail(I18n.t("vagrant.inserted_key"))
@connection.close @connection.close
@connection = nil @connection = nil
@ -597,6 +621,16 @@ module VagrantPlugins
# Otherwise, just raise the error up # Otherwise, just raise the error up
raise raise
end end
# This will test whether path is the Vagrant insecure private key.
#
# @param [String] path
def insecure_key?(path)
return false if !path
return false if !File.file?(path)
source_path = Vagrant.source_root.join("keys", "vagrant")
return File.read(path).chomp == source_path.read.chomp
end
end end
end end
end end

View File

@ -0,0 +1,21 @@
require "vagrant/util/shell_quote"
module VagrantPlugins
module GuestLinux
module Cap
class RemovePublicKey
def self.remove_public_key(machine, contents)
contents = contents.chomp
contents = Vagrant::Util::ShellQuote.escape(contents, "'")
machine.communicate.tap do |comm|
if comm.test("test -f ~/.ssh/authorized_keys")
comm.execute(
"sed -i '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys")
end
end
end
end
end
end
end

View File

@ -62,6 +62,11 @@ module VagrantPlugins
Cap::ReadIPAddress Cap::ReadIPAddress
end end
guest_capability("linux", "remove_public_key") do
require_relative "cap/remove_public_key"
Cap::RemovePublicKey
end
guest_capability("linux", "rsync_installed") do guest_capability("linux", "rsync_installed") do
require_relative "cap/rsync" require_relative "cap/rsync"
Cap::RSync Cap::RSync

View File

@ -130,8 +130,13 @@ en:
Starting Docker containers... Starting Docker containers...
inserted_key: |- inserted_key: |-
Key inserted! Disconnecting and reconnecting using new SSH key... Key inserted! Disconnecting and reconnecting using new SSH key...
inserting_insecure_key: |- inserting_insecure_detected: |-
Inserting Vagrant public key within guest... Vagrant insecure key detected. Vagrant will automatically replace
this with a newly generated keypair for better security.
inserting_random_key: |-
Inserting generated public key within guest...
inserting_remove_key: |-
Removing insecure key from the guest if its present...
list_commands: |- list_commands: |-
Below is a listing of all available Vagrant commands and a brief Below is a listing of all available Vagrant commands and a brief
description of what they do. description of what they do.
@ -1071,6 +1076,16 @@ en:
using a shell that is unavailable on the system. Please verify using a shell that is unavailable on the system. Please verify
you're using the full path to the shell and that the shell is you're using the full path to the shell and that the shell is
executable by the SSH user. executable by the SSH user.
ssh_insert_key_unsupported: |-
Vagrant is configured to generate a random keypair and insert it
onto the guest machine, but it appears Vagrant doesn't know how to do
this with your guest OS. Please disable key insertion by setting
`config.ssh.insert_key = false` in the Vagrantfile.
After doing so, run `vagrant reload` for the setting to take effect.
If you'd like Vagrant to learn how to insert keys on this OS, please
open an issue with details about your environment.
ssh_is_putty_link: |- ssh_is_putty_link: |-
The `ssh` executable found in the PATH is a PuTTY Link SSH client. The `ssh` executable found in the PATH is a PuTTY Link SSH client.
Vagrant is only compatible with OpenSSH SSH clients. Please install Vagrant is only compatible with OpenSSH SSH clients. Please install