Comment puis-je implémenter ansible avec des mots de passe par hôte, en toute sécurité?

108

J'aimerais utiliser ansible pour gérer un groupe de serveurs existants. J'ai créé un ansible_hostsfichier et testé (avec l' -Koption) avec succès avec des commandes qui ne ciblent qu'un seul hôte

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Mon problème actuel est que les mots de passe des utilisateurs sur chaque hôte sont différents, mais je ne trouve pas de moyen de gérer cela dans Ansible.

En utilisant -K, je ne suis invité à entrer qu'un seul mot de passe sudo au départ, qui semble alors être essayé pour tous les hôtes suivants sans demander:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Recherche jusqu'ici:

  • une question StackOverflow avec une réponse incorrecte ("use -K") et une réponse de l'auteur disant "J'ai découvert qu'il me fallait sudo sans mot de passe"

  • La documentation Ansible , qui dit: "L'utilisation de sudo sans mot de passe facilite l'automatisation, mais ce n'est pas obligatoire ." (c'est moi qui souligne)

  • cette question de sécurité StackExchange qui prend comme lu ce qui NOPASSWDest requis

  • article "Approvisionnement évolutif et compréhensible ..." qui dit:

    "Pour exécuter sudo, il peut être nécessaire de saisir un mot de passe, ce qui est un moyen sûr de bloquer Ansible. Une solution simple consiste à exécuter visudo sur l'hôte cible et à s'assurer que l'utilisateur qu'Ansible utilisera pour se connecter ne doit pas entrer de mot de passe"

  • article "Playbooks Ansible de base" , qui dit

    "Ansible peut se connecter au serveur cible en tant que root et éviter la nécessité de sudo, ou laisser l'utilisateur de ansible le faire sans mot de passe, mais la pensée de le faire me fait craquer de me soulever l'oesophage et de bloquer ma trachée. ne pas "

    Mes pensées exactement, mais alors comment s'étendre au-delà d'un seul serveur?

  • numéro 1227 d'ansible , "Ansible devrait demander un mot de passe sudo pour tous les utilisateurs d'un livre de jeu", qui a été fermé il y a un an par mpdehaan avec le commentaire "Je n'ai pas vu beaucoup de demande pour cela, je pense que la plupart des gens craignent un seul compte d'utilisateur ou en utilisant la plupart du temps des clés. "

Alors… comment les gens utilisent-ils Ansible dans de telles situations? La mise NOPASSWDen place /etc/sudoers, la réutilisation du mot de passe sur plusieurs hôtes ou l'activation de la connexion SSH racine semblent constituer des réductions drastiques de la sécurité.

supervacuo
la source
2
Y a-t-il une raison pour laquelle vous n'utilisez pas de clés SSH?
Trondh
22
J'utilise déjà les clés SSH; ils n'affectent pas sudo(ce qui nécessite toujours un mot de passe).
mardi
1
Ce n'est peut-être pas exactement ce que vous recherchez, mais sur les boîtes Ubuntu, j'utilise toujours des clés, c'est-à-dire que je mets ma clé publique dans / root / allowed_keys pour y accéder directement en tant que root. Un inconvénient évident est d'autoriser les connexions root sur ssh ... J'interdit également les connexions de mot de passe sur ssh et lance fail2ban pour plus de sécurité.
senorsmile
27
@senorsmile merci pour la réponse! Est-ce que cela vous dérangerait d'en faire une réponse pour que je puisse vous inviter à ne pas lire la question?
Surveillance
4
c'est-à - dire que le ansible_ssh_passwordparamètre ne s'applique qu'au mot de passe SSH (l'indice est dans le nom ...). & J'utilise déjà la connexion SSH basée sur des clés.
Surveillance

Réponses:

53

Vous avez certainement fait vos recherches ...

D'après toutes mes expériences avec ansible, ce que vous cherchez à accomplir n'est pas pris en charge. Comme vous l'avez mentionné, ansible déclare qu'il n'est pas nécessaire d'utiliser sudo sans mot de passe, et vous avez raison, ce n'est pas le cas. Mais je n'ai pas encore vu de méthode pour utiliser plusieurs mots de passe sudo dans ansible, sans exécuter plusieurs configurations.

Donc, je ne peux pas offrir la solution exacte que vous recherchez, mais vous avez demandé ...

"Alors ... comment les gens utilisent-ils Ansible dans de telles situations? Définir NOPASSWD dans / etc / sudoers, réutiliser le mot de passe sur plusieurs hôtes ou activer la connexion SSH à la racine semblent constituer des réductions drastiques de la sécurité."

Je peux vous donner un avis à ce sujet. Mon cas d'utilisation est constitué de 1 000 nœuds dans plusieurs centres de données prenant en charge une entreprise SaaS globale dans laquelle je dois concevoir / mettre en œuvre des contrôles de sécurité extrêmement stricts en raison de la nature de nos activités. La sécurité est toujours un équilibre, plus de convivialité, moins de sécurité, ce processus n’est pas différent si vous utilisez 10 serveurs ou 1 000 ou 100 000 personnes.

Vous avez absolument raison de ne pas utiliser les connexions root, que ce soit par mot de passe ou par clé ssh. En fait, la connexion root doit être entièrement désactivée si un câble réseau est connecté aux serveurs.

Parlons de la réutilisation des mots de passe. Dans une grande entreprise, est-il raisonnable de demander aux administrateurs système d’avoir des mots de passe différents sur chaque nœud? pour quelques nœuds, peut-être, mais mes administrateurs / ingénieurs se mutineraient s'ils devaient avoir des mots de passe différents sur 1000 nœuds. En outre, il serait presque impossible de mettre en œuvre cette solution, chaque utilisateur devant stocker ses propres mots de passe quelque part, espérons-le, un clavier numérique, pas un tableur. Et chaque fois que vous placez un mot de passe dans un emplacement où il peut être extrait en texte brut, votre sécurité est considérablement réduite. Je préférerais qu'ils sachent, par cœur, un ou deux mots de passe très forts, plutôt que de devoir consulter un fichier de clés chaque fois qu'ils ont besoin de se connecter ou d'appeler sudo sur une machine.

Ainsi, la réutilisation des mots de passe et la normalisation sont totalement acceptables et standard même dans un environnement sécurisé. Sinon, les services de répertoire LDAP, Keystone et autres n'auraient pas besoin d'exister.

Lorsque nous passons aux utilisateurs automatisés, les clés ssh fonctionnent très bien pour vous permettre d'entrer, mais vous devez tout de même passer à travers sudo. Vous avez le choix entre un mot de passe normalisé pour l'utilisateur automatisé (ce qui est acceptable dans de nombreux cas) ou pour activer NOPASSWD, comme vous l'avez indiqué. La plupart des utilisateurs automatisés n'exécutent que quelques commandes. Il est donc tout à fait possible et souhaitable d'activer NOPASSWD, mais uniquement pour les commandes pré-approuvées. Je suggérerais d'utiliser votre gestion de la configuration (ansible dans ce cas) pour gérer votre fichier sudoers afin que vous puissiez facilement mettre à jour la liste des commandes sans mot de passe.

À présent, vous pouvez prendre certaines mesures une fois que vous avez commencé à mettre à l'échelle pour isoler davantage les risques. Bien que nous ayons environ 1 000 nœuds, tous ne sont pas des serveurs de «production», certains sont des environnements de test, etc. Tous les administrateurs ne peuvent pas accéder aux serveurs de production, mais ceux-ci peuvent utiliser leur même clé d'utilisateur / mot de passe SSO comme ailleurs. . Mais les utilisateurs automatisés sont un peu plus sécurisés, par exemple un outil automatisé auquel les administrateurs non producteurs peuvent accéder a un utilisateur et des informations d'identification qui ne peuvent pas être utilisées en production. Si vous souhaitez lancer ansible sur tous les nœuds, vous devez le faire en deux lots, une pour la production et une autre pour la production.

Nous utilisons également puppet, car il s’agit d’un outil de gestion de la configuration contraignant, de sorte que la plupart des modifications apportées à tous les environnements sont forcées.

De toute évidence, si la demande de fonctionnalité que vous avez citée est rouverte / complétée, ce que vous cherchez à faire serait entièrement pris en charge. Même dans ce cas, la sécurité est un processus d’évaluation des risques et de compromis. Si vous ne pouvez mémoriser les mots de passe que pour quelques nœuds sans avoir recours à un post-it, des mots de passe distincts seraient légèrement plus sécurisés. Mais pour la plupart d'entre nous, ce n'est pas une option réalisable.

Zeb
la source
Merci, @Zeb - J'avais imaginé que les utilisateurs disposant de dizaines de milliers de serveurs utiliseraient NOPASSWDde toute façon des raisons de sécurité (probablement soutenus par des règles de pare-feu plus strictes, etc. ), mais il est bon de lire votre cas d'utilisation et de réfléchir à la menace. modèle.
Supervacuo
16
Un commentaire, cependant, à propos de votre suggestion de limiter les commandes "pré-approuvées" sudo(ce qui m’est venu à l’esprit lorsque j’ai découvert que NOPASSWDc’était plutôt nécessaire). Malheureusement, cela ne semble pas du tout supporté - ansible ne fait aucune promesse concernant l’appel direct, par exemple, chown ou les mkdirfichiers binaires, et doit pouvoir fonctionner sudo /bin/shpour la plupart des modules.
Surveillance
Il me semble que l'un de mes ingénieurs s'est plaint de cela il y a quelque temps, c'est agaçant.
Zeb
36

À partir d'Ansible 1.5, il est possible d'utiliser un coffre-fort chiffré pour host_vars et d'autres variables. Cela vous permet au moins de stocker une ansible_sudo_passvariable par hôte (ou par groupe) en toute sécurité. Malheureusement, vous --ask-vault-passne demanderez qu'un seul mot de passe de coffre-fort pour chaque appel, de sorte que vous êtes toujours contraint à un seul mot de passe de coffre-fort pour tous les hôtes que vous utiliserez ensemble.

Néanmoins, pour certaines utilisations, cela peut représenter une amélioration par rapport à la présence d'un mot de passe sudo unique sur plusieurs hôtes, car un attaquant sans accès à vos hôtes chiffrés aurait toujours besoin d'un mot de passe sudo distinct pour chaque machine (ou groupe de machines) qu'il attaque.

Daniel Neades
la source
3
L’ ansible_sudo_passoption semble aussi nouvelle - et semble faire ce que je demandais. Un mot de passe unique pour le coffre-fort est également idéal pour mes besoins. Merci!
Supervacuo
Y at - il un moyen d'éviter le chiffrement tout host_vars en utilisant cette méthode? (une limitation potentielle notée par Alex Dupuy)
supervacuo le
1
@supervacuo - Pour éviter de chiffrer tous les vars hôtes, utilisez simplement un répertoire var hôte contenant main.yml (non chiffré) et secret.yml (chiffré) - voir la dernière partie de cette section de la documentation où il est question du groupe "raleigh" - technique identique fonctionne pour les hôtes et les vars de groupe. J'utilise beaucoup cela, la seule variante est que si un secret n'est requis que par certains livres de lecture, il peut être utile de le stocker entièrement dans une autre arborescence et de l'inclure via un chemin qui inclut le nom d'hôte ou de var.
RichVel
1
Si j'ai chiffré la valeur 'ansible_ssh_pass' dans le coffre-fort, j'ai donc également besoin de dupliquer la valeur 'ansible_sudo_pass'? Existe-t-il un moyen pour la seconde valeur sudo_pass de faire référence à la première valeur 'ssh_pass'?
emeraldjava
Vous pouvez trouver une bonne couverture sur l'utilisation du mot de passe
protégé par coffre-fort
22

Avec Ansible 1.5, il est possible de définir la variable ansible_sudo_pass à l'aide de lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Je trouve cela plus pratique que d’utiliser des fichiers host_vars/pour plusieurs raisons:

  • J'utilise en fait with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" les mots de passe pour l' utilisateur distant déployé (qui est alors nécessaire pour sudo ), afin qu'ils soient déjà présents dans les fichiers (bien que ces recherches en texte brut perdent la valeur salt stockée dans le fichier lorsque la valeur hachée est générée) .

  • Cela ne conserve que les mots de passe dans le fichier (aucun ansible_sudo_pass:texte en clair connu) pour augmenter la sécurité cryptographique d’epsilon. Plus important encore, cela signifie que vous ne chiffrez pas toutes les autres variables spécifiques à l'hôte, elles peuvent donc être lues sans le mot de passe du coffre-fort.

  • En plaçant les mots de passe dans un répertoire distinct, il est plus facile de garder les fichiers en dehors du contrôle de la source ou d'utiliser un outil tel que git-crypt pour les stocker sous forme chiffrée (vous pouvez utiliser cela avec Ansible antérieur, dépourvu de la fonctionnalité de coffre-fort). J'utilise git-crypt et comme je n'extrais que le référentiel sous forme déchiffrée sur des systèmes de fichiers chiffrés, je ne me soucie pas du coffre-fort et je n'ai donc pas besoin de taper un mot de passe du coffre-fort. (L'utilisation des deux serait bien sûr plus sécurisée.)

Vous pouvez également utiliser la fonction de recherche avec ansible_ssh_pass ; cela peut même être possible avec les versions précédentes d'Ansible qui n'ont pas ansible_sudo_pass .

Alex Dupuy
la source
2
J'ai finalement réussi à essayer (merci!), Mais je ne vois pas comment cela fonctionnerait sans cela git-crypt. d'aussi loin que je puisse voir. Il semble que Ansible ne supporte pas encore l' utilisation lookupsur un emplacement de stockage chiffré. La passworddocumentation du module indique qu'il existe une prise en charge non encore documentée du stockage crypté, mais je n'ai pas encore trouvé de détails. Des indices?
Supervacuo
19

Utiliser pass est une méthode simple pour fournir des mots de passe sudo compatibles avec ansible. pass stocke un mot de passe par fichier, ce qui facilite le partage des mots de passe via git ou d'autres méthodes. Il est également sécurisé (avec GnuPG) et si vous utilisez gpg-agent, il vous permet d’utiliser ansible sans saisir de mot de passe pour chaque utilisation.

Pour fournir le mot de passe stocké servers/foode serveur fooà ansible, utilisez-le dans un fichier d'inventaire comme celui-ci:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Etant donné que vous avez déverrouillé la clé pour gpg-agent plus tôt, cela fonctionnera sans devoir entrer de mot de passe.

fqxp
la source
3

C'est un fil assez ancien, néanmoins:

  • Nous utilisons deux systèmes d’authentification différents en interne. La gestion des machines est effectuée à partir des stations de travail locales de mon équipe.
  • J'ai écrit un vars_pluginpour Ansible (une implémentation assez complète est disponible à l' adresse https://gist.github.com/mfriedenhagen/e488235d732b7becda81 ) qui différencie plusieurs systèmes d'authentification:
  • Le nom du système d'authentification est spécifique à un groupe.
  • L'utilisateur login / sudo utilisé est spécifique au groupe et à l'administrateur.
  • Je tire donc l'utilisateur de l'environnement de l'administrateur et du mot de passe correspondant via la bibliothèque python-keyring d'un mot de passe sécurisé (nous utilisons le trousseau de Mac OS X, mais la documentation kwallet Gnome et _win_crypto sont également supportés).
  • J'ai défini les autorisations sur les mots de passe dans le trousseau de Mac OS X pour m'avertir du fait que la sécurité du programme en ligne de commande demande l'accès à un mot de passe pour chaque système d'authentification utilisé par les hôtes. Je lance donc "ansible -s all -m ping". et obtenir deux invites (une pour chaque système d'authentification) où j'appuie sur la barre d'espace et ansible récupère les mots de passe.
Mirko Friedenhagen
la source
Cela a l'air très chouette, merci - j'aime bien l'idée de ne pas avoir à stocker les mots de passe à deux endroits. Pour le moment, je suis coincé sous KeepassX (car le trousseau de clés GNOME ne semble pas très portable), mais je peux peut-être faire python-keepassfonctionner?
Supervacuo
Autant que je sache, python-keyring est une abstraction pour cela, vos collègues peuvent donc utiliser d'autres systèmes d'exploitation. Ou stockez-vous votre base de données keepassx sur une clé USB et devez-vous l’administrer à partir de postes de travail sous différents systèmes d’exploitation?
Mirko Friedenhagen
compris; Je voulais dire que je devais déjà utiliser KeepassX pour avoir accès aux mots de passe des systèmes non-GNOME, donc les stocker dans gnome-keyringce système signifierait conserver des enregistrements en double. Encore mieux que d'utiliser NOPASSWD, cependant…
supervacuo
0

Une méthode possible consiste à utiliser des variables environnementales.

par exemple

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Ensuite, dans les jeux, vous pouvez rechercher le mot de passe sudo en utilisant:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Paul Calabro
la source