Distribuer les clés publiques ssh entre les hôtes

11

Je configure certaines machines avec Ansible et je dois activer les connexions sans mot de passe entre elles. J'ai un maître de base de données et plusieurs esclaves. Pour la réplication initiale, les esclaves doivent ssh dans le maître et obtenir une copie de la base de données. Je ne sais pas quelle est la meilleure façon d'ajouter dynamiquement toutes les clés publiques d'esclaves au authorized_keysfichier master .

J'ai déjà pensé à fournir les clés publiques des esclaves en tant que variables, puis à les ajouter via le authorized_keymodule. Mais alors je dois maintenir la liste des clés. Je cherche une approche où j'ajoute juste un autre hôte le groupe des esclaves et le reste fonctionnera automatiquement.

Des idées?

Mettre à jour:

Jusqu'à présent, j'ai obtenu le pseudo-code suivant:

# 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

La boucle avec le {% %}seul fonctionne dans les fichiers modèles et pas directement dans les playbooks. Y a-t-il un moyen de le faire dans mon playbook?

plongeur
la source

Réponses:

5

J'ai trouvé une solution qui fonctionne pour moi. Je crée les clés publiques / privées sur ma machine à partir de laquelle Ansible est exécuté et lors de la première connexion, je mets les clés en place.

Ensuite, j'ajoute les clés de tous les esclaves au maître avec ce qui suit:

# 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

Le playbook complet se trouve sur github.com/soupdiver/ansible-cluster .

plongeur
la source
5

Je pense que la solution suivante devrait fonctionner dans votre cas. Je l'ai utilisé pour un scénario similaire avec un serveur de sauvegarde central et plusieurs clients de sauvegarde.

J'ai un rôle (disons " db_replication_master ") associé au serveur recevant les connexions:

    - 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

Ensuite, nous créons les tâches réelles dans le rôle 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

Nous sommes donc essentiellement:

  • créer dynamiquement des clés ssh sur les esclaves qui ne les ont toujours pas
  • nous utilisons ensuite delegate_to pour exécuter le module de récupération sur les esclaves et récupérer leurs clés de pub ssh sur l'hôte exécutant ansible, enregistrant également le résultat de cette opération dans une variable afin que nous puissions accéder à la liste réelle des fichiers récupérés
  • après cela, nous continuons à pousser normalement les pubkeys ssh récupérés (ainsi que toutes les pubkeys supplémentaires fournies) vers le nœud maître avec le module authorized_keys (nous utilisons quelques filtres jinja2 pour extraire les chemins de fichier de la variable dans la tâche ci-dessus)
  • enfin, nous supprimons les fichiers pubkey mis en cache localement sur l'hôte exécutant ansible

La limitation d'avoir le même utilisateur sur tous les hôtes peut probablement être contournée, mais d'après ce que j'obtiens de votre question, ce n'est probablement pas un problème pour vous (c'est un peu plus pertinent pour mon scénario de sauvegarde). Vous pouvez bien sûr également configurer le type de clé (rsa, dsa, ecdsa, etc.).

Mise à jour : oups, j'avais écrit à l'origine en utilisant une terminologie spécifique à mon problème, pas la vôtre! Cela devrait avoir plus de sens maintenant.

Leo Antunes
la source
0

J'ai le même problème et je l'ai résolu de cette façon:

---
# 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
la source