前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在Ubuntu 16.04上使用Vault来保护敏感的Ansible数据

如何在Ubuntu 16.04上使用Vault来保护敏感的Ansible数据

原创
作者头像
所有的酒都不如你
修改2018-08-10 17:41:48
2.1K0
修改2018-08-10 17:41:48
举报
文章被收录于专栏:云计算教程系列

介绍

Ansible Vault是一项允许用户加密Ansible项目中的值和数据结构的功能。这提供了保证Ansible成功运行敏感数据所必备的能力。

在本教程中,我们将演示如何使用Ansible Vault,并开发一些推荐操作以简化其使用。我们将使用Ubuntu 16.04服务器作为Ansible控制机器。不需要远程主机。

准备

您将需要一个具有sudo权限的非root用户的Ubuntu 16.04服务器。在服务器上,您需要安装和配置Ansible

什么是Ansible Vault?

Vault是一种允许将加密内容透明地并入Ansible工作流程的机制。所谓的ansible-vault的实用程序通过在磁盘上加密来保护机密数据。为了将这些密钥与常规的Ansible数据整理在一起,ansibleansible-playbook命令分别用于执行adhoc任务和结构化playbook的命令,都支持在运行时解密加密vault的内容。

Vault是以文件级粒度实现,这意味着文件是完全加密或未加密的。它使用AES256算法提供与用户提供的密码相符合的加密。这意味着使用相同的密码才能加密和解密内容,这从可用性的角度来看是有用的。Ansible能够识别和解密在执行文本或任务时找到的任何加密文件。

在撰写本文时,用户只能将一个密码传递给Ansible。这意味着所涉及的每个加密文件都必须共享密码。

了解Vault的内容,我们就可以开始讨论Ansible提供的工具以及如何将Vault与现有工作流程结合使用。

设置Ansible Vault编辑器

在使用ansible-vault命令之前,最好指定首选的文本编辑器。Vault的一些命令会涉及打开编辑器来操作加密文件的内容。Ansible会查看EDITOR环境变量以查找首选编辑器。如果未设置,则默认为vi

如果您不想使用vi进行编辑,则应在EDITOR环境中设置变量。

注意:如果您发现自己在vi会话中发生异常,可以通过按Esc键,键入:q!,然后按Enter键退出。如果您不熟悉vi编辑器,则您所做的任何更改都可能是无意的,因此该命令会在不保存的情况下退出。

要为单个命令设置编辑器,请在命令前加上环境变量赋值,如下所示:

代码语言:txt
复制
$ EDITOR=nano ansible-vault . . .

要使其持久化,请打开您的~/.bashrc文件:

代码语言:txt
复制
$ nano ~/.bashrc

通过在文件末尾添加EDITOR分配来指定首选编辑器:

~/.bashrc

代码语言:txt
复制
~/.bashrc
export EDITOR=nano

完成后保存并关闭文件。

再次获取文件以读取当前会话的更改:

代码语言:txt
复制
$ . ~/.bashrc

显示EDITOR变量以检查您的设置是否已应用:

代码语言:txt
复制
$ echo $EDITOR
代码语言:txt
复制
nano

现在您已经建立了首选编辑器,我们可以使用ansible-vault命令讨论操作。

如何使用ansible-vault管理敏感文件

ansible-vault命令是用于管理Ansible中的加密内容的主界面。此命令用于初始加密文件,随后用于查看,编辑或解密数据。

创建新的加密文件

要创建使用Vault加密的新文件,请使用ansible-vault create命令。传入您要创建的文件的名称。例如,要创建一个名为vault.yml存储敏感变量的加密YAML文件,可以键入:

代码语言:txt
复制
$ ansible-vault create vault.yml

系统将提示您输入并确认密码:

代码语言:txt
复制
New Vault password: 
Confirm New Vault password:

确认密码后,Ansible将立即打开一个编辑窗口,您可以在其中输入所需的内容。

要测试加密功能,请输入一些测试文本:

vault.yml

代码语言:txt
复制
Secret information

Ansible将在您关闭文件时加密内容。如果您检查文件,您不会看到键入的单词,而是看到一个加密的块:

代码语言:txt
复制
$ cat vault.yml
代码语言:txt
复制
$ANSIBLE_VAULT;1.1;AES256
65316332393532313030636134643235316439336133363531303838376235376635373430336333
3963353630373161356638376361646338353763363434360a363138376163666265336433633664
30336233323664306434626363643731626536643833336638356661396364313666366231616261
3764656365313263620a383666383233626665376364323062393462373266663066366536306163
31643731343666353761633563633634326139396230313734333034653238303166

我们可以看到Ansible用来知道如何处理文件的一些头信息,然后是加密内容,显示为数字。

加密现有文件

如果您已经拥有要使用Vault加密的文件,请改用ansible-vault encrypt命令。

为了测试,我们可以通过输入以下内容来创建示例文件

代码语言:txt
复制
$   echo 'unencrypted stuff' > encrypt_me.txt

现在,您可以通过键入以下内容来加密现有文件:

代码语言:txt
复制
$  ansible-vault encrypt encrypt_me.txt

同样,系统将提示您提供并确认密码。之后,一条消息将确认加密:

代码语言:txt
复制
New Vault password: 
Confirm New Vault password:
Encryption successful

而不是打开编辑窗口,ansible-vault将加密文件的内容并将其写回磁盘,替换未加密的版本。

如果我们检查文件,我们应该看到类似的加密模式:

代码语言:txt
复制
$  cat encrypt_me.txt
代码语言:txt
复制
$ANSIBLE_VAULT;1.1;AES256
66633936653834616130346436353865303665396430383430353366616263323161393639393136
3737316539353434666438373035653132383434303338640a396635313062386464306132313834
34313336313338623537333332356231386438666565616537616538653465333431306638643961
3636663633363562320a613661313966376361396336383864656632376134353039663662666437
39393639343966363565636161316339643033393132626639303332373339376664

如您所见,Ansible加密现有内容的方式与加密新文件的方式大致相同。

查看加密文件

有时侯,您可能需要引用文件库加密文件的内容,而无需编辑它或将其写入未加密的文件系统。则输入ansible-vault view命令将文件的内容提供给标准输出。默认情况下,这意味着内容显示在终端中。

将vault加密文件传递给命令:

代码语言:txt
复制
$   ansible-vault view vault.yml

系统将要求您输入文件密码。成功输入后,将显示以下内容:

代码语言:txt
复制
Vault password:
Secret information

如您所见,密码提示混合到文件内容的输出中。ansible-vault view在自动化过程中使用时会记住这一点。

编辑加密文件

需要编辑加密文件时,请使用以下ansible-vault edit命令:

代码语言:txt
复制
$ ansible-vault edit vault.yml

系统将提示您输入文件密码。输入后,Ansible将打开文件编辑窗口,您可以在其中进行任何必要的更改。

保存后,新内容将再次使用文件的加密密码加密并写入磁盘。

手动解密加密文件

要解密文件库加密文件,请使用ansible-vault decrypt命令。

注意:由于意外将敏感数据提交到项目存储库的可能性增加,因此ansible-vault decrypt是仅在您希望永久删除文件中的加密时才建议使用的命令。如果您需要查看或编辑保险库加密文件,通常最好分别使用ansible-vault viewansible-vault edit命令。

传入加密文件的名称:

代码语言:txt
复制
$   ansible-vault decrypt vault.yml

系统将提示您输入该文件的加密密码。输入正确的密码后,文件将被解密:

代码语言:txt
复制
Vault password:
Decryption successful

如果再次查看文件,不是看到文件库加密,而是应该看到文件的实际内容:

代码语言:txt
复制
$   cat vault.yml
代码语言:txt
复制
Secret information

您的文件现在在磁盘上未加密。完成后,请务必删除所有敏感信息或重新加密文件。

更改加密文件的密码

如果需要更改加密文件的密码,请使用以下ansible-vault rekey命令:

代码语言:txt
复制
$   ansible-vault rekey encrypt_me.txt

输入命令后,系统将首先提示您输入文件的当前密码:

代码语言:txt
复制
Vault password:

输入后,系统会要求您选择并确认新的保管库密码:

代码语言:txt
复制
Vault password:
New Vault password:
Confirm New Vault password:

成功确认新密码后,您将收到一条消息,指示重新加密过程成功:

代码语言:txt
复制
Rekey successful

现在可以使用新密码访问该文件。旧密码将不再有效。

使用Vault加密文件运行Ansible

使用Vault加密敏感信息后,您可以开始使用Ansible传统工具的文件。在命令密码正确的情况下,ansibleansible-playbook命令都知道如何解密受保护文件的文件。根据您的需要,有几种不同的方法可以为这些命令提供密码。

您需要一个保险库加密的文件。您可以输入以下内容创建一个:

代码语言:txt
复制
$   ansible-vault create secret_key

选择并确认密码。填写您想要的任何内容:

secret_key

代码语言:txt
复制
confidential data

保存并关闭文件。

我们还可以创建一个临时hosts文件作为库存:

代码语言:txt
复制
$   nano hosts

我们将只添加Ansible localhost。为了准备以后的步骤,我们将把它放在[database]组中:

hosts

代码语言:txt
复制
[database]
localhost ansible_connection=local

完成后保存并关闭文件。

接下来,ansible.cfg如果尚不存在,则在当前目录中创建一个文件:

代码语言:txt
复制
$ nano ansible.cfg

现在,只需添加一个[defaults]部分并将Ansible指向我们刚刚创建的库存:

ansible.cfg

代码语言:txt
复制
[defaults]
inventory = ./hosts

准备好后,继续。

使用交互式提示

在运行解密内容的最直接方法是让Ansible提示您输入相应的凭据。您可以通过添加--ask-vault-pass到任何一个ansibleansible-playbook命令来完成此操作。Ansible将提示您输入密码,该密码将用于尝试解密其找到的任何受保管库保护的内容。

例如,如果我们需要将vault加密文件的内容复制到主机,我们可以使用copy模块和--ask-vault-pass标志。如果文件实际上包含敏感数据,您很可能在具有权限和所有权限制的情况下锁定远程主机上的访问权限。

注意:我们localhost在此示例中用作目标主机以最小化所需的服务器数量,但结果应与主机真正远程时的结果相同:

代码语言:txt
复制
$ ansible --ask-vault-pass -bK -m copy -a 'src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root' localhost

我们的任务指定应将文件的所有权更改为root,因此需要管理权限。-bK标志告诉Ansible提示输入目标主机的sudo密码,因此系统会要求您输入sudo密码。然后,系统会要求您输入Vault 密码:

代码语言:txt
复制
SUDO password:
Vault password:

提供密码后,Ansible将尝试使用Vault密码对其找到的任何加密文件执行任务。请记住,执行期间引用的所有文件都必须使用相同的密码:

代码语言:txt
复制
localhost | SUCCESS => {
    "changed": true, 
    "checksum": "7a2eb5528c44877da9b0250710cba321bc6dac2d", 
    "dest": "/tmp/secret_key", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "270ac7da333dd1db7d5f7d8307bd6b41", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/home/sammy/.ansible/tmp/ansible-tmp-1480978964.81-196645606972905/source", 
    "state": "file", 
    "uid": 0
}

提示输入密码是安全的,但可能很繁琐,特别是在重复运行时,也会妨碍自动化。好在这些情况有一些替代方案。

使用Ansible Vault和密码文件

如果您不希望每次执行任务时都输入Vault密码,则可以将Vault密码添加到文件中,并在执行期间引用该文件。

例如,您可以将密码放在如下.vault_pass文件中:

代码语言:txt
复制
$ echo 'my_vault_password' > .vault_pass

如果您使用的是版本控制,请确保将密码文件添加到版本控制软件的忽略文件中,以避免意外提交:

代码语言:txt
复制
$ echo '.vault_pass' >> .gitignore

现在,您可以改为引用该文件。--vault-password-file标志位于命令行中。我们可以通过输入以下内容完成上一节中的相同任务:

代码语言:txt
复制
$ ansible --vault-password-file=.vault_pass -bK -m copy -a 'src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root' localhost

这次就不会提示您输入Vault密码了。

自动读取密码文件

为了避免一直提供指令,您可以设置ANSIBLE_VAULT_PASSWORD_FILE路径环境变量以使用密码文件:

代码语言:txt
复制
$  export ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass

您现在应该能够执行没有--vault-password-file指令的命令:

代码语言:txt
复制
$ ansible -bK -m copy -a 'src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root' localhost

要使Ansible知道跨会话的密码文件位置,您可以编辑ansible.cfg文件。

打开我们之前创建的本地文件ansible.cfg

代码语言:txt
复制
$   nano ansible.cfg

[defaults]部分中,设置vault_password_file,指向密码文件的位置。这可以是相对路径或绝对路径,具体取决于哪个最适合您:

ansible.cfg

代码语言:txt
复制
[defaults]
. . .
vault_password_file = ./.vault_pass

现在,当您运行需要解密的命令时,将不再提示您输入保管库密码。ansible-vault不仅会使用文件中的密码来解密任何文件,而且在使用ansible-vault create和创建新文件时也会应用密码ansible-vault encrypt

从环境变量中读取密码

您可能担心不小心将密码文件上传到存储库。不幸的是,虽然Ansible有一个环境变量指向密码文件的位置,但它没有一个用于设置密码。

但是,如果您的密码文件是可执行文件,Ansible将把它作为脚本运行并使用生成的输出作为密码。在GitHub问题中,Brian Schwind建议使用以下脚本从环境变量中提取密码。

在编辑器中打开文件.vault_pass

代码语言:txt
复制
$  nano .vault_pass

使用以下脚本替换内容:

.vault_pass

代码语言:txt
复制
#!/usr/bin/env python

import os
print os.environ['VAULT_PASSWORD']

输入以下命令使文件可执行:

代码语言:txt
复制
$ chmod +x .vault_pass

然后,您可以设置并导出环境变量VAULT_PASSWORD,该变量可用于您当前的会话:

代码语言:txt
复制
export VAULT_PASSWORD=my_vault_password

您必须在每个Ansible会话开始时执行此操作,也许不太方便。但是,这有效地防止您意外提交Vault加密密码。

使用带有常规变量的Vault加密变量

虽然Ansible Vault可以与任意文件一起使用,但它最常用于保护敏感变量。我们将通过一个示例向您展示如何将常规变量文件转换为平衡安全性和可用性的配置。

设置示例

假设您正在配置数据库服务器。在您之前创建文件hosts时,将条目localhost放在一个名为database的准备步骤组中。

数据库通常需要混合使用敏感和非敏感变量。这些可以在以组group_vars命名的文件中的目录中分配:

代码语言:txt
复制
$ mkdir -p group_vars
$ nano group_vars/database

group_vars/database文件内部,设置一些变量。如端口号MySQL,不是秘密的,可以自由共享。其他变量(如数据库密码)将保密:

group_vars/database

代码语言:txt
复制
---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

# sensitive data
mysql_password: supersecretpassword

我们可以使用Ansible的debug模块和hostvars变量来测试所有变量是否可用于我们的主机:

代码语言:txt
复制
$   ansible -m debug -a 'var=hostvars[inventory_hostname]' database
代码语言:txt
复制
localhost | SUCCESS => {
    "hostvars[inventory_hostname]": {
        "ansible_check_mode": false, 
        "ansible_version": {
            "full": "2.2.0.0", 
            "major": 2, 
            "minor": 2, 
            "revision": 0, 
            "string": "2.2.0.0"
        }, 
        "group_names": [
            "database"
        ], 
        "groups": {
            "all": [
                "localhost"
            ], 
            "database": [
                "localhost"
            ], 
            "ungrouped": []
        }, 
        "inventory_dir": "/home/sammy", 
        "inventory_file": "hosts", 
        "inventory_hostname": "localhost", 
        "inventory_hostname_short": "localhost", 
        "mysql_host": "10.0.0.3",
        "mysql_password": "supersecretpassword",
        "mysql_port": 3306,
        "mysql_user": "fred",
        "omit": "__omit_place_holder__1c934a5a224ca1d235ff05eb9bda22044a6fb400", 
        "playbook_dir": "."
    }
}

输出确认我们设置的所有变量都应用于主机。但是,我们的group_vars/database文件目前包含所有变量。这意味着我们可以保留未加密变量。但是由于数据库密码变更,就有一个安全的问题。如果我们加密所有变量,这会产生可用性和协作问题。

将敏感变量移动到Ansible Vault中

要解决这个问题,我们需要区分敏感和非敏感变量。我们应该能够加密机密值,同时轻松分享我们的非敏感变量。为此,我们将在两个文件之间拆分变量。

可以使用变量目录代替Ansible变量文件,以便从多个文件应用变量。我们可以重构以利用这种能力。首先,将现有文件重命名database为vars。这将是我们未加密的变量文件:

代码语言:txt
复制
$  mv group_vars/database group_vars/vars

接下来,创建一个与旧变量文件同名的目录。将vars文件移到里面:

代码语言:txt
复制
$ mkdir group_vars/database
$ mv group_vars/vars group_vars/database/

我们现在有一个database组的变量目录而不是单个文件,我们有一个未加密的变量文件。由于我们将加密敏感变量,因此我们应该从未加密的文件中删除它们。编辑group_vars/database/vars文件以删除机密数据:

代码语言:txt
复制
$  nano group_vars/database/vars

在这种情况下,我们想要删除mysql_password变量。该文件现在应如下所示:

group_vars/database/vars

代码语言:txt
复制
---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

接下来,在与未加密vars文件并存的目录中创建一个保险库加密文件:

代码语言:txt
复制
$   ansible-vault create group_vars/database/vault

在此文件中,定义以前在vars文件中的敏感变量。使用相同的变量名称,但前置字符串vault_以指示这些变量是在受保管库保护的文件中定义的:

group_vars/database/vault

代码语言:txt
复制
---
vault_mysql_password: supersecretpassword

完成后保存并关闭文件。

生成的目录结构如下所示:

代码语言:txt
复制
.
├── . . .
├── group_vars/
│   └── database/
│       ├── vars
│       └── vault
└── . . .

此时,变量是分开的,只有机密数据被加密。这是安全的,但我们的操作已经影响了我们的可用性。虽然我们的目标是保护敏感,但我们也无意中降低了对实际变量名称的可见性。目前尚不清楚在没有引用多个文件的情况下分配了哪些变量,虽然您可能希望在协作时限制对机密数据的访问,但您仍可能希望共享变量名称。

为解决这个问题,Ansible项目通常建议采用略有不同的方法。

从未加密变量引用Vault变量

当我们将敏感数据移动到受保护库保护的文件时,我们使用开始变量名称vault_。我们可以将原始变量名称(mysql_password)添加回未加密的文件中。我们可以使用Jinja2模板语句从未加密的变量文件中引用加密的变量名,而不是直接将它们设置为敏感值。这样,您就可以通过引用单个文件来查看所有已定义的变量,但机密值仍保留在加密文件中。

要演示,请再次打开未加密的变量文件:

代码语言:txt
复制
$  nano group_vars/database/vars

再次添加变量mysql_password。这次,使用Jinja2模板来引用受保管库文件中定义的变量:

group_vars/database/vars

代码语言:txt
复制
---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

# sensitive data
mysql_password: "{{ vault_mysql_password }}"

变量mysql_password将被设置为vault_mysql_password的值可变,这是在保管库文件中定义。

使用此方法,您可以database通过查看group_vars/database/vars文件了解将应用于组中主机的所有变量。Jinja2模板会遮挡敏感部分。在group_vars/database/vault仅在需要被查看时更改自己的值。

您可以检查以确保变量mysql_*仍使用与上次相同的正确方法应用。

注意:如果未使用密码文件自动应用Vault密码,请将--ask-vault-pass指令添加到下面的命令中。

代码语言:txt
复制
$ ansible -m debug -a 'var=hostvars[inventory_hostname]' database
代码语言:txt
复制
localhost | SUCCESS => {
    "hostvars[inventory_hostname]": {
        "ansible_check_mode": false, 
        "ansible_version": {
            "full": "2.2.0.0", 
            "major": 2, 
            "minor": 2, 
            "revision": 0, 
            "string": "2.2.0.0"
        }, 
        "group_names": [
            "database"
        ], 
        "groups": {
            "all": [
                "localhost"
            ], 
            "database": [
                "localhost"
            ], 
            "ungrouped": []
        }, 
        "inventory_dir": "/home/sammy/vault", 
        "inventory_file": "./hosts", 
        "inventory_hostname": "localhost", 
        "inventory_hostname_short": "localhost", 
        "mysql_host": "10.0.0.3",
        "mysql_password": "supersecretpassword",
        "mysql_port": 3306,
        "mysql_user": "fred",
        "omit": "__omit_place_holder__6dd15dda7eddafe98b6226226c7298934f666fc8", 
        "playbook_dir": ".", 
        "vault_mysql_password": "supersecretpassword"
    }
}

无论是vault_mysql_passwordmysql_password都可访问。

结论

在教程中,我们演示了Ansible Vault如何加密信息,以便您可以将所有配置数据保存在一个位置而不会影响安全性。


参考文献:《How To Use Vault to Protect Sensitive Ansible Data on Ubuntu 16.04》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 准备
  • 什么是Ansible Vault?
  • 设置Ansible Vault编辑器
  • 如何使用ansible-vault管理敏感文件
    • 创建新的加密文件
      • 加密现有文件
        • 查看加密文件
          • 编辑加密文件
            • 手动解密加密文件
              • 更改加密文件的密码
              • 使用Vault加密文件运行Ansible
                • 使用交互式提示
                  • 使用Ansible Vault和密码文件
                    • 自动读取密码文件
                      • 从环境变量中读取密码
                      • 使用带有常规变量的Vault加密变量
                        • 设置示例
                          • 将敏感变量移动到Ansible Vault中
                            • 从未加密变量引用Vault变量
                            • 结论
                            相关产品与服务
                            云数据库 MySQL
                            腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档