最近爆出不少公司代码泄露的新闻,像前不久的Bilibili后端代码被上传到Github,大疆因为前员工泄露公司源代码,致黑客入侵造成百万损失。生产环境代码泄露的危害,一方面是业务逻辑被不怀好意的人分析,容易被找出可利用的漏洞,当然更危险的是如果代码里面有一些明文存储secrets、Token、Api Key等,这些内容被别人拿到,服务就很容易遭到致命的攻击,给我们带来不可估量的损失 。所以合理存储程序中的secrets是十分有必要的。本文接下来简单给大家介绍解决以上问题方法密钥管理服务(Key Management Service,KMS)以及一款开源的密钥管理工具Vault。
一. 密钥管理服务介绍
1.1 什么是密钥管理服务?
密钥管理服务是一款安全管理类服务,使用经过第三方认证的硬件安全模块 HSM(Hardware Security Module) 来生成和保护密钥。帮助用户轻松创建和管理密钥,满足用户多应用多业务的密钥管理需求,符合监管和合规要求。
1.2 具体应用在哪些场景?
1.2.1 账号及密码
网站用户的账号、密码等关键数据,明文存放非常危险,万一泄露或被窃取会产生巨大损失,因此想要使用密钥来对其进行加密存储,使用的时候再对其进行解密。密钥的管理必须是安全的,访问必须经过授权。
1.2.2 SSL证书
目前大部分网站使用HTTPS协议来保障数据传输时的安全,在网站提供HTTPS服务时就需要使用到SSL证书和密钥。若以明文保存在本地 ,攻击者获取SSL证书和密钥后,HTTPS的安全机制就完全失效了。
1.2.3 合规性要求
政策法规要求密钥管理必须符合相关规定,必须确保密钥调用都拥有合理的授权,密钥相关的操作都能够被审计、追溯。
二. Vault密钥管理
Vault是用来安全的存储秘密信息的工具,提供了对Token,密码,证书,API key等的安全存储(key/value)和控制功能。它能处理key的续租、撤销、审计等功能。通过API访问可以获取到加密保存的密码、SSH key、证书等。
2.1 Vault的特性
(1)安全的存储后端
任意的键值对密码都能存储在Vault。Vault在把数据写入存储后端之前会先将数据加密,所以即使你直接读取存储后端数据也无法拿到数据的明文。
(2)动态密码生成
Vault能够按需生成某些后端的密码,例如:AWS、SQL数据库等等。当一个应用需要访问AWS的S3 bucket,应用向Vault请求访问S3 bucket的证书,Vault能按需生成一个指定权限的AWS密钥,并且能够根据租期自动销毁这个密钥。
(3)数据加密
Vault可以在不对数据存储的情况下,对数据进行加密和解密。安全团队只需定义好加密方法,开发将加密后的数据存储在例如SQL之类的后端即可,而无需设计自己的加密方式。
(4)租期和续租
在Vault里面,全部的密码都可以跟租期联系起来。在租期结束时,Vault会自动销毁对应的密码。客户端能够通过Renew-API进行续租。
(5)销毁
Vault本身支持对密码进行销毁,不仅支持销毁单个密码,还支持销毁与之关联的密码。比如指定某个用户读取的全部密码,或者特定类型的密码。销毁功能能够在密码被泄露的时候辅助锁定系统。
2.2 Vault的使用场景
(1)作为集中存储各个服务器账号密码的服务器。
比如数据库密码泄露,正常流程可能是需要先修改密码,首先数据库修改密码,然后通知到应用,应用再做代码上的变更。如果使用Vault的话,数据库只要在Vault上面修改好密码之后通知应用重新从Vault拉取最新密码就行了,类似于实现了加密的配置文件的效果。
(2)为每一个操作单位动态分配账号
当我们想要对某些敏感操作进行审计,但是由于生成账号比较麻烦,所以存在公用账号的情况。Vault支持为某些后端动态生成账号的功能,比如SQL,当某个应用向Vault请求账号密码的时候,Vault能够为每次请求生成一个独一无二的SQL账号密码。
(3) 作为证书服务器
Vault能够作为CA服务器,根据请求信息自动颁发证书。并且提供在线CA和CRL的功能。
(4)作为OAUTH服务器
Vault支持多种认证后端,比如GitHub、Kubernetes、账号密码等。Vault能够将这些账号关联成一个用户,在用户认证之后返回一个Token供其使用。一个系统可能需要访问多个带密码的后端:例如数据库、通过API keys对外部系统进行调用,面向服务的架构通信等等。要将众多系统中的用户和权限对应起来已经非常困难,加上提供密钥滚动功能、安全的存储后端还要有详细的审计日志,自定义解决方案几乎不太可能,所以Vault就出现了。
三. Vault部署与应用
3.1 安装
源码编译安装(需要本机安装Golang和Git环境,具体步可骤参见网上)
1.源码下载到GOPATH
$ git clone https://github.com/hashicorp/vault
2. 进入代码目录,编译(因为编译需要安装相关库,所以需要使用代理)
$ cd $GOPATH/src/github.com/hashicorp/vault/$ make dev
预编译的Vault二进制安装
1.下载预编译二进制包
$ wget https://releases.hashicorp.com/Vault/1.1.3/Vault_1.1.3_linux_amd64.zip
2.解压到环境变量路径
$ unzip Vault_1.1.3_linux_amd64.zip -d /usr/local/bin
这里建议直接使用预编译的二进制包安装,简单快捷。
3.2 服务配置与启动
3.2.1 启动配置文件
编辑配置文件vault.hcl,配置中需要配置存储密钥的数据库相关信息,这里用的MySQL,官网上还支持其他数据库,具体信息参见官方文档:(https://www.vaultproject.io/docs/configuration/storage/index.html)
1 disable_mlock = true2 ui = true3 backend "mysql" {4 address = "192.168.23.225:3306"5 username = "root"6 password = "123456"7 database = "vault-test"8 table = "vault"9 }10 listener "tcp" {11 address = "0.0.0.0:8200"12 tls_disable = 113 }1415 api_addr = "http://192.168.23.225:8200"
3.2.2 启动Vault
1 #启动Vault服务23 vault server -config=vault.hcl45 #设置访问地址设置成http67 export VAULT_ADDR=http://127.0.0.1:8200
3.2.3 初始化Vault
1 vault init -key-shares=5 -key-threshold=323 # -key-shares:指定密钥的总股数,45 # -key-threshold:指定需要几股可解锁67 # 以上参数为默认,可不设置。
Vault借助Shamir门限秘密共享方案创建主密钥
初始化的Vault会返回5个密钥,根据我们设置的启动参数,正确输入其中的3个密钥就可以解封数据库。Root Token是用作首次访问Vault使用。
1 Unseal Key 1: O2h1reLoykkEDPVptQ7xr4M6zpSLwexYvRxSbIsRqIRX23 Unseal Key 2: xo5sQSE2MoiUbT4s/9WvmEF18K9HWy2ARwS1wW4VnX2c45 Unseal Key 3: jm6BkWMnZlYGf2R5van32UJdB8nzE6uemyYz4JrsMH/267 Unseal Key 4: B6qEyjN26sookmCbmh0ZJr/B/4Ik7FdALaFmF4pylDGh89 Unseal Key 5: Zw+JnaM7biiLlA094o2pAIXWrEM37sV7BF9flg8DFe8K10111213 Initial Root Token: s.MWnxEObtfY6Knkk8tkDZs5yz14151617 Vault initialized with 5 key shares and a key threshold of 3. Please securely1819 distribute the key shares printed above. When the Vault is re-sealed,2021 restarted, or stopped, you must supply at least 3 of these keys to unseal it2223 before it can start servicing requests.24252627 Vault does not store the generated master key. Without at least 3 key to2829 reconstruct the master key, Vault will remain permanently sealed!30313233 It is possible to generate new unseal keys, provided you have a quorum of3435 existing unseal keys shares. See "vault operator rekey" for more information.
3.2.4 解封Vault
数据初始化的时候获取的5个密钥中的3个对Vault进行解封操作:
1 vault operator unseal23 #分别输入5个中的3个密钥45 Unseal Key (will be hidden):67 Key Value89 --- -----1011 Seal Type shamir1213 Initialized true1415 Sealed true1617 Total Shares 51819 Threshold 32021 Unseal Progress 1/32223 Unseal Nonce 4bd56e46-40c1-baf9-ce13-b47386f35d782425 Version 1.1.22627 HA Enabled false
成功解封后,一个可用的Vault服务就启动了。
3.3 创建CA签发引擎
Vault可以使用简单的API调用,实现撤销或颁发新的CA证书,完美解决了手动生成自签名证书的困扰。创建一个CA证书签发引擎步骤如下:
3.3.1 登录Vault
使用Root Token登录Vault
1 vault login s.MWnxEObtfY6Knkk8tkDZs5yz2345 Success! You are now authenticated. The token information displayed below67 is already stored in the token helper. You do NOT need to run "vault login"89 again. Future Vault requests will automatically use this token.10111213 Key Value1415 --- -----1617 token s.MWnxEObtfY6Knkk8tkDZs5yz1819 token_accessor kVlLumxoJUyBH7ORZ0oNJgH72021 token_duration ∞2223 token_renewable false2425 token_policies ["Root"]2627 identity_policies []2829 policies ["Root"]
3.3.2 创建Root CA
在创建根CA之前,我们需要先在Vault创建一个路径来存放Root CA
1 #创建存放证书路径23 vault secrets enable -path=test -description="MQTT CA" -max-lease-ttl=87600h pki4567 Success! Enabled the pki secrets engine at: test /89 #查看已经创建的引擎1011 vault secrets list
Vault中的每个secret引擎都需要定义路径和属性。对于用户来说,secret引擎的行为类似于虚拟文件系统,支持读、写和删除等操作,当然具体取决于使用角色分配给它们的权限。
1 #创建Root CA 填写相关证书信息23 vault write test/Root/generate/internal \45 common_name="test.com" \67 ttl=87600h \89 key_bits=4096
执行成功后会返回certificate就是我们的Root CA。更多的证书申请参数参见官网文档: Vault PKI证书介绍
3.3.3 创建角色
1 #创建role23 vault write test/roles/test_server \45 key_bits=2048 \67 max_ttl=8750h \89 allow_any_name=true
参数的test就是我们刚刚存放Root CA的路径,test_server就是我们创建角色的名称。
3.3.4 签发证书
那么就下来就用刚刚申请的角色签发一个证书。
1 #签发证书23 vault write test/issue/test_server \45 common_name="test.com" \67 ttl=8660h \89 format=pem
因为返回结果比较长,就不在文中贴了。执行成功后,会返回一个我们新签的CA证书,还有我们的Root CA,还有就是新颁发CA的私钥。
当然颁发证书的接口我们也可以通过HTTP接口获得:
定义请求参数 payload.json:
1 {23 "common_name": "iot-sdk.intra.***.com",45 "ttl":"8000h",67 "format":"pem"89 }
使用curl向Vault服务器发起POST请求,X-Vault-Token就是Vault的Root Token:
1 curl --header "X-Vault-Token: s.MWnxEObtfY6Knkk8tkDZs5yz" --request POST --data @payload.json http://192.168.23.225:8200/v1/test/issue/test_server23 {4 "auth": null,5 "data": {6 "certificate": "-----BEGIN CERTIFICATE-----\nMIIEXjdCzwN6h2...\n-----END CERTIFICATE-----",7 "expiration": 1589711650,8 "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIFLDCCAxSgAwI...\n-----END CERTIFICATE-----",9 "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAA...\n-----END RSA PRIVATE KEY-----",10 "private_key_type": "rsa",11 "serial_number": "76:e8:f1:49:91:58:8e:e3:6a:bc:b3:2d:ae:1c:bb:de:0c:27:a0:a6"12 },13 "lease_duration": 0,14 "lease_id": "",15 "renewable": false,16 "request_id": "08d5fd69-bc93-5b10-9bc7-94ff47440b3b",17 "warnings": null,18 "wrap_info": null19 }
3.3.5 证书校验
接下来,用Root CA验证一下我们新签发的CA证书:
将我们的Root CA存储到ca.crt中
签发CA存储到server.crt中
使用openssl命令进行校验,返回OK就证明申请的证书校验通过
1 #使用openssl校验证书23 openssl verify -CAfile ca.crt client.crt45 server.crt: OK
综上,一个完整的使用Vault签发CA证书的流程就完成了。
四. 总结
个人觉得Vault是一个非常有用的应用,所以写了这篇介绍的文章分享给大家。当然本文也只是简单介绍了Vault中CA证书引擎的使用方法,它还支持SSH密钥管理、KV加密存储等功能。要发掘Vault的更多信息,请访问其官方网(https://www.vaultproject.io/)。对程序的密钥、Token、用户及密码等合理的加密管理,让我们的服务更安全。
参考链接:
[1]. https://help.aliyun.com/document_detail/28935.html?spm=a2c4g.11186623.6.542.67c4623aXx5oM4
[2]. https://cloud.baidu.com/doc/KMS/ProductDescription/24.5C.E5.BA.94.E7.94.A8.E5.9C.BA.E6.99.AF.html
[3]. Vault-服务器密码/证书管理工具:https://segmentfault.com/a/1190000012959727?utm_source=tag-newest
[4]. https://medium.com/@sufiyanghori/guide-using-hashicorp-vault-to-manage-pki-and-issue-certificates-e1981e7574e
[5]. https://www.vaultproject.io/
声明:本文来自绿盟科技研究通讯,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。