Distribuya claves públicas ssh entre hosts

11

Estoy configurando algunas máquinas con Ansible y necesito habilitar conexiones sin contraseña entre ellas. Tengo un maestro de base de datos y varios esclavos. Para la replicación inicial, los esclavos necesitan ingresar al maestro y obtener una copia de la base de datos. No estoy seguro de cuál es la mejor manera de agregar dinámicamente todas las claves públicas esclavas al authorized_keysarchivo maestro .

Ya pensé en proporcionar las claves públicas esclavas como variables y luego agregarlas a través del authorized_keymódulo. Pero luego debo mantener la lista de claves. Estoy buscando un enfoque en el que simplemente agregue otro host al grupo de esclavos y el resto funcionará automáticamente.

¿Algunas ideas?

Actualizar:

Hasta ahora obtuve el siguiente pseudocódigo:

# collect public keys from slave machines
- name: collect slave keys
  {% for host in groups['databases_slave'] %}
     shell: /bin/cat /var/lib/postgresql/.ssh/id_rsa.pub
     register: slave_keys #how to add to an array here?
  {% endfor %}

# Tasks for PostgreSQL master
- name: add slave public key
  sudo: yes
  authorized_key: user=postgres state=present key={{ item }}
  with_items: slave_keys

El bucle con el {% %}solo funciona en archivos de plantilla y no en libros de jugadas directamente. ¿Alguna forma de hacer esto en mi libro de jugadas?

sopa de sopa
fuente

Respuestas:

5

Se me ocurrió una solución que funciona para mí. Creo las claves públicas / privadas en mi máquina desde donde se ejecuta Ansible y en la primera conexión puse las claves en su lugar.

Luego agrego las claves de todos los esclavos al maestro con lo siguiente:

# Tasks for PostgreSQL master
- name: add slave public key
  sudo: yes
  authorized_key: user=postgres state=present key="{{ lookup('file', '../../../keys/' + item + '/id_rsa.pub') }}"
  with_items: groups.databases_slave

El libro de jugadas completo se puede encontrar en github.com/soupdiver/ansible-cluster .

sopa de sopa
fuente
5

Creo que la siguiente solución debería funcionar en su caso. Lo he estado usando para un escenario similar con un servidor de respaldo central y múltiples clientes de respaldo.

Tengo un rol (digamos " db_replication_master ") asociado al servidor que recibe las conexiones:

    - role: db_replication_master
      db_slaves: ['someserver', 'someotherserver']
      db_slave_user: 'someuser' # in case you have different users
      db_master_user: 'someotheruser'
      extra_pubkeys: ['files/id_rsa.pub'] # other keys that need access to master

Luego creamos las tareas reales en el rol db_replication_master :

    - name: create remote accounts ssh keys
      user:
        name: "{{ db_slave_user }}"
        generate_ssh_key: yes
      delegate_to: "{{ item }}"
      with_items: db_slaves

    - name: fetch pubkeys from remote users
      fetch:
        dest: "tmp/db_replication_role/{{ item }}.pub"
        src: "~{{db_slave_user}}/.ssh/id_rsa.pub"
        flat: yes
      delegate_to: "{{ item }}"
      with_items: db_slaves
      register: remote_pubkeys
      changed_when: false # we remove them in "remove temp local pubkey copies" below

    - name: add pubkeys to master server
      authorized_key:
        user: "{{ db_master_user }}"
        key: "{{ lookup('file', item) }}"
      with_flattened:
        - extra_pubkeys
        - "{{ remote_pubkeys.results | default({}) | map(attribute='dest') | list }}"

    - name: remove temp local pubkey copies
      local_action: file dest="tmp/db_replication_role" state=absent
      changed_when: false

Así que básicamente somos:

  • crear dinámicamente claves ssh en esos esclavos que aún no las tienen
  • entonces estamos usando delegate_to para ejecutar el módulo de búsqueda en los esclavos y buscar sus ske pubkeys en el host que ejecuta ansible, también guardando el resultado de esta operación en una variable para que podamos acceder a la lista real de archivos recuperados
  • después de eso, normalmente procedemos a empujar los pubkeys ssh recuperados (más cualquier pubkeys adicional proporcionado) al nodo maestro con el módulo autorizado_keys (usamos un par de filtros jinja2 para extraer las rutas de archivos de la variable en la tarea anterior)
  • finalmente eliminamos los archivos pubkey almacenados en caché localmente en el host que ejecuta ansible

La limitación de tener el mismo usuario en todos los hosts probablemente se pueda solucionar, pero por lo que obtengo de su pregunta, probablemente no sea un problema para usted (es un poco más relevante para mi escenario de copia de seguridad). Por supuesto, también puede hacer que el tipo de clave (rsa, dsa, ecdsa, etc.) sea configurable.

Actualización : ¡Uy, originalmente había escrito usando terminología específica para mi problema, no el tuyo! Debería tener más sentido ahora.

Leo Antunes
fuente
0

Obtuve el mismo problema y lo resolví de esta manera:

---
# Gather the SSH of all hosts and add them to every host in the inventory
# to allow passwordless SSH between them
- hosts: all
  tasks:
  - name: Generate SSH keys
    shell: ssh-keygen -q -t rsa -f /root/.ssh/id_rsa -N ''
    args:
      creates: /root/.ssh/id_rsa

  - name: Allow passwordless SSH between all hosts
    shell: /bin/cat /root/.ssh/id_rsa.pub
    register: ssh_keys

  - name: Allow passwordless SSH between all hosts
    lineinfile:
      dest: /root/.ssh/authorized_keys
      state: present
      line:  " {{ hostvars[item]['ssh_keys']['stdout'] }}"
    with_items: "{{ groups['all']}}"
Julen Larrucea
fuente