Class: Vagrant::SSH

Inherits:
Object
  • Object
show all
Includes:
Util::SafeExec
Defined in:
lib/vagrant/ssh.rb

Overview

Manages SSH connection information as well as allows opening an SSH connection.

Instance Method Summary collapse

Methods included from Util::SafeExec

#safe_exec

Constructor Details

#initialize(vm) ⇒ SSH

Returns a new instance of SSH.



13
14
15
16
# File 'lib/vagrant/ssh.rb', line 13

def initialize(vm)
  @vm     = vm
  @logger = Log4r::Logger.new("vagrant::ssh")
end

Instance Method Details

#check_key_permissions(key_path) ⇒ Object

Checks the file permissions for a private key, resetting them if needed.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/vagrant/ssh.rb', line 105

def check_key_permissions(key_path)
  # Windows systems don't have this issue
  return if Util::Platform.windows?

  @logger.debug("Checking key permissions: #{key_path}")
  stat = File.stat(key_path)

  if stat.owned? && Util::FileMode.from_octal(stat.mode) != "600"
    @logger.info("Attempting to correct key permissions to 0600")
    File.chmod(0600, key_path)

    if Util::FileMode.from_octal(stat.mode) != "600"
      raise Errors::SSHKeyBadPermissions, :key_path => key_path
    end
  end
rescue Errno::EPERM
  # This shouldn't happen since we verified we own the file, but
  # it is possible in theory, so we raise an error.
  raise Errors::SSHKeyBadPermissions, :key_path => key_path
end

#exec(opts = {}) ⇒ Object

Connects to the environment's virtual machine, replacing the ruby process with an SSH process.

Parameters:

  • opts (Hash) (defaults to: {})

    Options hash

Raises:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/vagrant/ssh.rb', line 54

def exec(opts={})
  # Get the SSH information and cache it here
  ssh_info = info

  if Util::Platform.windows?
    raise Errors::SSHUnavailableWindows, :host => ssh_info[:host],
                                         :port => ssh_info[:port],
                                         :username => ssh_info[:username],
                                         :key_path => ssh_info[:private_key_path]
  end

  raise Errors::SSHUnavailable if !Kernel.system("which ssh > /dev/null 2>&1")

  # If plain mode is enabled then we don't do any authentication (we don't
  # set a user or an identity file)
  plain_mode = opts[:plain_mode]

  options = {}
  options[:host] = ssh_info[:host]
  options[:port] = ssh_info[:port]
  options[:username] = ssh_info[:username]
  options[:private_key_path] = ssh_info[:private_key_path]

  # Command line options
  command_options = ["-p", options[:port].to_s, "-o", "UserKnownHostsFile=/dev/null",
                     "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR"]

  # Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option
  command_options += ["-o", "IdentitiesOnly=yes"] unless Util::Platform.solaris?

  command_options += ["-i", options[:private_key_path]] if !plain_mode
  command_options += ["-o", "ForwardAgent=yes"] if ssh_info[:forward_agent]

  # If there are extra options, then we append those
  command_options.concat(opts[:extra_args]) if opts[:extra_args]

  if ssh_info[:forward_x11]
    # Both are required so that no warnings are shown regarding X11
    command_options += ["-o", "ForwardX11=yes"]
    command_options += ["-o", "ForwardX11Trusted=yes"]
  end

  host_string = options[:host]
  host_string = "#{options[:username]}@#{host_string}" if !plain_mode
  command_options << host_string
  @logger.info("Invoking SSH: #{command_options.inspect}")
  safe_exec("ssh", *command_options)
end

#infoHash

Returns a hash of information necessary for accessing this virtual machine via SSH.

Returns:

  • (Hash)

Raises:



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/vagrant/ssh.rb', line 22

def info
  results = {
    :host          => @vm.config.ssh.host,
    :port          => @vm.config.ssh.port || @vm.driver.ssh_port(@vm.config.ssh.guest_port),
    :username      => @vm.config.ssh.username,
    :forward_agent => @vm.config.ssh.forward_agent,
    :forward_x11   => @vm.config.ssh.forward_x11
  }

  # This can happen if no port is set and for some reason Vagrant
  # can't detect an SSH port.
  raise Errors::SSHPortNotDetected if !results[:port]

  # Determine the private key path, which is either set by the
  # configuration or uses just the built-in insecure key.
  pk_path = @vm.config.ssh.private_key_path || @vm.env.default_private_key_path
  results[:private_key_path] = File.expand_path(pk_path, @vm.env.root_path)

  # We need to check and fix the private key permissions
  # to make sure that SSH gets a key with 0600 perms.
  check_key_permissions(results[:private_key_path])

  # Return the results
  return results
end