1

注:该文作者是 RAPHAEL CAMPARDOU,该文是摘取了 Ansible (Real Life) Good Practices 其中的 Vault Pseudo leaf encryption 来讲的。

Ansible 最佳实践

Vault Pseudo leaf encryption

从 Ansbile 1.5 版本起,Ansible 引入了 Ansible Vault 功能,在 playbook 中加密数据,并在运行时解密的方法。这个特性是高度要求的,在平台管理工具之间给了 Ansible 它的真实位置。

事实是:我们喜欢 Ansible 的可读性,加密的方式使事情,好吧,缺少可读性。

ansible-vault 命令将将加密或解密整个 var 文件,你不能只加密一个变量的值。解决方案非常简单:你可以仅仅为敏感数据创建第二个 var 文件。但是带来了另外一个问题:你的变量会分布在多个文件中,并且它们中的一部分加密。这容易引起混乱。比如,如果你定义一个字典的变量,并且仅仅它们中的一个是敏感的,你不得不加密整个字典。

Leaf encryption 是一个特色要求,但同时,这有一个更简洁优雅的方式解决可读和安全性这两个问题:嵌套变量。

对于每一个敏感变量,你可以创建一个双大括号({{}})前缀的变量在加密文件中。

# var_file
db_password: {{ vaulted_db_passord }}
# and for a dctionnary
aws: 
  - "access_key_id='abcdefgh'"
  - "secret_access_key='{{ vaulted_aws_secret_access_key }}'"
# vault_file
vaulted_db_passord: a_super_secret
vaulted_aws_secret_access_key: the_aws_secret

以这样的方式,你就可以像之前那样操作你所有的变量,知道 vaulted 的版本保持加密。你甚至可以解决由某些人负责加密文件的问题,团队中的其他人绝对不会看到文件的内容,但是仍然可以管理他们需要的 var 文件。

Git Pre-commit Hook for Vault

最后这一条不是直接与 Ansible 相关的,它更多的是工作流的建议。

有两种方式处理 vault 文件:ansible-vault [encrypt|decrypt] 或 用第一种方法 ansible-vault edit,这是一个很好的机会,在某一时刻,解密的版本最终会在一个 Git 提交中,如果可以擦除它的历史,这是一个真正的痛苦。

我写了一个简单的 pre-commit 钩子来检查是否一个文件在提交前调用的 "vault-something" 是加密的。如果不是,它将显示一个帮助信息。

把它复制为 .git/hooks/pre-commit 并使得它可执行(或追加到现有的 pre-commit)。它可以存在于你的 Ansible 工程仓库中或是在你的全局 .git/ 中。

#!/bin/sh
#
# Pre-commit hook that verifies if all files containing 'vault' in the name
# are encrypted.
# If not, commit will fail with an error message
#
# File should be .git/hooks/pre-commit and executable
FILES_PATTERN='.*vault.*\.yml$'
REQUIRED='ANSIBLE_VAULT'

EXIT_STATUS=0
wipe="\033[1m\033[0m"
yellow='\033[1;33m'
# carriage return hack. Leave it on 2 lines.
cr='
'
for f in $(git diff --cached --name-only | grep -E $FILES_PATTERN)
do
  # test for the presence of the required bit.
  MATCH=`head -n1 $f | grep --no-messages $REQUIRED`
  if [ ! $MATCH ] ; then
    # Build the list of unencrypted files if any
    UNENCRYPTED_FILES="$f$cr$UNENCRYPTED_FILES"
    EXIT_STATUS=1
  fi
done
if [ ! $EXIT_STATUS = 0 ] ; then
  echo '# COMMIT REJECTED'
  echo '# Looks like unencrypted ansible-vault files are part of the commit:'
  echo '#'
  while read -r line; do
    if [ -n "$line" ]; then
      echo "#\t${yellow}unencrypted:   $line${wipe}"
    fi
  done <<< "$UNENCRYPTED_FILES"
  echo '#'
  echo "# Please encrypt them with 'ansible-vault encrypt <file>'"
  echo "#   (or force the commit with '--no-verify')."
  exit $EXIT_STATUS
fi
exit $EXIT_STATUS

扩展阅读

First Five (and a Half) Minutes on a Server with Ansible


yexiaobai
4.8k 声望875 粉丝

就是不告诉你 O(∩_∩)O哈哈~。