Aller au contenu
Infrastructure as Code medium

Module authorized_key Ansible : clés SSH des utilisateurs

10 min de lecture

Logo Ansible

ansible.posix.authorized_key: gère les clés SSH publiques dans le fichier ~/.ssh/authorized_keys d’un utilisateur. C’est l’outil du provisioning des accès SSH — ajouter, supprimer, ou forcer la liste exclusive des clés autorisées.

Ce module appartient à la collection ansible.posix (pas builtin). Sur Ansible Core 2.20, l’installer via ansible-galaxy collection install ansible.posix.

Options principales : user:, key:, state:, exclusive: true (remplacement complet), key_options: (from=, command=, no-pty), comment:.

  • Ajouter une clé SSH à un utilisateur existant (avec permissions strictes auto).
  • Distinguer state: present (ajout) de exclusive: true (remplacement total).
  • Restreindre une clé avec key_options: pour le moindre privilège.
  • Charger une clé depuis un fichier local avec lookup('file', ...).
  • Provisionner plusieurs clés pour plusieurs users en une passe (subelements).
  • Avoir ansible.posix installé : ansible-galaxy collection install ansible.posix.
  • Avoir lu Module user — l’utilisateur doit exister avant l’ajout de la clé.
- name: Cle SSH d alice
ansible.posix.authorized_key:
user: alice
key: "{{ lookup('file', 'files/alice.pub') }}"
state: present

lookup('file', ...) lit le fichier côté control node et injecte le contenu en string. La clé n’est pas transférée comme un fichier — c’est juste son contenu qui est ajouté à authorized_keys.

Côté managed node, le module gère automatiquement :

  • Création de ~/.ssh/ avec mode 0700.
  • Création de ~/.ssh/authorized_keys avec mode 0600.
  • Owner / group corrects (l’utilisateur cible).

C’est essentiel : sans ces permissions strictes, sshd refuse silencieusement la clé. Le module évite ce piège classique.

exclusive: true (remplacement complet — révoque massive)

Section intitulée « exclusive: true (remplacement complet — révoque massive) »
- name: Forcer la liste exclusive des cles
ansible.posix.authorized_key:
user: alice
key: "{{ lookup('file', 'files/alice.pub') }}"
state: present
exclusive: true

exclusive: true efface toutes les clés existantes pour ne laisser que celles spécifiées. Pattern de revoke d’accès massive : un développeur quitte l’équipe → relancer le play sans sa clé pour la révoquer partout.

Risque : si key: est vide ou la lookup échoue, toutes les clés sont effacées. Précaution :

- name: Verifier que la cle est bien chargee
ansible.builtin.assert:
that:
- alice_pub_key | length > 100 # Une cle ed25519 fait ~100 chars
fail_msg: "Cle alice introuvable — exclusive: true serait dangereux"
vars:
alice_pub_key: "{{ lookup('file', 'files/alice.pub') }}"
- name: Maintenant on peut faire exclusive: true
ansible.posix.authorized_key:
user: alice
key: "{{ alice_pub_key }}"
exclusive: true
- name: Cle restreinte (from=IP + commande forcee)
ansible.posix.authorized_key:
user: bob
key: "{{ lookup('file', 'files/bob.pub') }}"
key_options: 'from="10.10.20.0/24",command="/usr/local/bin/restricted",no-pty,no-X11-forwarding'

La ligne dans authorized_keys est préfixée par les restrictions :

from="10.10.20.0/24",command="/usr/local/bin/restricted",no-pty,no-X11-forwarding ssh-ed25519 AAAA... bob@laptop

Restrictions courantes :

OptionEffet
from="IP_or_CIDR"Limite l’IP source autorisée
command="/path"Force l’exécution de cette commande (ignore SSH command client)
no-ptyPas de TTY (interdit ssh user@host interactif)
no-X11-forwardingPas de forwarding X11
no-port-forwardingPas de tunnel SSH (-L, -R)
no-agent-forwardingPas de forwarding de l’agent SSH

Pattern security-hardened : pour des clés de service (rsync, backup, monitoring), combiner from= + command= + no-pty + no-X11-forwarding + no-port-forwarding. Un attaquant qui vole la clé ne peut rien faire d’autre que la commande imposée.

- name: Provisionner N users x M cles
hosts: db1.lab
become: true
vars:
team_users:
- name: alice
ssh_keys:
- "ssh-ed25519 AAAA1 alice@laptop"
- "ssh-ed25519 AAAA2 alice@server"
- name: bob
ssh_keys:
- "ssh-ed25519 BBBB1 bob@laptop"
tasks:
- name: Ajouter chaque cle a chaque user
ansible.posix.authorized_key:
user: "{{ item.0.name }}"
key: "{{ item.1 }}"
state: present
loop: "{{ team_users | subelements('ssh_keys') }}"
loop_control:
label: "{{ item.0.name }}"

subelements('ssh_keys') produit des paires (parent, child) — parfait pour des structures N users avec M clés chacun. Une seule tâche, idempotente.

- name: Revoquer la cle d alice
ansible.posix.authorized_key:
user: alice
key: "{{ lookup('file', 'files/alice.pub') }}"
state: absent

Ansible matche par contenu de la clé (pas par commentaire ni hash). Si vous générez une nouvelle clé pour alice, l’ancienne reste si vous ne la révoquez pas explicitement.

SymptômeCauseFix
~/.ssh/authorized_keys mode 0644 → SSH refusecopy: brut au lieu d’authorized_key:Toujours utiliser le module dédié
exclusive: true efface toutLookup file vide ou erreurPrécéder d’un assert: sur la longueur de la clé
Clé reste après changement de userMatch par contenu — l’ancienne clé n’est pas dans la nouvellestate: absent explicite, ou exclusive: true
no module named ansible.posixCollection non installéeansible-galaxy collection install ansible.posix
  • Module ansible.posix.authorized_key: (pas builtin — collection requise).
  • Permissions strictes auto : 0700 sur ~/.ssh/, 0600 sur authorized_keys.
  • exclusive: true = révoque massive — risqué si la clé n’est pas chargée.
  • key_options: = restrictions SSH (from=, command=, no-pty).
  • Pattern subelements = N users × M clés en une tâche.
  • Match par contenu — pas par comment ni hash.

Cette page a un lab d’accompagnement : labs/modules-utilisateurs/authorized-key/ dans stephrobert/ansible-training.

Challenge — sur db1.lab :

  1. Créer alice + bob.
  2. Provisionner les clés depuis files/<user>.pub.
  3. Restreindre la clé de bob (from="10.10.20.0/24", no-pty).
  4. Ajouter une clé de service avec command="/usr/local/bin/backup.sh".

Validation pytest+testinfra :

Fenêtre de terminal
ansible-playbook solution.yml
pytest -v labs/modules-utilisateurs/authorized-key/challenge/tests/

6 tests vérifient permissions strictes, présence des clés, et restrictions appliquées.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn