Jak wygenerować klucze SSH hosta za pomocą ansible?

11

Próbuję ponownie wygenerować klucze hosta ssh na kilku zdalnych serwerach za pomocą ansible (i ssh-keygen), ale wydaje się, że pliki się nie wyświetlają. Playbook działa OK, ale pliki na pilocie nie są zmieniane.

Muszę uciekać się do echo -ehakerów, ponieważ te piloty działają pod Ubuntu 14.04 i nie mają właściwej wersji python-pexpectdostępnej (zgodnie z ansiblem).

czego mi brakuje? Mój podręcznik i wyniki są poniżej:

poradnik

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
    - name: Generate /etc/ssh/ RSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

    - name: Generate /etc/ssh/ DSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

    - name: Generate /etc/ssh/ ECDSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

wynik

$ ansible-playbook ./playbooks/ssh-hostkeys.yml -l myhost.mydom.com, 
SUDO password: 

PLAY [all] **********************************************************************************************

TASK [Generate /etc/ssh/ RSA host key] ******************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C  -N "
    ]
}

TASK [Generate /etc/ssh/ DSA host key] ******************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C  -N "
    ]
}

TASK [Generate /etc/ssh/ ECDSA host key] ****************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C  -N "
    ]
}

PLAY RECAP **********************************************************************************************
myhost.mydom.com : ok=6    changed=3    unreachable=0    failed=0  
Błąd serwera
źródło

Odpowiedzi:

14

O ile mi wiadomo, jedynym powodem, dla którego trzeba by potokować „y” do ssh-keygen, jest to, że twoje polecenie zastępuje istniejący plik. Moim zdaniem nie jest to dobry sposób na zrobienie czegoś z narzędzia do zarządzania konfiguracją.

Powinieneś dostosować swoje zadania, aby były idempotentne. W szczególności, jeśli dodasz creates: filenamedo polecenia, nowe klucze zostaną utworzone tylko wtedy, gdy jeszcze nie istnieją, zamiast zastępować je za każdym razem, gdy uruchomisz ten podręcznik.

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
  - name: Generate /etc/ssh/ RSA host key
    command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_rsa_key

  - name: Generate /etc/ssh/ DSA host key
    command : ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_dsa_key

  - name: Generate /etc/ssh/ ECDSA host key
    command : ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_ecdsa_key

Jeśli z jakiegoś powodu chcesz wymienić te klucze, na przykład jeśli są one zbyt stare lub coś, co możesz chcieć dodać inne zadanie, aby je usunąć. Oto proste usunięcie

- file:
    state: absent:
    path: "{{item}}"
  loop:
  - /etc/ssh/ssh_host_rsa_key
  - /etc/ssh/ssh_host_dsa_key
  - /etc/ssh/ssh_host_ecdsa_key

Jeśli chcesz usunąć pliki wygenerowane przed określonym czasem, możesz użyć modułu statystycznego, aby pobrać szczegółowe informacje o tych plikach i skonfigurować whenwarunki, aby selektywnie je usunąć, jeśli były starsze niż określona data lub coś.

Zoredache
źródło
Świetny przykład i dzięki za przemyślenia na temat zachowania idempotencji. W moim przypadku używam sklonowanych maszyn wirtualnych, więc zawsze będą klucze do zastąpienia. W pewnym sensie potrzebuję opcji jądrowej, aby po prostu usunąć i wymienić.
Błąd serwera
Jeśli zawsze chcesz to usunąć, prawdopodobnie zrobiłbym takie file: state:absent ...podejście, jak przesyłać rzeczy do ssh-keygen. Chociaż prawdopodobnie nie ma dużej różnicy.
Zoredache
Ach, okej to ma więcej sensu. absentKilka dni temu nie wiedziałem o tym. Skutecznie spowoduje to usunięcie pliku przed ponownym wygenerowaniem klucza. Jest to znacznie jaśniejsze podejście. Dzięki.
Błąd serwera
6

commandModuł ansible nie przekazuje poleceń przez powłokę . Oznacza to, że nie można używać operatorów powłok, takich jak potok, i dlatego na wyjściu widać symbol potoku. Jeśli chodzi o ansible, wykonał polecenie echoz całą resztą wiersza jako argumentami echo.

Jeśli potrzebujesz linii poleceń przetwarzanej przez powłokę, użyjshell zamiast command.

I powinien istnieć lepszy sposób na zregenerowanie kluczy hosta ssh, ale nie mogę ich teraz znaleźć ...

Michael Hampton
źródło
Dzięki za wskazówkę powłoki vs. polecenie (teraz działa dobrze) Nie wiedziałem - wciąż całkiem nowy do odpowiedzi
Błąd serwera
Jeśli chodzi o ostatnią instrukcję (przynajmniej na CentOS / RHEL), jeśli usuniesz stare klucze i zrestartujesz, klucze hosta demona zostaną ponownie wygenerowane. W każdym razie musisz zrestartować usługę, więc zdecydowanie wydaje się to nieco lepsze.
Aaron Copley,
@AaronCopley Miałem bardziej na myśli rolę Ansible niż usługę dystrybucji. Wiem, że większość głównych dystrybucji ma usystematyzowaną usługę, która generuje klucze hosta ssh. Niestety usługa ta ma subtelne różnice specyficzne dla dystrybucji (nawet różni się między CentOS a Fedorą). Rola byłaby dobrym sposobem na podsumowanie tego wszystkiego, ale nie mogę znaleźć jednego od razu.
Michael Hampton
Bez obaw, pomyślałem, że o tym wspomnę. (Być może wiesz, ale OP może nie.)
Aaron Copley,
@AaronCopley - nawiasem mówiąc, to właśnie skończyłem. echo ...bit nie działa po drugim biegu (I testował w /tmp/której klawisze nie istniał za pierwszym razem). Zdecydowałem się najpierw usunąć klucze hosta, jak wspomniałeś, i wygenerować nowe. Jeśli chodzi o automatyczne generowanie kluczy, zależy to od dystrybucji, prawda? Nie wszystkie dystrybucje Linuksa używają systemd.
Błąd serwera
2

Użyj specjalnego modułu do tego zadania:

- name: Generate an OpenSSH keypair with the default values (4096 bits, rsa)
  openssh_keypair:
    path: /home/youruser/.ssh/id_rsa
    owner: youruser
    group: youruser

- name: Fix owner of the generated pub key
  file:
    path: /home/youruser/.ssh/id_rsa.pub
    owner: youruser
    group: youruser
Jorj
źródło
To nie są klucze hosta ssh
KumZ
1

przepraszam, ale nie mogłem użyć „tworzy” w zadaniu. otrzymałem następujący błąd:

ERROR! 'creates' is not a valid attribute for a Task

konsekwentnie korzystam z następujących zadań:

- name: remove existing ssh_host keys
  file: path={{ item }} state=absent
  with_items:
    - "/etc/ssh/ssh_host_rsa_key"
    - "/etc/ssh/ssh_host_dsa_key"
    - "/etc/ssh/ssh_host_ecdsa_key"

- name: Generate /etc/ssh/ RSA host key
  command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""

- name: Generate /etc/ssh/ DSA host key
  command : ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""

- name: Generate /etc/ssh/ ECDSA host key
  command : ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
MaxiReglisse
źródło
2
Użyj aktualnej wersji Ansible.
Michael Hampton
Masz rację, moja wersja Ansible jest nieco stara: 2.0.0.2 ... (na Ubuntu 16.04). Muszę się zmienić !
MaxiReglisse,
1

@Zoredache ma poprawną odpowiedź, ale kończy się niepowodzeniem (odnotowane przez @MaxiReglisse) w najnowszych wersjach Ansible. Zamiast tego użyj następującego kodu:

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
  - name: Generate /etc/ssh/ RSA host key
    command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_rsa_key
David Weber
źródło
1

Inną opcją jest użycie modułu użytkownika . Pozytywną stroną tego jest to, że dostaniesz idempotentne zadanie. Oto przykład, jak wygenerować klucze ssh na localhost:

- name: Generate ssh keys
  local_action:
    module: "user"
    name: "{{ lookup('env','USER') }}"
    generate_ssh_key: true
    ssh_key_type: "{{ item.0 }}"
    ssh_key_bits: "{{ item.1 }}"
    ssh_key_file: "{{ playbook_dir }}/{{ item.0 }}_{{ item.1 }}_key"
  with_together:
  - [ 'rsa', 'dsa' ]
  - [ 2048, 1024 ]
  loop_control:
    label: "{{ item.0 }}_{{ item.1 }}_key"

- name: Copy generated ssh keys to remote machine
  copy:
    src: "{{ playbook_dir }}/{{ item.0 }}_{{ item.1 }}_key"
    dest: "/etc/ssh/ssh_host_{{ item.0 }}_key{{ item.1 }}"
  with_nested:
  - [ 'rsa', 'dsa' ]
  - [ '', '.pub' ]
  notify:
  - Restart sshd
  loop_control:
    label: "/etc/ssh/ssh_host_{{ item.0 }}_key{{ item.1 }}"
HeroFromEarth
źródło
1
Czy to nie dotyczy kluczy użytkowników, a nie kluczy hosta?
MadHatter
Możesz użyć go również do kluczy hosta, ponieważ tak naprawdę jest to to samo. Nie zapomnij przywrócić kontekstu selinux, jeśli używasz SELinuksa w trybie wymuszania
HeroFromEarth
Z dokumentacji nie wynika jasno, że możesz. Jeśli przepiszesz swoją odpowiedź, aby wyraźnie pokazywała, że ​​tworzone są klucze hosta, usunę mój głos negatywny.
MadHatter
Okej, może to było niejasne. Dodałem kolejne zadanie, aby wyjaśnić, jak skopiować te klucze na zdalnym komputerze. I oczywiście jest to tylko mój przypadek (potrzebuję tych samych kluczy na kilku komputerach dla klastra, więc muszę wygenerować je na localhost) i jestem całkiem pewien, że możesz użyć modułu użytkownika do wygenerowania kluczy dla serwera ssh na maszyna zdalna (spójrz na 'ssh_key_file')
HeroFromEarth
Nadal nie jestem pewien, czy to coś innego niż włamanie (nie tylko dlatego, że pozostawia jednemu użytkownikowi kopię prywatnego klucza hosta!), Ale przynajmniej jest to coś, co odpowie teraz na pytanie, więc zadałem głosować.
MadHatter
0

Użyj modułów openssh_keypair i autoryzowanego_klucza, aby jednocześnie tworzyć i wdrażać klucze bez zapisywania ich na swoim hoście ansible.

- openssh_keypair:
    group: root
    owner: root
    path: /some/path/in/your/server
    register: ssh_key

- name: Store public key into origin
  delegate_to: central_server_name
  authorized_key:
     key: "{{ssh_key.public_key}}"
     comment: "{{ansible_hostname}}"
     user: any_user_on_central
MUY Belgium
źródło