Comment faire en sorte qu'Ansible utilise un mot de passe si la clé a été rejetée?

14

Mes nouvelles instances de serveur sont configurées pour se connecter sur root via ssh avec mot de passe. Je veux que mon playbook Ansible le reconfigure pour utiliser des clés à la place et désactiver la connexion root avec mot de passe lors de la première exécution, j'ai donc besoin de quelque chose comme ceci:

  • essayez de vous connecter avec la clé
  • si vous ne pouvez pas vous connecter avec la clé:

    • connexion avec mot de passe
    • ajouter la clé aux clés autorisées
    • désactiver la connexion root avec mot de passe
    • éventuellement reconnecter à l'aide de la clé
  • faire d'autres tâches

Comment puis-je y parvenir?

EDIT : Pour être clair, je ne demande pas comment ajouter une clé ou désactiver root, c'est juste pour le contexte. Je demande comment revenir au mot de passe s'il ne peut pas s'authentifier avec la clé. Avec --ask-passou ansible_ssh_passdéfini, Ansible n'essaiera même pas d'utiliser l'authentification par clé publique

petr0
la source
Bonne question, qu'avez-vous essayé jusqu'à présent?
dawud
1
J'ai pris la configuration ssh dans un playbook séparé et je l'exécute avec l'option -k, puis j'exécute le playbook principal sans -k (en utilisant la clé de l'agent). J'espérais cependant qu'il puisse être emballé dans un seul livre de lecture ...
petr0
@ petr0 Cela fonctionne pour moi lorsque le mot de passe de demande est pour un utilisateur différent de la clé (c'est-à-dire lorsque vous changez d'utilisateur distant après avoir désactivé ssh avec mot de passe). Je ne sais pas si cela aide.
DylanYoung

Réponses:

6

Vous pouvez essayer l' PreferredAuthenticationsoption en la réglant sur publickey,password. La valeur par défaut les inclut dans cet ordre, ainsi que d'autres options, donc ansible le définit probablement. L'ajout via -oou le client ssh_configpeut empêcher cela.

Vous pourrez peut-être utiliser un script wrapper. Par exemple, avec ceci dans key_or_password.shet un pass.shqui donne le mot de passe, l'exécution bash key_or_password.sh root@hostessaiera un publickey suivi d'une connexion par mot de passe non interactive.

export DISPLAY=dummy:0
export SSH_ASKPASS=$PWD/pass.sh
exec setsid ssh -v -o 'PreferredAuthentications publickey,password' "$@"

Le journal indique quelle méthode a réussi, par exemple

debug1: Authentication succeeded (publickey).
eisd
la source
7

Voici ce que je fais si ansible_userest différent pour la `` première exécution '' du playbook (par exemple, si vous n'avez qu'un rootutilisateur et que vous allez configurer un nouvel utilisateur avec une clé SSH):

  • Enregistrez le mot de passe ansible_passcomme vous le feriez si vous utilisiez des connexions par mot de passe (n'oubliez pas d'utiliser Vault), il devrait s'agir du mot de passe de l'utilisateur que vous utilisez pour la première exécution du playbook.
  • Définissez ansible_userle nom d'utilisateur de l'utilisateur que vous souhaitez utiliser après la première exécution lorsque les utilisateurs sont correctement configurés sur le serveur.
  • Définissez une variable de ansible_user_first_runl'utilisateur que vous allez utiliser pour la «première exécution» du playbook, par exemple root.
  • Utilisez une commande locale pour tenter de vous connecter au serveur avec la bonne clé SSH, en utilisant ignore_errorsetchanged_when: False
  • Si cela échoue, mettez ansible_userà jour la valeur deansible_user_first_run

Voici le code:

---
- name: Check if connection is possible
  command: ssh -o User={{ ansible_user }} -o ConnectTimeout=10 -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes {{ inventory_hostname }} echo "Worked"
  register: result
  connection: local
  ignore_errors: yes
  changed_when: False
- name: If no connection, change user_name
  connection: local
  set_fact:
    ansible_user: "{{ ansible_user_first_run }}"
  when: result|failed

Remarque: Cela vaut la peine d'être configuré transport = sshcar paramiko peut échouer de manière inattendue à se connecter au serveur dans certaines configurations (par exemple, lorsque le serveur est configuré pour ne pas accepter les mots de passe, et que vous essayez d'abord avec une clé puis un mot de passe ... bizarre!) Le transport ssh est également plus rapide, donc ça vaut le coup quand même.

Remarque supplémentaire: Si vous utilisez cette méthode, vous devez spécifier gather_facts: falsedans votre fichier de définition de playbook afin que les tâches de configuration / collecte de faits ne soient pas exécutées automatiquement avant de passer à l'étape de test des mots de passe. Si vous avez besoin de l'un des faits ansibles, vous devrez appeler explicitement setupvotre rôle avant d'accéder à l'une des données normalement disponibles dans des endroits tels que ansible_devices, etc. Une bonne façon de le faire est d'appeler setupavec une whenclause qui vérifie si le fait que vous utilisez est vide ou non avant de l'appeler dans votre rôle.

Tom Bull
la source
Votre solution est bonne mais vous devez ajouter un gather_facts: nopour cesser ansible d'essayer de vous connecter lors du lancement du playbook :)
k4cy
Vous avez raison. J'ai collect_facts désactivé pour tous mes playbooks, donc je dois appeler explicitement «setup». J'ai oublié de le mentionner dans la réponse, je vais le mettre à jour maintenant.
Tom Bull
5

Vous pouvez utiliser --ask-passlors de l'exécution de ansible-playbook.

Pour d'autres tâches que vous avez demandées, il est possible de le faire par divers moyens, par exemple, le module de copie.
La désactivation de la connexion root peut également être effectuée, par exemple. en modélisant sshd_confou en insérant une ligne dans le fichier conf.

titus
la source
--ask-pass (qui est le même que -k) est ce que je fais et j'en ai écrit dans le commentaire ci
petr0