一、背景:Ansible助力ToB私有化业务统一管理
ToB产品交付部署方式,主要分为三种:公有云部署、私有云部署和混合云部署。
其中,小微企业较为关注软硬件资源及后期运维成本,大多采用公有云部署。而大中型企业或金融、政府等行业出于数据隐私和等保合规因素的考虑,较多的采用私有云和混合云部署。
ToB产品在公有云(如腾讯云、阿里云、华为云等)部署的场景,配套有完善的分布存储、构建发布、监控告警、自动化运维平台,并且采用云租户的方式,有专业团队负责管理。而在混合云或私有云部署的场景,不同企业的软硬件资源和运维团队能力差异较大,针对这种场景,就急需一款简单而又专业的管理工具针对ToB产品的服务器进行统一管理。
针对批量资源管理问题,业界有不少开源软件(如Ansible、Salt Stack、Puppet),国内不少企业也开发了相应的商业化软件(如腾讯蓝鲸、行云管家)。商业化软件一方面会给企业带来额外的购买成本,另一方面复杂的商业化软件又徒增了ToB产品自身之外的交付运维负担,所以相对简单易用的开源软件就成了ToB产品服务器管理的首选。
Ansible是Red Hat旗下的一款开源自动化运维工具,基于Python开发,支持Linux和Windows服务器,可以实现服务器的批量运维管理。本文针对的是Ansible使用中的敏感信息保护问题展开介绍。
二、问题:运维平台存在敏感信息泄露风险
Ansible官方提供了详尽的使用指南,网上也有很多优秀的Ansible教程用例,但就我们产品在实践Ansible中遇到的服务器敏感信息安全保护问题,网上这方面的资料却相对较少。
近几年国家在信息安全方面的投入越来越大,HW攻防期间,某某企业由于运维平台被攻陷,导致蓝军借运维平台对企业内服务器进行任意操作的例子屡见不鲜。在Ansible实践上,敏感信息保护是最基本的安全底线。
三、解决:敏感信息安全加固的几种方法
Ansible采用agentless的方式,对远端服务器建立SSH通道,执行playbook或role里操作命令。
在对远端服务器建立SSH的方式上,支持显式密码方式连接,也支持SSH公私钥证书的方式。无疑,SSH密码或私钥证书就是Ansible使用中典型的敏感信息。
采用显式密码连接的方式,如何防止密码信息明文保存导致的信息泄露?
采用隐式公私钥证书连接的方式,如何防止私钥证书被恶意窃取,对企业服务器进行非法连接?
本文以远端服务器的SSH连接密码和证书,就敏感信息保护,结合Ansible进行实践探索。
1. 采用prompt交互的方式输入敏感内容
Ansible在采用Ad-Hoc或Playbook模式执行命令时,指定的inventory文件里,需要包含有远端服务器的账户名(ansible_ssh_user)和密码(ansible_ssh_pass),密码如果明文保存在inventory文件里,一旦服务器被攻陷,或者inventory文件被获取,就会导致企业内部服务器的敏感信息(这里是密码)泄露。
为此,可以采用Ansible prompt交互输入的方式,在运行时由客户或企业管理运维人员输入密码,来进行服务器的远程连接。
下面是prompt的使用示例:
代码语言:yaml复制# playbook: prompts.yml
---
- hosts: localhost
gather_facts: false
vars_prompt:
- name: pf_pwd
prompt: please enter the password
tasks:
- name: ensure pf_pwd is present in config.dat
lineinfile:
path: ../config.dat
regexp: '^password='
line: "password={{ pf_pwd }}"
- name: print the input content just for testing
debug: msg="the content you input is {{ pf_pwd }}"
执行prompts.yml之前,config.dat原始内容为:
代码语言:javascript复制user=pf_test
password=null
现执行prompts.yml
执行后,config.dat里的password被填充上输入的密码值:
代码语言:javascript复制user=pf_test
password=abcdef
2. 采用vault方式加密整个文件
prompt实时交互的方式,实现简单,但Ansible脚本在执行远端服务器连接时,需要人工参与输入密码,这样便限制了自动化运维的适用场景。
在实际工程应用中,大多采用无人值守的自动化运维,Ansible的文件变量功能很好的支持了该功能。
代码语言:javascript复制# 变量文件secret.src,里面的变量包含了敏感信息(如例子里的ssh连接密码)
ssh_password: abcdefg
敏感信息明文保存,这类场景在Git上常有发生。针对这类场景,Ansible Vault通过对文件进行AES对称加密,支持运行时动态解密文件,从中获取密码等敏感信息。
首先,对包含敏感信息的文件,进行加密。
将secret.src拷贝一份,重命名为secret.enc
代码语言:shell复制ansible-vault encrypt ./secret_file.enc
有了secret_file.enc文件,该文件就可以随着产品进行发布,而不用担心敏感信息明文保存被窃取的问题了。
补充说明下,如果要对vault加密的文件进行编辑或解密,使用ansible-vault decrypt/edit命令。
其次,在运行脚本时,指定使用vault加密的变量文件。
运维产品在运行时,动态临时生成vault password文件(如vault_pwd.txt),该文件里保存的是vault密码,使用完毕后清空该文件。
代码语言:shell复制ansible-playbook -e @secret_file.enc --vault-password-file ./vault_pwd.txt ./vault.yml
如上,在调用Playbook vault.yml时,就会对secret_file.enc里的变量进行动态解密获取。
通过vault对敏感文件或内容加密,就可以实现在网络传输或本地保存时,敏感信息文件也具有一定的安全性。
3. 采用vault方式加密部分变量
vault除了可以针对完整文件进行加解密使用外,也支持针对变量文件的部分变量进行加密保护。通过ansible-vault encrypt_string命令,即可实现对文件里的部分变量内容进行加密。
4. 工程化的加密实践
SSH远程连接方式选择
在通过Ansible对企业内服务器进行管理时,推荐使用公私钥方式,证书认证可以很好的解决企业内的服务器密码频繁变更问题。
之前我们有家KA客户,服务器密码每日一变,到后来,连客户侧的运维同学都不清楚密码是什么,只能进行重置。
管控机私钥证书管理
通过vault方式对私钥证书进行加密,加密后的文件不落地,通过管控WEB控制台运行时进行位置随机化后动态临时落地。在调用playbook时,指定私钥证书的文件路径。
vault加解密密码管理
前面介绍的内容中,对敏感信息采用vault加密,ansible脚本运行时,以交互输入/指定文件的方式作为vault解密密码输入源。针对vault加解密密码,建议可以通过lookup插件,基于第三方的认证系统获取vault解密密码,进一步增强敏感信息的安全性。
特别注意日志输出泄露敏感信息
ansible脚本在执行时,可以通过-v启用详细模式,更加详细的进行日志输出,这里就特别要注意了,在进行详细日志输出时,会将playbook的一些变量进行打印输出(其中就可能包含用户交互输入的密码)。如下面的这段playbook:
代码语言:javascript复制---
- hosts: localhost
gather_facts: false
vars_prompt:
- name: pf_pwd
prompt: Please enter the password
tasks:
- name: -vvv will print out sensitive information
lineinfile:
path: ../config.dat
regexp: '^password='
line: "password={{ pf_pwd }}"
在脚本的Task段里,开启nolog功能,可以有效避免日志中输出敏感信息的问题。
代码语言:javascript复制---
- hosts: localhost
gather_facts: false
vars_prompt:
- name: pf_pwd
prompt: Please enter the password
tasks:
- name: no log will not print out sensitive information
lineinfile:
path: ../config.dat
regexp: '^password='
line: "password={{ pf_pwd }}"
no_log: true
启用nolog后的脚本执行效果如下:
四、总结
在使用Ansible进行自动化运维时,需要特别关注敏感信息的安全性。
Ansible Prompt方式提供了交互输入,让使用者在动态运行过程中,输入敏感信息。这种方式实现简单,安全性高,但需要人工的介入,自动化能力差。
Ansible Vault方式采用对称加密的方式,支持对文件或文件中部分变量进行加密,在调用playbook时,对vault进行解密的密码,可以采用交互输入的实时输入,也可以采用指定vault解密文件无交互执行,还可以结合lookup插件与第三方认证系统对接,来提供vault解密的密码。
最后,尤其要注意Ansible的详细输出模式,通过启用nolog,来对敏感信息进一步保护。