Я настраиваю сервер 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 из этой ветки:
wrapper-script.sh.j2
echo {{ secret_eg_from_ansible_vault }} | su - "ls -l"
- 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