如何减少某些 Ansible 任务的详细程度以免将密码泄露到系统日志中?

如何减少某些 Ansible 任务的详细程度以免将密码泄露到系统日志中?

有时我想使用 Ansiblelineinfileblockinfile模块将密码写入某个配置文件。如果我这样做,整行或整块(包括密码)都会出现在我的syslog.

由于我不认为syslog是存储密码的安全地方,我该如何告诉 Ansible 不要泄露我的密码syslog?我希望有办法做到这一点,否则我会认为这是 Ansible 中的一个大安全问题。

例如,您可以使用这个临时命令来重现它:

ansible localhost -m blockinfile -a 'dest=/tmp/ansible_password_leak create=yes block="Password = {{password}}"' -e 'password=secret'

最终结果如下syslog

ansible-blockinfile: Invoked with directory_mode=None force=None remote_src=None insertafter=None owner=None follow=False marker=# {mark} ANSIBLE MANAGED BLOCK group=None insertbefore=None create=True setype=None content=None serole=None state=present dest=/tmp/ansible_password_leak selevel=None regexp=None validate=None src=None seuser=None delimiter=None mode=None backup=False block=Password = secret

在本例中,我使用了官方 Ansible Ubuntu PPA在 Debian“Jessie”8 系统上。

答案1

no_log 属性隐藏系统日志中的数据。它可以应用于单个任务

- name: secret task
  shell: /usr/bin/do_something --value={{ secret_value }}
  no_log: True

或剧本:

- hosts: all
  no_log: True

激活后实际上无法进行调试,因此建议仅将其用于单个任务。此功能自 1.5 版起可用Ansible. 正如 1.5 版本的发布公告中所述:

任务现在还可以采用“no_log=True”选项来防止敏感任务进入系统日志。(看起来像密码的参数已被过滤)

大多数情况下应该对密码进行过滤。

答案2

我开发了一个回调插件来隐藏默认输出的密码,它解析包含以下内容的键的输出字典密码,对于每一个,它将值替换为********。

protect_data.py在文件夹中创建一个名为的文件./插件/回调添加此代码:

from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
import os, collections

class CallbackModule(CallbackModule_default):
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'stdout'
    CALLBACK_NAME = 'protect_data'

    def __init__(self, display=None):
        super(CallbackModule, self).__init__(display)

    def hide_password(self, result):
        ret = {}
        for key, value in result.iteritems():
            if isinstance(value, collections.Mapping):
                ret[key] = self.hide_password(value)
            else:
                if "password" in key:
                    ret[key] = "********"
                else:
                    ret[key] = value
        return ret

    def _dump_results(self, result, indent=None, sort_keys=True, keep_invocation=False):
        return super(CallbackModule, self)._dump_results(self.hide_password(result), indent, sort_keys, keep_invocation)

在文件中ansible.cfg

  • 取消注释行stdout_callback并设置此插件名称的值(stdout_callback=protect_data
  • 取消注释行callback_plugins并设置值./plugins/callback

输出仅针对此插件进行修改,如果您使用其他插件来显示输出(logentries,...),则必须对其执行相同的操作

答案3

我想到的解决方法是:

- name: something that would ordinarily log a password
  something.that.requires:
    secret: "{{ a_secret }}"
  no_log: true # avoid logging the secret
  register: the_output_so_we_can_debug_if_it_fails
- name: Log the output of something that would ordinarily log a password with the password redacted
  ansible.builtin.debug:
    msg: "{{ (the_output_so_we_can_debug_if_it_fails ~ '') | replace(a_secret, 'a_secret') }}"

答案4

有人可能会建议使用 Vault 来解决这个问题。

相关内容