Comment puis-je empêcher ansible d'écrire des mots de passe dans les fichiers journaux?

22

Je configure un serveur MySQL et souhaite qu'Ansible définisse le mysql-rootmot de passe lors de l'installation.

Avec l'aide d'Internet, j'ai trouvé cette solution:

- name: Set MySQL root password before installing
  debconf: name='mysql-server' question='mysql-server/root_password' value='{{mysql_root_pwd | quote}}' vtype='password'
- name: Confirm MySQL root password before installing
  debconf: name='mysql-server' question='mysql-server/root_password_again' value='{{mysql_root_pwd | quote}}' vtype='password'
- name: Install Mysql
  apt: pkg=mysql-server state=latest

mysql_root_pwdest une variable chargée à partir du coffre-fort Ansible. Cela fonctionne bien, mais maintenant sur le serveur il y a beaucoup de lignes dans le journal:

Apr 10 14:39:59 servername ansible-debconf: Invoked with value=THEPASSWORD vtype=password question=mysql-server/root_password name=mysql-server unseen=None
Apr 10 14:39:59 servername ansible-debconf: Invoked with value=THEPASSWORD vtype=password question=mysql-server/root_password_again name=mysql-server unseen=None

Comment puis-je empêcher Ansible d'écrire des mots de passe en texte clair dans les fichiers journaux?

claus
la source

Réponses:

28

Pour empêcher une tâche contenant des informations confidentielles d'être journalisée, dans syslog ou autre, définissez no_log: true sur la tâche:

- name: secret stuff
  command: "echo {{secret_root_password}} | sudo su -"
  no_log: true

L'exécution de la tâche sera toujours enregistrée, mais avec peu de détails. De plus, le module utilisé doit prendre en charge no_log, alors testez les modules personnalisés.

Voir la FAQ Ansible pour plus de détails. Il peut être appliqué à un playbook entier, mais la sortie devient un peu désagréable avec "censuré!" messages.

Bill Carlson
la source
2
C'est entre autres ce que dit cette réponse serverfault.com/a/682823/9517
user9517 prend en charge GoFundMonica
9

Le comportement observé semble être un bogue dans le module debconf. J'ai déposé un rapport de bug .

L'utilisateur bcoca de github a souligné que l'on peut utiliser la no_log: truedirective dans les tâches, qui définissent les mots de passe, pour empêcher la journalisation. Ceci est une solution de contournement, qui fonctionne pour moi jusqu'à ce que le bug soit corrigé.

claus
la source
Je reçois une erreur lorsque j'utilise cette directive. Une idée de ce que je fais mal? ERROR: no_log is not a legal parameter in an Ansible task or handler
Bouke Versteegh
2
Il s'avère que j'avais une ancienne version d'ansible! Pour fixer (sur ubuntu): sudo apt-add-repository ppa:ansible/ansible, sudo apt-get update,sudo apt-get install ansible
Bouke Versteegh
Même problème pour moi mais je ne peux pas faire n_log: true pour fonctionner comme prévu. Ma version Ansible est 1.7.2. Qu'est-ce qui est à toi ?
jmcollin92
@ jmcollin92 J'utilise actuellement 2.1. Il y a un guide ici sur la façon d'installer la dernière version à partir de la source. Je l'utilise car ansible mûrit toujours.
claus
2

J'ai résolu en mettant à niveau la version Ansible vers 1.6.1

sudo pip install ansible==1.6.1
0x3bfc
la source
2

Selon les documents Ansible :

log_path

S'il est présent et configuré dans ansible.cfg, Ansible enregistrera des informations sur les exécutions à l'emplacement désigné. Assurez-vous que l'utilisateur exécutant Ansible dispose d'autorisations sur le fichier journal:

log_path=/var/log/ansible.log 

Ce comportement n'est pas activé par défaut. Notez qu'ansible enregistrera, sans ce paramètre, les arguments du module appelés dans le syslog des machines gérées. Les arguments de mot de passe sont exclus.

Cela ressemble à un réglage log_pathsur votre nœud de contrôle, car il n'aura pas de journaux sur les nœuds de destination.

Droopy4096
la source
En fait, j'ai un ansible.cfg dans mon répertoire local, où j'appelle ansible, définissant le log_path. Le journal local est bien créé et mis à jour après une nouvelle exécution (la journalisation fonctionne). Cela n'empêche pas (même si le document que vous avez indiqué le promet) d'empêcher l'hôte distant de se connecter. De plus, l'énoncé "Les arguments de mot de passe sont exclus" ne semble pas être vrai à 100%? Est-ce un bug (voire deux)?
claus
2
@claus "arguments de mot de passe exclus" s'applique uniquement aux modules où l'argument de mot de passe est explicite. Il n'y a aucun moyen pour ansible de savoir quel argument serait un mot de passe et lequel ne le serait pas avec des commandes générales comme debconf, shell, raw, etc.
Droopy4096
Veuillez faire défiler vers la droite dans mon livre de jeu initial. Ça dit vtype='password'. Cela devrait être assez explicite à mon humble avis? Je suppose que le message de journal est également créé par le module debconf.
claus
Ceci est une erreur. La documentation devrait indiquer plus précisément «Notez qu'ansible, quel que soit ce paramètre , enregistrera les arguments du module appelés dans le syslog des machines gérées».
augurar
2

Il y a un meilleur moyen que juste no_log: True

- name: write in string variables login and password
  set_fact:
    temp_user: "{{ USER_VAR }}"
    temp_pass: "{{ PASSWORD_VAR }}"


- name: Your operation with password in output
  shell: '/opt/hello.sh'
  ignore_errors: True
  no_log: True
  register: myregister

- debug:
    msg: '{{ myregister.stderr | regex_replace(temp_user) | regex_replace(temp_pass) }}'
  when: myregister.stderr != ""

- debug:
    msg: '{{ myregister.stdout | regex_replace(temp_user) | regex_replace(temp_pass) }}'
  when: myregister.stdout != ""

- fail:
    msg: "error shell /opt/hello.sh"
  when: myregister.stderr != ""

Comme vous pouvez le voir, vous devez ajouter:

ignore_errors: true
no_log: true

Et puis faites la sortie du résultat de la commande avec regex_replace, où:

USER_VAR - variable de connexion

PASSWORD_VAR - variable de mot de passe

Avec cette approche, vous masquerez non seulement les mots de passe et les connexions, mais obtiendrez également le résultat de votre opération

TheDESTROS
la source
1

Ceci est un complément à la réponse de TheDESTROS de ce fil:

  1. écrire un modèle, qui enveloppe la commande avec un secret:

wrapper-script.sh.j2

echo {{ secret_eg_from_ansible_vault }} | su - "ls -l"
  1. Appelez le script wrapper et supprimez-le immédiatement:
- name: create template
  template:
    src: wrapper-script.sh.j2
    dest: /tmp/wrapper-script.sh
    mode: 0700
  no_log: True
- name: invoke command with secret and remove it
  shell: /tmp/wrapper-script.sh; rm -f /tmp/wrapper-script.sh

Vous avez besoin d'un peu moins de code et vous pouvez ignorer les commandes de vos journaux. Il n'y a qu'une seule caveeat, si un secret est dans les commandes stdout. Si vous voulez éviter le modèle externe, le copymodule avec le paramètre contentpeut aider à écrire un petit script wrapper à la volée.

Christian Kaiser
la source
1

L' no_log: trueapproche doit être utilisée en dernier recours si d'autres tentatives échouent car cela rendra l'exécution de la tâche totalement opaque et vous n'aurez aucune idée de l'échec.

Les pratiques de sécurité recommandent de donner des informations d'identification à partir de stdin ou lorsque cela n'est pas possible en utilisant des fichiers d'informations d'identification (ou même des exécutables).

Voici un exemple sur la façon d'effectuer une connexion podman sécurisée en évitant d'exposer le mot de passe:

- name: secured login
  become: true
  command: >
    podman login --username={{ user }} --password-stdin ...
  args:
    stdin: "{{ secret }}"
  register: result

Avec cela, le secret ne sera pas dévoilé, resultmais vous pourrez toujours voir la sortie de la commande.

La plupart des outils nécessitant une connexion mettent en œuvre l'une des approches les plus sécurisées mentionnées. L'utilisation des informations d'identification sur CLI dans le code est comme avoir 123456comme mot de passe bancaire.

Sorin
la source