¿Cómo generar claves SSH de host a través de ansible?

11

Estoy tratando de volver a generar claves de host ssh en un puñado de servidores remotos a través de ansible (y ssh-keygen), pero los archivos no parecen estar apareciendo. El libro de jugadas funciona bien, pero los archivos del control remoto no se modifican.

Tengo que recurrir a la echo -ehackery ya que estos controles remotos se están ejecutando Ubuntu 14.04 y no tienen la versión correcta de la python-pexpectdisposición (según ansible).

¿Qué me estoy perdiendo? Mi libro de jugadas y mi salida están a continuación:

libro de jugadas

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

salida

$ 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  
Falla del servidor
fuente

Respuestas:

14

Hasta donde sé, la única razón por la que necesitaría canalizar una 'y' a ssh-keygen, es si su comando está reemplazando un archivo existente. En mi opinión, esta no es una buena manera de hacer algo desde una herramienta de administración de configuración.

Debes ajustar tus tareas para hacerlas idempotentes. Específicamente, si agrega el creates: filenamecomando, las nuevas claves solo se crearán cuando aún no existan, en lugar de reemplazarse cada vez que ejecute ese libro de jugadas.

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

Si, por alguna razón, desea reemplazar esas claves, por ejemplo, si eran demasiado viejas o algo así, es posible que desee agregar otra tarea para eliminarlas. Aquí hay una simple eliminación

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

Si desea eliminar los archivos generados antes de un cierto tiempo, puede usar el módulo de estadísticas para recuperar detalles sobre estos archivos y configurar las whencondiciones para eliminarlos selectivamente si eran anteriores a una fecha determinada o algo así.

Zoredache
fuente
Gran ejemplo y gracias por las ideas sobre el mantenimiento de la idempotencia. Para mi caso de uso, estoy aprovisionando máquinas virtuales clonadas para que siempre haya claves para sobrescribir. Necesito la opción nuclear para eliminar y reemplazar.
Error del servidor
Si siempre desea que se elimine, entonces probablemente haría el file: state:absent ...enfoque sobre las tuberías de ssh-keygen. Aunque probablemente no haya tanta diferencia.
Zoredache
Ah ok eso tiene más sentido. No lo sabía hace absentun par de días. Efectivamente, eso eliminará el archivo antes de volver a generar la clave. Es un enfoque mucho más claro. Gracias.
Fallo del servidor
6

El commandmódulo ansible no pasa comandos a través de un shell . Esto significa que no puede usar operadores de shell como la tubería, y es por eso que está viendo el símbolo de la tubería en la salida. En lo que respecta a ansible, ha ejecutado el comando echocon todo el resto de la línea como argumentos para echo.

Si necesita la línea de comando procesada por un shell, use enshell lugar de command.

Y, debería haber una mejor manera de regenerar las claves de host ssh, pero no puedo encontrar una en este momento ...

Michael Hampton
fuente
Gracias por la punta de comandos shell (vs. funciona bien ahora) Yo no sabía - todavía bastante nuevo en ansible
servidor falla
Con respecto a la última declaración (al menos en CentOS / RHEL) si elimina las claves antiguas y reinicia, las claves del host daemon se regeneran para usted. Deberá reiniciar el servicio de todos modos, por lo que definitivamente parece algo mejor.
Aaron Copley
@AaronCopley Me refería más a un rol de Ansible que al servicio de distribución. Soy consciente de que la mayoría de las distribuciones principales tienen un servicio systemd que genera claves de host ssh. Desafortunadamente, ese servicio tiene sutiles diferencias específicas de distribución (incluso es diferente entre CentOS y Fedora). Un rol sería una buena forma de encapsular todo eso, pero no puedo encontrar uno por casualidad.
Michael Hampton
No te preocupes, solo pensé en mencionarlo. (Puede que lo sepas, pero OP no.)
Aaron Copley
@AaronCopley: por cierto, esto es lo que terminé haciendo. el echo ...bit no funcionó después de una segunda ejecución (estaba probando /tmp/que las claves no existían la primera vez). Recurrí a eliminar las claves de host primero, como usted menciona, y generar las nuevas. En cuanto a que las claves se regeneren automáticamente, esto depende de su distribución, ¿correcto? No todas las distribuciones de Linux usan systemd.
Error del servidor el
2

Use el módulo especial para esta tarea:

- 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
fuente
Esas no son claves de host ssh
KumZ
1

lo siento, pero no pude usar "crea" en una tarea. Obtuve el siguiente error:

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

en consecuencia, uso las siguientes tareas:

- 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
fuente
2
Use una versión actual de Ansible.
Michael Hampton
Tienes razón, mi versión de Ansible es un poco antigua: 2.0.0.2 ... (en Ubuntu 16.04). Tengo que cambiar !
MaxiReglisse
1

@Zoredache tiene la respuesta correcta pero falla (anotado por @MaxiReglisse) para las versiones recientes de Ansible. Use el siguiente código en su lugar:

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

Otra opción es usar el módulo de usuario . El lado positivo de esto es que obtendrá una tarea idempotente. Aquí hay un ejemplo de cómo generar claves ssh en 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 }}"
HéroeDe La Tierra
fuente
1
¿No es eso para las claves de usuario, no las claves de host?
MadHatter
También puede usarlo para claves de host porque en realidad es lo mismo. Simplemente no olvides restaurar el contexto de selinux si usas SELinux en el modo de imposición
HeroFromEarth
No me queda claro por la documentación que pueda. Si reescribe su respuesta para que muestre explícitamente las claves de host que se están creando, eliminaría mi voto negativo.
MadHatter
De acuerdo, tal vez no estaba claro. Agregué otra tarea para explicar cómo copiar estas claves en una máquina remota. Y, por supuesto, es solo mi caso (necesito las mismas claves en algunas máquinas para un clúster, así que necesito generarlas en localhost) y estoy bastante seguro de que puede usar el módulo 'usuario' para generar claves para el servidor ssh en la máquina remota (mira 'ssh_key_file')
HeroFromEarth
Todavía no estoy seguro de que sea algo más que un hackeo (¡sobre todo porque deja a un usuario con una copia de la clave privada del host!), Pero al menos es algo que ahora responderá la pregunta tal como se me preguntó, así que eliminé mi voto negativo
MadHatter
0

Utilice el módulo openssh_keypair y authorised_key para crear e implementar las claves al mismo tiempo sin guardarlas en su host 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 Bélgica
fuente