Spécifiez le mot de passe sudo pour Ansible

225

Comment spécifier un mot de passe sudo pour Ansible de manière non interactive?

J'utilise le playbook Ansible comme ceci:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username --ask-sudo-pass

Mais je veux le faire comme ceci:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username` **--sudo-pass=12345**

Y a-t-il un moyen? Je souhaite automatiser autant que possible le déploiement de mon projet.

Slava Fomin II
la source
4
Voir aussi: serverfault.com/questions/560106/…
utapyngo

Réponses:

170

Vous pouvez transmettre des variables sur la ligne de commande via --extra-vars "name=value". La variable de mot de passe Sudo est ansible_sudo_pass. Votre commande ressemblerait donc à:

ansible-playbook playbook.yml -i inventory.ini --user=username \
                              --extra-vars "ansible_sudo_pass=yourPassword"

Mise à jour 2017 : Ansible 2.2.1.0 utilise désormais var ansible_become_pass. Soit semble fonctionner.

Alexandr Nikitin
la source
7
Du point de vue de la sécurité, la meilleure réponse, si vous ajoutez ce qui suit: history -caprès l'exécution du yml.
kiltek
12
@kiltek: ou ajoutez un espace supplémentaire au début de la ligne (en bash) qui n'écrira * pas * la ligne .bash_history.
ccpizza
44
Pas une bonne pratique pour passer des mots de passe en ligne de commande. Tout le monde pourra voir le mot de passe dans la liste des processus, pendant que la commande s'exécute ...
Pavel Chernikov
22
encore, ne le faites pas. --ask-sudo-pass
JasonG
2
@scrutari Il est parfaitement valable dans certaines situations: Par exemple: changement d'un mot de passe initial par défaut, mondialement connu, pour injecter la clé ssh publique de l'utilisateur ... Pensez à la configuration initiale d'un système fraîchement repensé.
Ceredig
236

Les documents recommandent fortement de ne pas définir le mot de passe sudo en texte brut et de l'utiliser --ask-sudo-passà la place sur la ligne de commande lors de l'exécutionansible-playbook


Mise à jour 2016:

Ansible 2.0 (pas 100% quand) marqué --ask-sudo-passcomme obsolète. Les documents recommandent désormais d'utiliser à la --ask-become-passplace, tout en échangeant l'utilisation de sudotout au long de vos playbooks avec become.

deefour
la source
16
Oui, je peux voir pourquoi cela est recommandé. Cependant, lorsque nous utilisons Ansible dans le cadre du processus de déploiement, quelle est la meilleure façon d'automatiser cela? Il n'est pas très pratique de s'arrêter au milieu du processus de déploiement et de demander à l'utilisateur de saisir le mot de passe sudo.
Slava Fomin II
9
Remarque --ask-sudo-pass peut être abrégé en -K, cependant, pour autant que je puisse voir, il n'y a aucun moyen de gérer un playbook fonctionnant sur plusieurs serveurs avec des mots de passe différents (il ne vous le demande qu'une seule fois), donc je pense sans mot de passe sudo est la voie à suivre.
William Turrell
1
Ne semble pas fonctionner. mais la suggestion suivante ("some-host ansible_sudo_pass = 'foobar'") le fait
nadavkav
--ask-sudo-pass a été déprécié plus tôt, en 1.9
Chris Betti
J'aimerais mettre à jour la réponse avec un lien source si vous en avez un.
deefour
106

Probablement la meilleure façon de le faire - en supposant que vous ne pouvez pas utiliser la solution NOPASSWD fournie par scottod est d'utiliser la solution de Mircea Vutcovici en combinaison avec Ansible vault .

Par exemple, vous pourriez avoir un playbook quelque chose comme ceci:

- hosts: all

  vars_files:
    - secret

  tasks:
    - name: Do something as sudo
      service: name=nginx state=restarted
      sudo: yes

Ici, nous incluons un fichier appelé secretqui contiendra notre mot de passe sudo.

Nous utiliserons ansible-vault pour créer une version chiffrée de ce fichier:

ansible-vault create secret

Cela vous demandera un mot de passe, puis ouvrez votre éditeur par défaut pour modifier le fichier. Vous pouvez mettre votre ansible_sudo_passici.

par exemple secret::

ansible_sudo_pass: mysudopassword

Enregistrez et quittez, vous avez maintenant un secretfichier crypté qu'Ansible est capable de décrypter lorsque vous exécutez votre playbook. Remarque: vous pouvez modifier le fichier avec ansible-vault edit secret(et saisir le mot de passe que vous avez utilisé lors de la création du fichier)

La dernière pièce du puzzle est de fournir à Ansible un fichier --vault-password-filequ'il utilisera pour décrypter votre secretfichier.

Créez un fichier appelé vault.txtet entrez le mot de passe que vous avez utilisé lors de la création de votre secretfichier. Le mot de passe doit être une chaîne stockée sur une seule ligne dans le fichier.

Depuis les documents Ansible:

.. assurez-vous que les autorisations sur le fichier sont telles que personne d'autre ne peut accéder à votre clé et n'ajoutez pas votre clé au contrôle de code source

Enfin: vous pouvez maintenant exécuter votre playbook avec quelque chose comme

ansible-playbook playbook.yml -u someuser -i hosts --sudo --vault-password-file=vault.txt 

Ce qui précède suppose la disposition de répertoire suivante:

.
|_ playbook.yml
|_ secret
|_ hosts
|_ vault.txt

Vous pouvez en savoir plus sur Ansible Vault ici: https://docs.ansible.com/playbooks_vault.html

toast38coza
la source
5
Remarque: à partir de ansible 1.9, il semble que vous ne puissiez plus utiliser la variable ansible_sudo_pass (ou ansible_become_pass): "fatal: [...] => Mot de passe manquant"
toast38coza
6
J'utilise cette solution en production, jenkins stocke le mot de passe du coffre-fort en tant que variable d'environnement obscurci, l'écrit au moment de l'exécution dans un fichier temporaire et continue d'appeler ansible.
simone cittadini
6
ou plus simplement: ansible-vault create group_vars/all/ansible.ymlet ajoutez- ansible_sudo_pass: yourpasswordy. Pas besoin de changer les playbooks ou l'inventaire
Bouke Versteegh
1
J'ai essayé mais j'ai eu cette erreur:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
À quoi sert un coffre-fort si vous stockez le mot de passe dans le coffre-fort en texte brut juste à côté?
Erik
44

En regardant le code ( runner/__init__.py), je pense que vous pouvez probablement le définir dans votre fichier d'inventaire:

[whatever]
some-host ansible_sudo_pass='foobar'

Il semble également y avoir une disposition dans le ansible.cfgfichier de configuration, mais pas implémentée pour le moment ( constants.py).

leucos
la source
7
Une excellente façon de configurer ce serait en toute sécurité à stocker ceci dans le host_varsou group_varsrépertoire, puis crypter le fichier en utilisant ansible-voûte
Kyle
44

Je ne pense pas qu'ansible vous permettra de spécifier un mot de passe dans les drapeaux comme vous le souhaitez. Il peut y avoir quelque part dans les configurations cela peut être défini mais cela rendrait l'utilisation d'ansible moins sûre dans l'ensemble et ne serait pas recommandée.

Une chose que vous pouvez faire est de créer un utilisateur sur la machine cible et de leur accorder des privilèges sudo sans mot de passe à toutes les commandes ou à une liste restreinte de commandes.

Si vous exécutez sudo visudoet entrez une ligne comme celle ci-dessous, l'utilisateur «privilegedUser» ne devrait pas avoir à saisir de mot de passe lorsqu'il exécute quelque chose comme sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
Scottod
la source
7
@bschlueter donc vous approuvez les mauvaises pratiques?
stephen
1
Je ne pense pas que ce soit une bonne idée. L'utilisation de --ask-sudo-pass est logique pour moi.
kgpdeveloper
@simone cittadini Je suis totalement d'accord car c'est en fait la réponse que j'allais donner. Celui-ci est un risque pour la sécurité.
einarc
Le risque de sécurité est moindre si vous utilisez sudo sans mot de passe pour déployer sur staging / prod, mais que vous souhaitez utiliser ces réponses pour éviter d'avoir à taper votre mot de passe de connexion d'ordinateur portable local lors du déploiement sur votre hôte local toutes les 15 minutes toute la journée, tous les jours.
Jonathan Hartley
Comment ajoutez-vous cette ligne en utilisant Ansible?
Matthias
21

Le mot de passe sudo est stocké sous la forme d'une variable appelée ansible_sudo_pass. Vous pouvez définir cette variable de plusieurs manières:

Par hôte, dans votre fichier d'hôtes d'inventaire ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Par groupe, dans votre fichier de groupes d'inventaire ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Par groupe, en groupe vars ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Par groupe, crypté ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
la source
18

Vous pouvez définir le mot de passe pour un groupe ou pour tous les serveurs à la fois:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1
Mircea Vutcovici
la source
14

J'arrachais mes cheveux sur celui-ci, maintenant j'ai trouvé une solution qui fait ce que je veux:

1 fichier chiffré par hôte contenant le mot de passe sudo

/ etc / ansible / hosts:

[all:vars]
ansible_ssh_connection=ssh ansible_ssh_user=myuser ansible_ssh_private_key_file=~/.ssh/id_rsa

[some_service_group]
node-0
node-1

puis vous créez pour chaque hôte un fichier var chiffré comme ceci:

ansible-vault create /etc/ansible/host_vars/node-0

avec contenu

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

la façon dont vous organisez le mot de passe du coffre-fort (entrez via --ask-vault-pass) ou par cfg dépend de vous

sur cette base, je pense que vous pouvez simplement crypter tout le fichier d'hôtes ...

greenone83
la source
Le chiffrement à l'aide du coffre-fort est le plus logique pour moi, bien que j'aie eu du mal à les utiliser ansible-playback. J'ai dû utiliser -e @vault/filename.extpour utiliser le coffre-fort avec mon ansible-playbookappel.
Alex
9

Une façon plus judicieuse de le faire consiste à stocker votre sudomot de passe dans un coffre-fort sécurisé tel que LastPass ou KeePass , puis à le passer à l' ansible-playbookaide de -e@mais au lieu de coder en dur le contenu d'un fichier réel, vous pouvez utiliser la construction -e@<(...)pour exécuter une commande dans un sous-shell, et rediriger sa sortie (STDOUT) vers un descripteur de fichier anonyme, en fournissant efficacement le mot de passe au -e@<(..).

Exemple

$ ansible-playbook -i /tmp/hosts pb.yml \
   -e@<(echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)")

Ce qui précède fait plusieurs choses, décomposons-le.

  • ansible-playbook -i /tmp/hosts pb.yml - évidemment exécuter un playbook via ansible-playbook
  • $(lpass show folder1/item1 --password)"- exécute la CLI LastPass lpasset récupère le mot de passe à utiliser
  • echo "ansible_sudo_pass: ...password..." - prend la chaîne 'ansible_sudo_pass:' et la combine avec le mot de passe fourni par lpass
  • -e@<(..)- rassemble ce qui précède et connecte le sous-shell de <(...)comme descripteur de fichier ansible-playbookà consommer.

Améliorations supplémentaires

Si vous préférez ne pas taper cela à chaque fois, vous pouvez simplement faire des choses comme ça. Créez d'abord un alias dans votre .bashrccomme ceci:

$ cat ~/.bashrc
alias asp='echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)"'

Vous pouvez maintenant exécuter votre playbook comme ceci:

$ ansible-playbook -i /tmp/hosts pb.yml -e@<(asp)

Références

slm
la source
1
Utiliser une sous-coque est une idée très intelligente! Pour ceux qui se demandent, voici à quoi cela ressemble avec la CLI de 1Password:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti
1
J'aime ça parce que quand j'ai vérifié l'historique de bach, le mot de passe n'était pas exposé en texte clair. Il est également vraisemblable que si l'audit du système est activé, la commande est consignée comme lisant un fichier, par exemple, /dev/fd/63et si le mot de passe est dans un descripteur de fichier temporaire, il n'est pas divulgué.
JPvRiel
5

Si vous êtes à l'aise avec la conservation des mots de passe dans des fichiers en texte brut, une autre option consiste à utiliser un fichier JSON avec le paramètre --extra-vars (assurez-vous d'exclure le fichier du contrôle de code source):

ansible-playbook --extra-vars "@private_vars.json" playbook.yml 

Ansible prend en charge cette option depuis la 1.3 .

sidecarcat
la source
5

vous pouvez écrire le mot de passe sudo pour votre playbook dans le fichier hosts comme ceci:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'
fawadRafiq
la source
5

Un coffre-fort ansible a été suggéré plusieurs fois ici, mais je préfère git-crypt pour crypter des fichiers sensibles dans mes playbooks. Si vous utilisez git pour garder vos playbooks ansible, c'est un jeu d'enfant. Le problème que j'ai trouvé avec le coffre-fort ansible est que je tombe inévitablement sur des copies chiffrées du fichier avec lequel je veux travailler et que je dois le déchiffrer avant de pouvoir travailler. git-cryptoffre un flux de travail plus agréable IMO.

En utilisant cela, vous pouvez mettre vos mots de passe dans une var dans votre playbook, et marquer votre playbook comme un fichier crypté .gitattributescomme ceci:

 my_playbook.yml filter=git-crypt diff=git-crypt

Votre playbook sera crypté de manière transparente sur Github. Ensuite, il vous suffit d'installer votre clé de chiffrement sur l'hôte que vous utilisez pour exécuter ansible ou de suivre les instructions de la documentation pour le configurer gpg.

Il y a un bon Q&A sur les gpgclés de transfert comme vos ssh-agentclés SSH vers l'avant ici: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

user2432419
la source
3

Vous pouvez utiliser l' sshpassutilitaire comme ci-dessous,

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass
Sachin
la source
3

L'utilisation de ansible 2.4.1.0 et des éléments suivants doit fonctionner:

[all]
17.26.131.10
17.26.131.11
17.26.131.12
17.26.131.13
17.26.131.14

[all:vars]
ansible_connection=ssh
ansible_user=per
ansible_ssh_pass=per
ansible_sudo_pass=per

Et lancez simplement le playbook avec cet inventaire comme:

ansible-playbook -i inventory copyTest.yml
Hearen
la source
3

Mon hack pour automatiser cela était d'utiliser une variable d'environnement et d'y accéder via --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Exportez une variable env, mais évitez l'historique bash / shell (ajoutez un espace, ou d'autres méthodes). Par exemple:

     export ANSIBLE_BECOME_PASS='<your password>'

Recherchez la ansible_become_passvariable env en passant la variable supplémentaire dans ansible-playbook, par exemple:

ansible-playbook playbook.yml -i inventories/dev/hosts.yml -u user --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

Bonnes réponses alternatives:

JPvRiel
la source
2

Vous pouvez utiliser le coffre-fort ansible qui votre mot de passe en coffre-fort chiffré. Après cela, vous pouvez utiliser la variable du coffre-fort dans les playbooks.

Quelques documentations sur ansible vault:
http://docs.ansible.com/playbooks_vault.html

Nous l'utilisons comme coffre-fort par environnement. Pour modifier le coffre-fort, nous avons la commande suivante:
ansible-vault edit inventories/production/group_vars/all/vault

Si vous voulez appeler la variable vault, vous devez utiliser ansible-playbook avec des paramètres comme:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Oui, nous stockons le mot de passe du coffre-fort dans le répertoire local en texte brut, mais ce n'est pas plus dangereux comme stocker le mot de passe root pour chaque système. Le mot de passe root se trouve dans le fichier du coffre-fort ou vous pouvez l'avoir comme le fichier sudoers pour votre utilisateur / groupe.

Je recommande d'utiliser le fichier sudoers sur le serveur. Voici un exemple pour l'administrateur de groupe:
%admin ALL=(ALL) NOPASSWD:ALL

maxo
la source
1

Après cinq ans, je constate que c'est toujours un sujet très pertinent. Reflétant quelque peu la réponse de leucos que je trouve la meilleure dans mon cas, en utilisant uniquement des outils ansibles (sans authentification centralisée, jetons ou autre). Cela suppose que vous avez le même nom d'utilisateur et la même clé publique sur tous les serveurs. Si vous ne le faites pas, vous devrez bien sûr être plus précis et ajouter les variables correspondantes à côté des hôtes:

[all:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file=home/user/.ssh/mykey
[group]
192.168.0.50 ansible_sudo_pass='{{ myserver_sudo }}'

ansible-vault create mypasswd.yml
ansible-vault edit mypasswd.yml

Ajouter:

myserver_sudo: mysecretpassword

Ensuite:

ansible-playbook -i inv.ini my_role.yml --ask-vault --extra-vars '@passwd.yml'

Au moins de cette façon, vous n'avez pas à écrire plus de variables qui pointent vers les mots de passe.

Lethargos
la source
1

La solution ci-dessus de @ toast38coza a fonctionné pour moi; juste ce sudo: yes est déconseillé dans Ansible maintenant. Utilisez devenir et become_user à la place.

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root
Nätu
la source
0

nous pouvons également utiliser EXPECT BLOCK en ansible pour générer bash et le personnaliser selon vos besoins

- name: Run expect to INSTALL TA
  shell: |
    set timeout 100
    spawn /bin/sh -i

    expect -re "$ "
    send "sudo yum remove -y xyz\n"

    expect "$ "
    send "sudo yum localinstall -y {{ rpm_remotehost_path_for_xyz }}\n"

    expect "~]$ "
    send "\n"

    exit 0
  args:
  executable: /usr/bin/expect
Ashish Ranjan
la source
0

Très simple, et ajoutez seulement dans le fichier variable:

Exemple:

$ vim group_vars/all

Et ajoutez-les:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
la source
Merci, mais je pense que vous voulez dire ansible_become_pass au lieu de Ansible_become_pass.
Krishnom
0

Juste un addendum, donc personne d'autre ne ressent le désagrément que j'ai fait récemment:

AFAIK, la meilleure solution est celle qui suit les lignes générales de toast38coza ci-dessus. S'il est logique de lier statiquement vos fichiers de mots de passe et votre playbook, suivez son modèle avec vars_files(ou include_vars). Si vous souhaitez les garder séparés, vous pouvez fournir le contenu du coffre-fort sur la ligne de commande comme suit:

ansible-playbook --ask-vault-pass -e@<PATH_TO_VAULT_FILE> <PLAYBOOK_FILE>

C'est évident rétrospectivement, mais voici les pièges:

  1. Ce sanglant signe @ . Si vous le laissez de côté, l'analyse échouera silencieusement et ansible-playbook se déroulera comme si vous n'aviez jamais spécifié le fichier en premier lieu.

  2. Vous devez importer explicitement le contenu du coffre-fort, soit avec une ligne de commande --extra-vars / -e ou dans votre code YAML. L' --ask-vault-passindicateur ne fait rien par lui-même (en plus de vous demander une valeur qui peut ou non être utilisée plus tard).

Puissiez-vous inclure vos "@" et gagner une heure.

Eric Anderson
la source
-3

Cela a fonctionné pour moi ... Fichier créé /etc/sudoers.d/90-init-users avec NOPASSWD

echo "user ALL=(ALL)       NOPASSWD:ALL" > 90-init-users

où "utilisateur" est votre ID utilisateur.

ScottM
la source