Come generare chiavi SSH host tramite Ansible?


11

Sto cercando di rigenerare le chiavi dell'host ssh su una manciata di server remoti tramite ansible (e ssh-keygen), ma i file non sembrano essere visualizzati. Il playbook funziona correttamente, ma i file sul telecomando non vengono modificati.

Devo ricorrere al echo -epirateria informatica poiché questi telecomandi eseguono Ubuntu 14.04 e non hanno la versione corretta del python-pexpectdisponibile (secondo Ansible).

Cosa mi sto perdendo? Il mio playbook e l'output sono di seguito:

playbook

---
- 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

produzione

$ 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  

Risposte:


14

Per quanto ne so, l'unica ragione per cui dovresti reindirizzare una 'y' a ssh-keygen è se il tuo comando sta sostituendo un file esistente. Secondo me questo non è un buon modo per fare qualcosa da uno strumento di gestione della configurazione.

Dovresti adattare i tuoi compiti per renderli idempotenti. In particolare se aggiungi il creates: filenamecomando al tuo comando, le nuove chiavi verranno create solo quando non esistono già, invece di essere sostituite ogni volta che esegui quel playbook.

---
- 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

Se per qualche motivo volessi sostituire quelle chiavi, ad esempio se fossero troppo vecchie o qualcosa, potresti voler aggiungere un'altra attività per rimuoverle. Ecco una semplice eliminazione

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

Se si desidera eliminare i file generati prima di un certo tempo, è possibile utilizzare il modulo stat per recuperare i dettagli su questi file e le whencondizioni di installazione per rimuoverli selettivamente se fossero più vecchi di una certa data o qualcosa del genere.


Grande esempio e grazie per i pensieri sul mantenimento dell'idempotenza. Per il mio caso d'uso, eseguo il provisioning di macchine virtuali clonate, quindi ci saranno sempre le chiavi da sovrascrivere. Ho bisogno dell'opzione nucleare per rimuovere e sostituire.
Server Fault

Se vuoi sempre che rimuova, allora probabilmente farei l' file: state:absent ...approccio sul piping roba a ssh-keygen. Anche se probabilmente non c'è molta differenza.
Zoredache,

Ah ok. ha più senso. Non ne sapevo absentun paio di giorni fa. In effetti, questo eliminerà il file prima di rigenerare la chiave. È un approccio molto più chiaro. Grazie.
Server Fault

6

Il commandmodulo ansible non passa i comandi attraverso una shell . Ciò significa che non è possibile utilizzare operatori shell come pipe, ed è per questo che si vede il simbolo pipe nell'output. Per quanto riguarda ansible, ha eseguito il comando echocon tutto il resto della riga come argomenti echo.

Se hai bisogno della riga di comando elaborata da una shell, usashell invece di command.

E dovrebbe esserci un modo migliore per rigenerare le chiavi dell'host ssh, ma non riesco a trovarne uno in questo momento ...


Grazie per il suggerimento shell vs. comando (funziona bene ora) Non lo sapevo - ancora abbastanza nuovo per rispondere
Errore del server

Per quanto riguarda l'ultima istruzione (almeno su CentOS / RHEL) se si rimuovono le vecchie chiavi e si riavvia le chiavi host del daemon vengono rigenerate per te. Dovrai comunque riavviare il servizio, quindi questo sembra decisamente migliore.
Aaron Copley,

@AaronCopley Mi riferivo più a un ruolo Ansible che al servizio di distribuzione. Sono consapevole che la maggior parte delle distro ha un servizio systemd che genera chiavi host ssh. Sfortunatamente quel servizio presenta sottili differenze specifiche per la distribuzione (è persino diverso tra CentOS e Fedora). Un ruolo sarebbe un bel modo per incapsulare tutto ciò, ma non riesco a trovarne uno di mano.
Michael Hampton,

Nessun problema, ho pensato di menzionarlo. (Potresti sapere, ma OP potrebbe non farlo.)
Aaron Copley

@AaronCopley - per inciso, questo è quello che ho finito per fare. il echo ...bit non ha funzionato dopo una seconda esecuzione (stavo testando in /tmp/cui le chiavi non esistevano la prima volta). Ho fatto ricorso prima alla rimozione delle chiavi host, come dici tu, e alla generazione di nuove. Per quanto riguarda la rigenerazione automatica delle chiavi, questo dipende dalla tua distribuzione, giusto? Non tutte le distribuzioni Linux utilizzano systemd.
Errore del server

2

Utilizzare il modulo speciale per questa attività:

- 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

Quelle non sono chiavi host ssh
KumZ

1

scusa, ma non ho potuto usare "crea" in un compito. ho ottenuto il seguente errore:

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

di conseguenza, utilizzo i seguenti compiti:

- 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 ""

2
Utilizzare una versione corrente di Ansible.
Michael Hampton,

Hai ragione, la mia versione di Ansible è un po 'vecchia: 2.0.0.2 ... (Su Ubuntu 16.04). Devo cambiare!
MaxiReglisse,

1

@Zoredache ha la risposta corretta ma non riesce (notato da @MaxiReglisse) per le versioni recenti di Ansible. Utilizzare invece il seguente codice:

---
- 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

1

Un'altra opzione è quella di utilizzare il modulo utente . Il lato positivo di questo è che avrai un compito idempotente. Ecco un esempio di come generare chiavi ssh su 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 }}"

1
Non è per le chiavi utente, non per le chiavi host?
MadHatter,

Puoi usarlo anche per le chiavi host perché in realtà è la stessa cosa. Basta non dimenticare di ripristinare il contesto selinux se si utilizza SELinux in modalità di esecuzione
HeroFromEarth

Non mi è chiaro dalla documentazione che puoi. Se riscrivi la tua risposta in modo che mostri esplicitamente la creazione delle chiavi host, rimuoverei il mio downvote.
MadHatter,

Ok, forse non era chiaro. Ho aggiunto un'altra attività per spiegare come copiare queste chiavi su una macchina remota. E ovviamente è solo il mio caso (ho bisogno delle stesse chiavi su alcune macchine per un cluster, quindi ho bisogno di generarle su localhost) e sono abbastanza sicuro che puoi usare il modulo 'user' per generare le chiavi per il server SSH su the remote machine (guarda 'ssh_key_file')
HeroFromEarth

Non sono ancora sicuro che sia qualcosa di diverso da un hack (non ultimo perché lascia un utente con una copia della chiave privata dell'host!) Ma almeno è qualcosa che ora risponderà alla domanda come chiesto, quindi ho rimosso il mio downvote.
MadHatter,

0

Utilizzare il modulo openssh_keypair e authorized_key per creare e distribuire le chiavi contemporaneamente senza salvarle nel proprio host.

- 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.