Jak dodać własny klucz publiczny do Vagrant VM?

82

Mam problem z dodaniem klucza ssh do maszyny wirtualnej Vagrant. Zasadniczo konfiguracja, którą tutaj mam, działa dobrze. Po utworzeniu maszyn wirtualnych mogę uzyskać do nich dostęp za pośrednictwem vagrant ssh, użytkownik „vagrant” istnieje iw pliku znajduje się klucz ssh dla tego użytkownika authorized_keys.

Chciałbym teraz: móc łączyć się z tymi maszynami wirtualnymi za pośrednictwem sshlub z nich korzystać scp. Musiałbym więc tylko dodać mój klucz publiczny od id_rsa.pubdo authorized_keys- tak jak bym to zrobił ssh-copy-id.

Czy istnieje sposób, aby podczas konfiguracji powiedzieć Vagrantowi, że powinien zostać uwzględniony mój klucz publiczny? Jeśli nie (co jest prawdopodobne, według moich wyników Google), czy istnieje sposób na łatwe dodanie mojego klucza publicznego podczas konfiguracji włóczęgi?

tehK
źródło

Odpowiedzi:

55

Skopiowanie żądanego klucza publicznego należałoby bezpośrednio do fazy udostępniania . Dokładna odpowiedź zależy od tego, z jakiej obsługi chcesz skorzystać (powłoka, szef kuchni, marionetka itp.). Najbardziej trywialnym byłoby filezaopatrzenie w klucz, coś w tym:

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

Cóż, właściwie musisz dołączyć do Authorized_keys. Użyj narzędzia do obsługi powłoki, na przykład:

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

Możesz także użyć prawdziwego dostawcy, takiego jak Puppet . Na przykład zobacz Managing SSH Authorized Keys with Puppet .

Remus Rusanu
źródło
8
Dziękuję za odpowiedź - to był impuls, którego potrzebowałem :) Myślałem, że może Vagrant coś zapewni, ale z zaopatrzeniem jest to możliwe. Może trochę „brzydki”, ale działa jak urok. Po prostu kopiuję plik zgodnie z sugestią, a następnie używam narzędzia do obsługi powłoki, aby dołączyć klucz. virtualhost.vm.provision "shell", inline: "cat ~vagrant/.ssh/me.pub >> ~vagrant/.ssh/authorized_keys"
tehK
6
W komentarzu @ tehK powyżej (przed is) ukryte są znaki Unicode, które mogą zrujnować twoje popołudnie - oto poprawiona kopia / wersja do wklejaniavirtualhost.vm.provision "shell", inline: "cat ~vagrant/.ssh/me.pub >> ~vagrant/.ssh/authorized_keys"
Aidan Kane
To rozwiązanie działało pięknie! Dziękuję bardzo :)
Samir Patel
Przepraszam, spóźniłem się na mecz. Co to jest config.vm.provision?
user2568374
5
Nie koduj na stałe ~/.ssh/id_rsa.pub. ssh-add -LZamiast tego weź klucze .
Timur
72

Możesz użyć podstawowego modułu File w Ruby, na przykład:

  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

Ten działający przykład dołącza ~/.ssh/id_rsa.pubsię ~/.ssh/authorized_keyszarówno do użytkownika włóczącego się, jak i użytkownika root, co pozwoli ci użyć istniejącego klucza SSH.

Miauczeć
źródło
2
Dobrze i działa, ale doda linię przy każdym przepisie, który może być wykonywany kilka razy.
sekrett
2
Głosuję za odrzuceniem większego uzupełnienia tej odpowiedzi - ponieważ to dodanie powinno zostać dodane jako własna odpowiedź. @ user76329 (jeśli kiedykolwiek wrócisz, aby to przeczytać), powinien zamiast tego dodać to jako oddzielną odpowiedź.
HPierce
1
@sekrett Jeśli chcesz, aby dostawca łusek działał tylko raz, oto jedno rozwiązanie: blog.ouseful.info/2015/07/27/ ... Zasadniczo tworzysz flagę pliku, aby zaznaczyć, że prowokowanie już się wydarzyło.
rszalski
Musiałem dodać odpowiednik: mkdir ~ / .ssh && touch
allowed_keys
@sekrett Jeśli chodzi o idempotencję, lepiej Ci służy Ansible, powłoka może zrobić tylko tyle. docs.ansible.com/ansible/latest/modules/ ...
MGP,
38

Jest bardziej „elegancki” sposób na osiągnięcie tego, co chcesz. Możesz znaleźć istniejący klucz prywatny i użyć go, zamiast męczyć się z dodaniem klucza publicznego.

Postępuj w ten sposób, aby zobaczyć ścieżkę do istniejącego klucza prywatnego (spójrz poniżej na IdentityFile ):

biegać

 vagrant ssh-config 

wynik:

$ vagrant ssh-config
Host magento2.vagrant150
  Nazwa hosta 127.0.0.1
  Użytkownik włóczęga
  Port 3150
  UserKnownHostsFile / dev / null
  StrictHostKeyChecking no
  Hasło Nr uwierzytelnienia
  IdentityFile „/Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key”
  Tożsamości Tylko tak
  LogLevel FATAL

Następnie możesz użyć takiego klucza prywatnego, zwróć także uwagę na przełącznik do wyłączania uwierzytelniania hasłem

ssh -i /Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key -o PasswordAuthentication = no [email protected] -p 3150
Madis Maenni
źródło
Otrzymano: ssh_exhange_identification: Połączenie zamknięte przez zdalny host. Teraz nie mogę nawet uzyskać błędu uwierzytelniania na vagrant w górę. Mówi się, że próbowano wykonać operacje specyficzne dla gościa na komputerze, który nie jest gotowy do komunikacji z gościem. To nie powinno się zdarzyć i ale powinno zostać zgłoszone.
user2568374
13

Ta doskonała odpowiedź została dodana przez użytkownika76329 w odrzuconej sugerowanej edycji

Rozwijając przykład Meow , możemy skopiować lokalne klucze pub / private ssh, ustawić uprawnienia i sprawić, by skrypt wbudowany był idempotentny (uruchamia się raz i powtórzy się tylko wtedy, gdy warunek testu nie powiedzie się, a zatem wymaga aprowizacji):

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
źródło
11

Krótszy i bardziej poprawny kod powinien wyglądać następująco:

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

W przeciwnym razie użytkownik .ssh/authorized_keysbędzie należał do użytkownika root.

Mimo to doda linię przy każdym uruchomieniu, ale Vagrant jest używany do testowania, a maszyna wirtualna ma zwykle krótką żywotność, więc nie jest to duży problem.

sekrett
źródło
1
Musiałem dodać config.vm.provision 'shell', inline: "mkdir -p /root/.ssh"po pierwszej linii, ponieważ folder nie istniał
geekQ
@geekQ, którego używam ssh-copy-id, więc jest zawsze tworzony dla mnie, ale bardziej poprawne jest tworzenie go dla innych. Będę edytować, dzięki.
sekrett
9

W końcu używam kodu takiego jak:

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

Zauważ, że nie powinniśmy twardej ścieżki do kodu, /home/vagrant/.ssh/authorized_keysponieważ niektóre błędne pola nie używają vagrantnazwy użytkownika.

smartwjw
źródło
Naprawdę dobra odpowiedź. Bardzo mi pomogło. Ale mam konfiguracje, które dostosowują miejsce vagrant.dprzechowywania katalogu, więc dostosowałem konfigurację do obsługi takich przypadków. Szczegóły tutaj .
Giacomo1968,
2

Żaden ze starszych postów nie działał dla mnie, chociaż niektóre były bliskie. Musiałem zrobić klucze rsa z keygenem w terminalu i korzystać z niestandardowych kluczy. Innymi słowy, pokonany przez użycie kluczy Vagranta.

Korzystam z Mac OS Mojave od daty tego postu. Ustawiłem dwie skrzynki Vagrant w jednym pliku Vagrantfile. Pokazuję całe pierwsze pudełko, aby nowicjusze mogli zobaczyć kontekst. Umieściłem folder .ssh w tym samym folderze co plik Vagrant, w przeciwnym razie użyj konfiguracji user9091383.

Kredyt za to rozwiązanie przypada temu koderowi.

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
źródło
1

To doskonały wątek, który pomógł mi rozwiązać podobną sytuację, jaką opisuje oryginalny plakat.

Chociaż ostatecznie użyłem ustawień / logiki przedstawionych w odpowiedzi smartwjw, napotkałem problem , ponieważ używam VAGRANT_HOMEzmiennej środowiskowej do zapisywania podstawowych danych vagrant.dkatalogu na zewnętrznym dysku twardym w jednym z moich systemów programistycznych.

Oto dostosowany kod, którego używam w moim pliku Vagrantfile, aby dostosować się do VAGRANT_HOMEustawianej zmiennej środowiskowej; „magia” dzieje się w tej linii 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
źródło
1

Dla dostawców powłoki wbudowanej - często klucz publiczny zawiera spacje, komentarze itp. Dlatego upewnij się, że wokół zmiennej rozwijanej do klucza publicznego umieszczasz cudzysłowy (ze znakami ucieczki):

config.vm.provision 'shell', inline: "echo \"#{ssh_pub_key}\" >> /home/vagrant/.ssh/authorized_keys", privileged: false
Dick Visser
źródło
0

Całkiem kompletny przykład, mam nadzieję, że pomoże to komuś, kto odwiedza następny. Przeniesiono wszystkie konkretne wartości do zewnętrznych plików konfiguracyjnych. Przypisanie adresu IP służy tylko do wypróbowania.

# -*- 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
źródło
-1

Odpowiedź Madis Maenni jest najbliższa najlepszemu rozwiązaniu:

po prostu zrób:

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

możesz po prostu ssh przez nazwę hosta.

Aby uzyskać listę nazw hostów skonfigurowanych w ~ / .ssh / config

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

Mój przykład:

$ grep -E '^Host' ~/.ssh/config
Host web
Host db
$ ssh web
[vagrant@web ~]$
Gregory
źródło
-2

Wygeneruj parę kluczy rsa do uwierzytelniania włóczęgów ssh-keygen -f ~/.ssh/vagrant

Możesz również dodać pliki tożsamości włóczęgów do swojego ~/.ssh/config

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

Z jakiegoś powodu nie możemy po prostu określić klucza, który chcemy wstawić, więc wykonujemy kilka dodatkowych kroków, aby samodzielnie wygenerować klucz. W ten sposób uzyskujemy bezpieczeństwo i wiedzę o tym, jakiego dokładnie klucza potrzebujemy (+ wszystkie pudełka włóczęgów otrzymają ten sam klucz)

Nie można ssh do vagrant VM przy użyciu niezabezpieczonego klucza prywatnego (vagrant 1.7.2) Jak dodać własny klucz publiczny do 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

MUSZLA

user9091383
źródło