web-dev-qa-db-fra.com

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

Je configure un serveur MySQL et souhaite qu'Ansible définisse le mysql-root mot 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_pwd est 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?

22
claus

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

L'utilisateur bcoca de github a souligné que l'on peut utiliser le no_log: true directive 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é.

9
claus

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 Ansible FAQ pour plus de détails. Il peut être appliqué à un playbook entier, mais la sortie devient un peu désagréable avec "censuré!" messages.

31
Bill Carlson

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

3
TheDESTROS

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

Sudo pip install ansible==1.6.1
2
0x3bfc

Selon documents Ansible :

log_path

S'il est présent et configuré dans ansible.cfg, Ansible enregistrera les 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.

Sonne comme le réglage log_path sur votre nœud de contrôle entraînera pas des journaux sur les nœuds de destination.

2
Droopy4096

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 module copy avec le paramètre content peut aider à écrire un petit script wrapper à la volée.

1
Christian Kaiser

Le no_log: true L'approche 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 exposé, dans result mais 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 123456 comme mot de passe bancaire.

1
sorin

L'argument environnement du playbook est approprié pour garder un secret caché. Le secret n'est pas imprimé même avec -vvvv. Il est disponible pour toute la pièce.

- hosts: control_Host
  gather_facts: no
  become: no
  environment:
    PASSWORD: "{{ password }}"
  tasks:

   - local_action: "Shell ./foobar.sh ${PASSWORD}"

   - local_action: "Shell echo ${PASSWORD}"

production:

ansible-playbook -i ... playbooks/demo.yml -v

PLAY [control_Host] *********************************************************************************

TASK [Shell] *********************************************************************************
changed: [localhost -> localhost] => {
    "changed": true,
    "cmd": "./foobar.sh ${PASSWORD}",
    "delta": "0:00:00.013467",
    "end": "2020-04-03 17:42:03.950534",
    "rc": 0,
    "start": "2020-04-03 17:42:03.937067"
}

TASK [Shell] *********************************************************************************
changed: [localhost -> localhost] => {
    "changed": true,
    "cmd": "echo ${PASSWORD}",
    "delta": "0:00:00.005925",
    "end": "2020-04-03 17:42:04.319085",
    "rc": 0,
    "start": "2020-04-03 17:42:04.313160"
}

STDOUT:

my_secret_password
0
selle