Назад | Перейти на главную страницу

Как я могу запретить Ansible записывать пароли в лог-файлы?

Я настраиваю сервер MySQL и хочу, чтобы Ansible установил mysql-root пароль при установке.

С помощью Интернета я придумал следующее решение:

- 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 - это переменная, загруженная из Ansible Vault. Это работает нормально, но теперь на сервере в журнале много строк:

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

Как я могу запретить Ansible записывать пароли в виде открытого текста в файлы журналов?

Чтобы предотвратить регистрацию задачи с конфиденциальной информацией в системном журнале или другом, установите no_log: true для задачи:

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

Выполнение задачи по-прежнему будет регистрироваться, но с небольшими подробностями. Кроме того, используемый модуль должен поддерживать no_log, поэтому тестируйте собственные модули.

Видеть Ansible FAQ для получения дополнительной информации. Его можно применить ко всему плейбуку, однако вывод становится немного неприятным с "censored!" Сообщения.

Наблюдаемое поведение кажется ошибкой в ​​модуле debconf. Я подал отчет об ошибке.

Пользователь bcoca на github указал, что можно использовать no_log: true директива в задачах, устанавливающих пароли, для предотвращения входа в систему. Это обходной путь, который работает у меня, пока ошибка не будет исправлена.

Есть способ лучше, чем просто 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 != ""

Как видите, нужно добавить:

ignore_errors: true
no_log: true

А затем сделайте вывод результата команды с regex_replace, где:

USER_VAR - переменная логина

PASSWORD_VAR - пароль переменной

При таком подходе вы не только скроете пароли и логины, но и получите результат своей операции.

Решил обновлением версии Ansible до 1.6.1

sudo pip install ansible==1.6.1

Согласно Ansible docs:

log_path

Если присутствует и настроено в ansible.cfg, Ansible будет регистрировать информацию о казнях в указанном месте. Убедитесь, что у пользователя, запускающего Ansible, есть разрешения на файл журнала:

log_path=/var/log/ansible.log 

Это поведение не включено по умолчанию. Обратите внимание, что без этого параметра ansible будет записывать вызываемые аргументы модуля в системный журнал управляемых машин. Аргументы пароля исключены.

Похоже на настройку log_path на вашем контрольном узле приведет к не наличие журналов на узлах назначения.

Это дополнение к ответу TheDESTROS из этой ветки:

  1. напишите шаблон, который обертывает команду секретом:

wrapper-script.sh.j2

echo {{ secret_eg_from_ansible_vault }} | su - "ls -l"
  1. Вызвать сценарий оболочки и сразу удалить его:
- 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

Вам нужно немного меньше кода и вы можете выводить команды в свои журналы. Есть только один нюанс, если секрет находится в командах stdout. Если вы хотите избежать использования внешнего шаблона, copy модуль с параметром content может помочь написать небольшой сценарий-оболочку на лету.

В no_log: true подход следует использовать в качестве последнего средства, если другие попытки не удастся, потому что он сделает выполнение задачи полностью непрозрачным, и вы не будете знать, когда он потерпит неудачу.

Практики безопасности рекомендуют вводить учетные данные из стандартного ввода или, когда это невозможно, использовать файлы учетных данных (или даже исполняемые файлы).

Вот пример того, как выполнить безопасный вход в систему podman, не раскрывая пароль:

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

При этом секрет не будет раскрыт, в result но вы все равно сможете увидеть вывод команды.

Большинство инструментов, требующих входа в систему, реализуют один из упомянутых более безопасных подходов. Использование учетных данных в CLI в коде похоже на 123456 в качестве пароля вашего банка.

В Окружающая среда Аргумент в сборнике пьес подходит для того, чтобы скрыть секрет. Секрет не печатается даже с -vvvv. Он доступен для всего спектакля.

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

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

   - local_action: "shell echo ${PASSWORD}"

вывод:

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