¿Cómo agrego mi propia clave pública a Vagrant VM?

81

Tengo un problema al agregar una clave ssh a una máquina virtual Vagrant. Básicamente, la configuración que tengo aquí funciona bien. Una vez que se crean las máquinas virtuales, puedo acceder a ellas a través de vagrant ssh, el usuario "vagabundo" existe y hay una clave ssh para este usuario en el authorized_keysarchivo.

Lo que me gustaría hacer ahora es: poder conectarme a esas VM mediante ssho usar scp. Por lo tanto, solo necesitaría agregar mi clave pública desde id_rsa.pubal authorized_keys, tal como lo haría con ssh-copy-id.

¿Hay alguna forma de decirle a Vagrant durante la configuración que debe incluirse mi clave pública? Si no es así (lo cual es probable, según mis resultados de Google), ¿hay alguna manera de agregar fácilmente mi clave pública durante la configuración de vagabundo?

tehK
fuente

Respuestas:

53

Copiar la clave pública deseada entraría directamente en la fase de aprovisionamiento . La respuesta exacta depende del aprovisionamiento que desee utilizar (shell, Chef, Puppet, etc.). El más trivial sería un fileaprovisionador de la clave, algo así:

config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/me.pub"

Bueno, en realidad necesitas agregar a las claves_autorizadas. Utilice el aprovisionador de shell, así:

config.vm.provision "shell", inline: <<-SHELL
  cat /home/vagrant/.ssh/me.pub >> /home/vagrant/.ssh/authorized_keys
SHELL
end

También puede utilizar un verdadero aprovisionador, como Puppet . Por ejemplo, consulte Administrar claves autorizadas SSH con Puppet .

Remus Rusanu
fuente
8
Gracias por tu respuesta, ese fue el empujón que necesitaba :) Pensé que tal vez Vagrant proporcionaría algo, pero con el aprovisionamiento es posible. Quizás un poco "feo", pero funciona de maravilla. Básicamente, solo estoy copiando el archivo como sugirió y luego uso el aprovisionador de shell para agregar la clave. virtualhost.vm.provision "shell", inline: "cat ~vagrant/.ssh/me.pub >> ~vagrant/.ssh/authorized_keys"
tehK
6
Hay caracteres Unicode ocultos en el comentario de @ tehK anterior (antes de la is) que pueden arruinar su tarde; aquí hay una copia fija / versión para pastavirtualhost.vm.provision "shell", inline: "cat ~vagrant/.ssh/me.pub >> ~vagrant/.ssh/authorized_keys"
Aidan Kane
¡Esta solución funcionó a la perfección! Muchas gracias :)
Samir Patel
Lo siento, llego tarde al juego. ¿Qué config.vm.provision?
user2568374
5
No codifique ~/.ssh/id_rsa.pub. Obtenga las llaves de en su ssh-add -Llugar.
Timur
72

Puede usar el módulo de archivo central de Ruby, así:

  config.vm.provision "shell" do |s|
    ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
    s.inline = <<-SHELL
      echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
      echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
    SHELL
  end

Este ejemplo de trabajo se agrega ~/.ssh/id_rsa.pubal del ~/.ssh/authorized_keysusuario vagabundo y root, lo que le permitirá usar su clave SSH existente.

maullar
fuente
2
Bien y funciona, pero agregará una línea en cada disposición que podría ejecutarse varias veces.
sekrett
2
Voto para rechazar una adición importante a esta respuesta , porque esa adición debe agregarse como su propia respuesta. @ user76329 (si alguna vez vuelve a leer esto) debería agregarlo como una respuesta separada.
HPierce
1
@sekrett Si desea que el shell provisoner se ejecute solo una vez, aquí tiene una solución: blog.ouseful.info/2015/07/27/… Básicamente, crea una bandera de archivo para marcar que la condición ya ha sucedido.
rszalski
Necesitaba agregar el equivalente de: mkdir ~ / .ssh && touch
protected_keys
@sekrett Por idempotencia, está mejor servido con Ansible, shell solo puede hacer mucho. docs.ansible.com/ansible/latest/modules/…
MGP
38

Hay una forma más "elegante" de lograr lo que quieres hacer. Puede encontrar la clave privada existente y usarla en lugar de pasar por la molestia de agregar su clave pública.

Proceda así para ver la ruta a la clave privada existente (busque a continuación IdentityFile ):

correr

 ssh-config vagabundo 

resultado:

$ vagrant ssh-config
Anfitrión magento2.vagrant150
  Nombre de host 127.0.0.1
  Usuario vagabundo
  Puerto 3150
  UserKnownHostsFile / dev / null
  StrictHostKeyChecking no
  Autenticación de contraseña no
  IdentityFile "/Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key"
  Identidades Solo si
  LogLevel FATAL

Luego puede usar la clave privada de esta manera, tenga en cuenta también el interruptor para desactivar la autenticación de contraseña

ssh -i /Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key -o PasswordAuthentication = no [email protected] -p 3150
Madis Maenni
fuente
Conseguido: ssh_exhange_identification: Conexión cerrada por host remoto. Ahora ni siquiera puedo obtener un error de autenticación en vagrant up. Dice que se intentaron operaciones específicas para invitados en una máquina que no está lista para la comunicación con invitados. Esto no debería suceder y se debería informar.
user2568374
13

Esta excelente respuesta fue agregada por user76329 en una edición sugerida rechazada

Ampliando el ejemplo de Meow , podemos copiar las claves ssh públicas / privadas locales, establecer permisos y hacer que el script en línea sea idempotente (se ejecuta una vez y solo se repetirá si la condición de prueba falla, por lo que necesita aprovisionamiento):

config.vm.provision "shell" do |s|
  ssh_prv_key = ""
  ssh_pub_key = ""
  if File.file?("#{Dir.home}/.ssh/id_rsa")
    ssh_prv_key = File.read("#{Dir.home}/.ssh/id_rsa")
    ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  else
    puts "No SSH key found. You will need to remedy this before pushing to the repository."
  end
  s.inline = <<-SHELL
    if grep -sq "#{ssh_pub_key}" /home/vagrant/.ssh/authorized_keys; then
      echo "SSH keys already provisioned."
      exit 0;
    fi
    echo "SSH key provisioning."
    mkdir -p /home/vagrant/.ssh/
    touch /home/vagrant/.ssh/authorized_keys
    echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
    echo #{ssh_pub_key} > /home/vagrant/.ssh/id_rsa.pub
    chmod 644 /home/vagrant/.ssh/id_rsa.pub
    echo "#{ssh_prv_key}" > /home/vagrant/.ssh/id_rsa
    chmod 600 /home/vagrant/.ssh/id_rsa
    chown -R vagrant:vagrant /home/vagrant
    exit 0
  SHELL
end
Stevie Howard
fuente
11

Un código más corto y correcto debería ser:

ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
config.vm.provision 'shell', inline: 'mkdir -p /root/.ssh'
config.vm.provision 'shell', inline: "echo #{ssh_pub_key} >> /root/.ssh/authorized_keys"
config.vm.provision 'shell', inline: "echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys", privileged: false

De lo contrario, el usuario .ssh/authorized_keyspertenecerá al usuario root.

Aún así, agregará una línea en cada ejecución de provisión, pero Vagrant se usa para pruebas y una VM generalmente tiene una vida corta, por lo que no es un gran problema.

sekrett
fuente
1
Tuve que agregar config.vm.provision 'shell', inline: "mkdir -p /root/.ssh"después de la primera línea ya que la carpeta no existía
geekQ
@geekQ Yo uso ssh-copy-id, por lo que siempre se crea para mí pero es más correcto crearlo para otros. Editaré, gracias.
sekrett
9

Termino usando código como:

config.ssh.forward_agent    = true
config.ssh.insert_key       = false
config.ssh.private_key_path =  ["~/.vagrant.d/insecure_private_key","~/.ssh/id_rsa"]
config.vm.provision :shell, privileged: false do |s|
  ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  s.inline = <<-SHELL
     echo #{ssh_pub_key} >> /home/$USER/.ssh/authorized_keys
     sudo bash -c "echo #{ssh_pub_key} >> /root/.ssh/authorized_keys"
  SHELL
end

Tenga en cuenta que no debemos codificar la ruta de acceso, /home/vagrant/.ssh/authorized_keysya que algunas cajas vagabundas no usan el vagrantnombre de usuario.

smartwjw
fuente
Muy buena respuesta. Me ayudo mucho. Pero tengo configuraciones que ajustan dónde vagrant.dse almacena el directorio, así que ajusté su configuración para manejar casos como ese. Detalles aquí .
Giacomo1968
2

Ninguna de las publicaciones más antiguas me funcionó, aunque algunas estuvieron cerca. Tuve que hacer claves rsa con keygen en la terminal e ir con claves personalizadas. En otras palabras, derrotado por usar las llaves de Vagrant.

Estoy en Mac OS Mojave a la fecha de esta publicación. He configurado dos cajas Vagrant en un Vagrantfile. Estoy mostrando todo el primer cuadro para que los novatos puedan ver el contexto. Puse la carpeta .ssh en la misma carpeta que el archivo Vagrant; de lo contrario, use la configuración user9091383.

El crédito por esta solución es para este codificador.

Vagrant.configure("2") do |config|
  config.vm.define "pfbox", primary: true do |pfbox|
        pfbox.vm.box = "ubuntu/xenial64"
        pfbox.vm.network "forwarded_port", host: 8084, guest: 80
        pfbox.vm.network "forwarded_port", host: 8080, guest: 8080
        pfbox.vm.network "forwarded_port", host: 8079, guest: 8079
        pfbox.vm.network "forwarded_port", host: 3000, guest: 3000
        pfbox.vm.provision :shell, path: ".provision/bootstrap.sh"
        pfbox.vm.synced_folder "ubuntu", "/home/vagrant"
        pfbox.vm.provision "file", source: "~/.gitconfig", destination: "~/.gitconfig"
        pfbox.vm.network "private_network", type: "dhcp"
        pfbox.vm.network "public_network"
        pfbox.ssh.insert_key = false
        ssh_key_path = ".ssh/"  # This may not be necessary.  I may remove.
        pfbox.vm.provision "shell", inline: "mkdir -p /home/vagrant/.ssh"
        pfbox.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key", ".ssh/id_rsa"]
        pfbox.vm.provision "file", source: ".ssh/id_rsa.pub", destination: ".ssh/authorized_keys"
        pfbox.vm.box_check_update = "true"
        pfbox.vm.hostname = "pfbox"
        # VirtualBox
          config.vm.provider "virtualbox" do |vb|
            # vb.gui = true
            vb.name = "pfbox" # friendly name for Oracle VM VirtualBox Manager
            vb.memory = 2048 # memory in megabytes 2.0 GB
            vb.cpus = 1 # cpu cores, can't be more than the host actually has.
          end
  end
  config.vm.define "dbbox" do |dbbox|
        ...
Preston
fuente
1

Este es un hilo excelente que me ayudó a resolver una situación similar a la que describe el póster original.

Si bien finalmente usé la configuración / lógica presentada en la respuesta de smartwjw , encontré un problema ya que uso la VAGRANT_HOMEvariable de entorno para guardar las vagrant.dcosas del directorio central en un disco duro externo en uno de mis sistemas de desarrollo.

Así que aquí está el código ajustado que estoy usando en mi Vagrantfile para adaptarse a una VAGRANT_HOMEvariable de entorno que se está configurando; la "magia" ocurre en esta línea vagrant_home_path = ENV["VAGRANT_HOME"] ||= "~/.vagrant.d":

config.ssh.insert_key = false
config.ssh.forward_agent = true
vagrant_home_path = ENV["VAGRANT_HOME"] ||= "~/.vagrant.d"
config.ssh.private_key_path = ["#{vagrant_home_path}/insecure_private_key", "~/.ssh/id_rsa"]
config.vm.provision :shell, privileged: false do |shell_action|
  ssh_public_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  shell_action.inline = <<-SHELL
    echo #{ssh_public_key} >> /home/$USER/.ssh/authorized_keys
  SHELL
end
Giacomo1968
fuente
1

Para los aprovisionadores de shell en línea, es común que una clave pública contenga espacios, comentarios, etc. Así que asegúrese de poner comillas (de escape) alrededor de la var que se expande a la clave pública:

config.vm.provision 'shell', inline: "echo \"#{ssh_pub_key}\" >> /home/vagrant/.ssh/authorized_keys", privileged: false
Dick Visser
fuente
0

Un ejemplo bastante completo, espero que esto ayude a alguien que visite a continuación. Se movieron todos los valores concretos a archivos de configuración externos. La asignación de IP es solo para probar.

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'yaml'
vmconfig = YAML.load_file('vmconfig.yml')

=begin
Script to created VMs with public IPs, VM creation governed by the provided
config file.
All Vagrant configuration is done below. The "2" in Vagrant.configure
configures the configuration version (we support older styles for
backwards compatibility). Please don't change it unless you know what
you're doing
Default user `vagrant` is created and ssh key is overridden. make sure to have
the files `vagrant_rsa` (private key) and `vagrant_rsa.pub` (public key) in the
path `./.ssh/`
Same files need to be available for all the users you want to create in each of
these VMs
=end

uid_start = vmconfig['uid_start']
ip_start = vmconfig['ip_start']
vagrant_private_key = Dir.pwd + '/.ssh/vagrant_rsa'
guest_sshkeys = '/' + Dir.pwd.split('/')[-1] + '/.ssh/'
Vagrant.configure('2') do |config|
  vmconfig['machines'].each do |machine|
    config.vm.define "#{machine}" do |node|
      ip_start += 1
      node.vm.box = vmconfig['vm_box_name']
      node.vm.box_version = vmconfig['vm_box_version']
      node.vm.box_check_update = false
      node.vm.boot_timeout = vmconfig['vm_boot_timeout']
      node.vm.hostname = "#{machine}"
      node.vm.network "public_network", bridge: "#{vmconfig['bridge_name']}", auto_config: false
      node.vm.provision "shell", run: "always", inline: "ifconfig #{vmconfig['ethernet_device']} #{vmconfig['public_ip_part']}#{ip_start} netmask #{vmconfig['subnet_mask']} up"
      node.ssh.insert_key = false
      node.ssh.private_key_path = ['~/.vagrant.d/insecure_private_key', "#{vagrant_private_key}"]
      node.vm.provision "file", source: "#{vagrant_private_key}.pub", destination: "~/.ssh/authorized_keys"
      node.vm.provision "shell", inline: <<-EOC
        sudo sed -i -e "\\#PasswordAuthentication yes# s#PasswordAuthentication yes#PasswordAuthentication no#g" /etc/ssh/sshd_config
        sudo systemctl restart sshd.service
      EOC
      vmconfig['users'].each do |user|
        uid_start += 1
        node.vm.provision "shell", run: "once", privileged: true, inline: <<-CREATEUSER
          sudo useradd -m -s /bin/bash -U #{user} -u #{uid_start}
          sudo mkdir /home/#{user}/.ssh
          sudo cp #{guest_sshkeys}#{user}_rsa.pub /home/#{user}/.ssh/authorized_keys
          sudo chown -R #{user}:#{user} /home/#{user}
          sudo su
          echo "%#{user} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/#{user}
          exit
        CREATEUSER
      end
    end
  end
Faisal K
fuente
-1

La respuesta de Madis Maenni es la más cercana a la mejor solución:

solo haz:

vagrant ssh-config >> ~/.ssh/config
chmod 600 ~/.ssh/config

entonces puede ssh a través del nombre de host.

Para obtener la lista de nombres de host configurados en ~ / .ssh / config

grep -E '^Host ' ~/.ssh/config

Mi ejemplo:

$ grep -E '^Host' ~/.ssh/config
Host web
Host db
$ ssh web
[vagrant@web ~]$
Gregory
fuente
-2

Genere un par de claves rsa para la autenticación de vagabundos ssh-keygen -f ~/.ssh/vagrant

Es posible que también desee agregar los archivos de identidad vagabundos a su ~/.ssh/config

IdentityFile ~/.ssh/vagrant
IdentityFile ~/.vagrant.d/insecure_private_key

Por alguna razón, no podemos simplemente especificar la clave que queremos insertar, por lo que tomamos algunos pasos adicionales para generar una clave nosotros mismos. De esta manera obtenemos seguridad y conocimiento de exactamente qué clave necesitamos (+ todas las cajas de vagabundos obtendrán la misma clave)

No se puede enviar SSH a VM vagrant usando la clave privada insegura (vagrant 1.7.2) ¿Cómo agrego mi propia clave pública a Vagrant VM?

config.ssh.insert_key = false
config.ssh.private_key_path = ['~/.ssh/vagrant', '~/.vagrant.d/insecure_private_key']
config.vm.provision "file", source: "~/.ssh/vagrant.pub", destination: "/home/vagrant/.ssh/vagrant.pub"
config.vm.provision "shell", inline: <<-SHELL
cat /home/vagrant/.ssh/vagrant.pub >> /home/vagrant/.ssh/authorized_keys
mkdir -p /root/.ssh
cat /home/vagrant/.ssh/authorized_keys >> /root/.ssh/authorized_keys

CÁSCARA

usuario9091383
fuente