使用 Ansible 时,使用在 Hashicorp Vault 中存储的机密信息

首先

使用Ansible设置VM实例等时,经常需要处理用户名称和密码、TLS客户端证书、API密钥等机密信息。我们不希望将机密信息与Ansible Playbook一同进行版本控制,也不愿意在执行Ansible时手动准备。在这种背景下,本文将介绍使用Vault模块将存储在Hashicorp Vault中的机密信息在Ansible中使用的方法。

Vault模块是什么?

Vault 模块是由 Ansible 社区维护的第三方模块,使用它可以在 Ansible 执行时从 Vault 中获取机密信息。

安装方法

使用 ansible-galaxy 命令安装 Vault 模块。

$ ansible-galaxy collection install community.hashi_vault

由于Vault模块依赖于名为hvac的Python库,因此需要同时安装它。

# Ansible が使用する Python インタープリターを特定
$ ansible -m debug -a 'var=ansible_python_interpreter' localhost
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | SUCCESS => {
    "ansible_python_interpreter": "/usr/local/Cellar/ansible/4.0.0/libexec/bin/python3.9"
}

# 使用される Python インタープリターで hvac をインストール
$ /usr/local/Cellar/ansible/4.0.0/libexec/bin/python3.9 -m pip install hvac

使用范例

在官方文件的示例中介绍了一行代码,但我觉得可维护性不好,所以在这里介绍了改进后的代码,考虑到了维护性。下面的示例是使用令牌作为身份验证方式的,所以请注意在执行主机上已完成vault登录(假设认证令牌已缓存在~/.vault-token中由令牌辅助工具处理)的前提下。

- name: read secrets from vault
  set_fact:
    mysql_root_password: >-
      {{ lookup(
        'community.hashi_vault.hashi_vault',
        ' url=' + vault_addr +
        ' ca_cert=' + vault_cacert +
        ' secret=/path/to/mysql-secrets:root-password'
      ) }}
    client_cert: >-
      {{ lookup(
        'community.hashi_vault.hashi_vault',
        ' url=' + vault_addr +
        ' ca_cert=' + vault_cacert +
        ' secret=/path/to/tls-client-secrets:client.pem'
      ) }}
    client_key: >-
      {{ lookup(
        'community.hashi_vault.hashi_vault',
        ' url=' + vault_addr +
        ' ca_cert=' + vault_cacert +
        ' secret=/path/to/tls-client-secrets:client-key.pem'
      ) }}
  vars:
    vault_addr: https://your-vault:8200
    vault_cacert: /path/to/cacert.pem

可以使用从Vault中获取的机密信息如下在上述任务中。

# ファイル内の文字列として使用する場合はテンプレートファイル内で {{ mysql_root_password }} を定義すること
- name: copy configuration file
  template:
    src: templates/server.conf
    dest: /path/to/server.conf

# ファイルとして使用する場合は Copy Module の content パラメーターを使用すること
- name: copy client cert
  copy:
    content: "{{ client_cert }}"
    dest: /path/to/client.pem

- name: copy client key
  copy:
    content: "{{ client_key }}"
    dest: /path/to/client-key.pem

我已经介绍了一个简单的使用示例,但是在官方文档中还介绍了其他各种用例的设定示例,所以我建议您也参考一下官方文档。

填補

在使用 macOS 上的 Vault 模块时,可能会出现以下错误输出。

objc[43838]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[43838]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

这是因为 macOS 引起的问题,正如 ansible/ansible#31869 所报告的那样,所以您需要声明以下环境变量作为解决方法,然后重新运行。

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

最后

这次我们介绍了使用 Vault 模块将保存在 Hashicorp Vault 中的机密信息在 Ansible 中使用的方法。Vault 模块非常方便,希望能为在 Ansible 中处理机密信息方面遇到问题的朋友们提供参考。

bannerAds