使用Vault搭建企业PKI系统

静态的数据加密和传输中的数据加密,对于数据安全来说同等重要。目前最流行的用于传输中数据加密的方式就是 SSL/TLS。 对于大多数企业内部网络管理员,如果不是非用不可,一般都不会主动使用SSL/TLS,没有一个方便高效和安全的创建CA,签发证书的解决方案。

Hashicorp公司的Vault工具出现,将秘钥管理提升到了一个新水平,其中的PKI后端可以方便的帮助企业搭建一套私有的PKI体系。Vault的使用文档从功能的角度对pki后端做了详细介绍,我在此将提供一个搭建企业自建PKI的完成过程。

这篇介绍将包括以下几个部分:

1. 启动vault服务

2. 为企业创建一个根CA

3. 为企业创建一个中间CA

4. 为一个web服务颁发TLS秘钥和证书 

5. 使用NGINX测试签发的证书

需要澄清的是这篇介绍只是一个对于概念完整介绍,并不是一个最好的实践方案,在此的目的是介绍pki后端的功能。 真实实践时,Vault需要配置为HA模式,由TLS保护,不使用root token和策略,与CA和证书关联的有效期也应谨慎的根据真实的应用情况而定。

Vault作为企业内部自建CA最方便的一点就是,应用可以随时请求证书和秘钥。这就意味着可以通过基本的cron任务来更新证书,因此证书的有效期可以尽可能的短(这部分内容我会在我的另一篇博客中介绍)。但这部分功能也是Vault与我们之前习惯使用的EasyRSA或者是CFSSL的区别所在,它改变了我们管理TLS的方式。


启动 Vault

下载Vault后,创建一个目录存储相关加密数据和配置等。接下来创建一个配置文件,并启动服务:

$ mkdir vault && cd vault
$ vi vault.hcl
disable_mlock  = true

listener "tcp" {
  address = "0.0.0.0:8200"
  tls_disable = 1
}

backend "file" {
  path = "/home/benr/vault/secrets"
}
$ vault server -config=vault.hcl
==> Vault server configuration:

                 Backend: file
              Listener 1: tcp (addr: "0.0.0.0:8200", tls: "disabled")
               Log Level: info
                   Mlock: supported: true, enabled: false
                 Version: Vault v0.6.0

==> Vault server started! Log data will stream in below:
在另一个终端中初始化并解封Vault:

$ export VAULT_ADDR='http://127.0.0.1:8200'
$ vault init
Unseal Key 1: 811538b33c90d6f558b0296e12dc0023fc4086f5cbc424a2a3766d52dd52d7cf01
Unseal Key 2: 3eb6e073249168bdef779cf0e47f5c02baf7a2260e3d531073ae40862916029302
Unseal Key 3: b99b0b9a16f2f88ab83f87ddab4e6f483b15f288889bc9d1b9b2d154ad14ac8f03
Unseal Key 4: c24260a579914e78f78123b7a83fc96ebd16434980fc5a003f24bd5e2ecf7fa804
Unseal Key 5: 456f8b4c4bf2de4fa0c9389ae70efa243cf413e7065ac0c1f5382c8caacdd1b405
Initial Root Token: d194e2e3-6483-aa23-9bf2-f1bb31b0edbb
...

$ vault unseal 811538b33c90d6f558b0296e12dc0023fc4086f5cbc424a2a3766d52dd52d7cf01
$ vault unseal 3eb6e073249168bdef779cf0e47f5c02baf7a2260e3d531073ae40862916029302
$ vault unseal b99b0b9a16f2f88ab83f87ddab4e6f483b15f288889bc9d1b9b2d154ad14ac8f03
Sealed: false
Key Shares: 5
Key Threshold: 3
Unseal Progress: 0
$ vault auth
Token (will be hidden): d194e2e3-6483-aa23-9bf2-f1bb31b0edbb
Successfully authenticated! You are now logged in.
token: d194e2e3-6483-aa23-9bf2-f1bb31b0edbb
token_duration: 0
token_policies: [root]
好了!到了这一步Vault已经启动并解封,可以使用了。


创建一个根CA

在Vault中,秘密信息是通过"backend"(后端)管理的,在使用之前必须被挂载。这在刚开始使用Vault时看起来非常奇怪,但这确实是合理的设计,后端可以多次挂载在不同的路径下。这个特性在我们搭建PKI时十分重要,因为Vault的一个pki后端只能代表一个CA,因此我们需要挂载两个pki后端,一个作为根CA,一个作为中间CA。这个特性使一个Vault服务可以支持多个CA,它们之间又彼此独立。

因此,我们先挂载一个pki后端,作为根CA,路径为“cuddltech”。我们在挂载时需要提供路径("path",用于访问这个特定后端的路径),描述("description"),最长有效期("maximum lease TTL"):

$ vault mount -path=cuddletech -description="Cuddletech Root CA" -max-lease-ttl=87600h pki
Successfully mounted 'pki' at 'cuddletech'!
$ vault mounts
Path         Type       Default TTL  Max TTL    Description
cubbyhole/   cubbyhole  n/a          n/a        per-token private secret storage
cuddletech/  pki        system       315360000  Cuddletech Root CA
secret/      generic    system       system     generic secret storage
sys/         system     n/a          n/a        system endpoints used for control, policy and debugging 
现在我们就可以创建我们的根CA证书和秘钥了:

$ vault write cuddletech/root/generate/internal \
> common_name="Cuddletech Root CA" \
> ttl=87600h \
> key_bits=4096 \
> exclude_cn_from_sans=true
Key             Value
---             -----
certificate     -----BEGIN CERTIFICATE-----
MIIFKzCCAxOgAwIBAgIUDXiI3GDzP2IbQ9IatFSCv9Pq/lgwDQYJKoZIhvcNAQEL
BQAwHTEbMBkGA1UEAxMSQ3VkZGxldGVjaCBSb290IENBMB4XDTE2MDcwOTA4MTIz
..
axscmLdVE2HTB87W1H77iKKN8n9Xne//LUidxVX0Kg==
-----END CERTIFICATE-----
expiration      1783411981
issuing_ca      -----BEGIN CERTIFICATE-----
MIIFKzCCAxOgAwIBAgIUDXiI3GDzP2IbQ9IatFSCv9Pq/lgwDQYJKoZIhvcNAQEL
BQAwHTEbMBkGA1UEAxMSQ3VkZGxldGVjaCBSb290IENBMB4XDTE2MDcwOTA4MTIz
...
axscmLdVE2HTB87W1H77iKKN8n9Xne//LUidxVX0Kg==
-----END CERTIFICATE-----
serial_number   0d:78:88:dc:60:f3:3f:62:1b:43:d2:1a:b4:54:82:bf:d3:ea:fe:58
最后需要做的就是配置URL用于获取CA证书和CRL:

$ vault write cuddletech/config/urls issuing_certificates="http://10.0.0.22:8200/v1/cuddletech
Success! Data written to: cuddletech/config/urls
到此,根CA就已经准备好了,接下来需要生成中间CA。


创建一个中间CA

创建中间CA的过程和创建根CA的过程类似,最大的不同是不能用一步一次生成证书和私钥。我们需要再挂载一个pki后端,在此先生成CSR和私钥,然后将CSR给根CA所在后端签名,将得到的证书导入后创建的pki后端作为中间CA的证书。

说起来有点绕,看步骤就清晰明了了。首先为中间CA再挂载一个pki后端,将它命名为Ops 中间CA:

$ vault mount -path=cuddletech_ops -description="Cuddletech Ops Intermediate CA" -max-lease-ttl=26280h pki
Successfully mounted 'pki' at 'cuddletech_ops'!

$ vault mounts
Path             Type       Default TTL  Max TTL    Description
cubbyhole/       cubbyhole  n/a          n/a        per-token private secret storage
cuddletech/      pki        system       315360000  Cuddletech Root CA
cuddletech_ops/  pki        system       94608000   Cuddletech Ops Intermediate CA
下一步生成一个中签CA的CSR:

$ vault write cuddletech_ops/intermediate/generate/internal \
>  common_name="Cuddletech Operations Intermediate CA"
>  ttl=26280h \
>  key_bits=4096 \
>  exclude_cn_from_sans=true
Key     Value
---     -----
csr     -----BEGIN CERTIFICATE REQUEST-----
MIICuDCCAaACAQAwMDEuMCwGA1UEAxMlQ3VkZGxldGVjaCBPcGVyYXRpb25zIElu
dGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALt8
...
hD8cpHTXqjKExYWKc/rQDgjw9+RNDdb45xszDagrgFgNPqI9i0fNh9jViMmjUiTc
PQTZS4XxIoRrx1/xVHJ4Qm++ntLPVCvzjMZafg==
-----END CERTIFICATE REQUEST-----
复制CSR的值到一个新建的文件: cuddletech_ops.csr 这样做的原因是下一步需要将它作为参数传给根CA所在后端进行签名。

$ vault write cuddletech/root/sign-intermediate \
>  csr=@cuddletech_ops.csr \
>  common_name="Cuddletech Ops Intermediate CA" \
>  ttl=8760h
Key             Value
---             -----
certificate     -----BEGIN CERTIFICATE-----
MIIEZDCCAkygAwIBAgIUHuIhRF3tYtfoZiAFdjcCtQpMR+cwDQYJKoZIhvcNAQEL
BQAwHTEbMBkGA1UEAxMSQ3VkZGxldGVjaCBSb290IENBMB4XDTE2MDcwOTA4Mjkz
...
UtI2b/AamAqf340eRKmSdEh4WypB4JR+t259YA45w2j4mS+rxREycEk4YosR/vUs
jekMiq57yNq7h8eOTrnOulJxazbVrYGb
-----END CERTIFICATE-----
expiration      1470645002
issuing_ca      -----BEGIN CERTIFICATE-----
MIIFKzCCAxOgAwIBAgIUDXiI3GDzP2IbQ9IatFSCv9Pq/lgwDQYJKoZIhvcNAQEL
BQAwHTEbMBkGA1UEAxMSQ3VkZGxldGVjaCBSb290IENBMB4XDTE2MDcwOTA4MTIz
..
1FRGlwHUg+6IIZBVIapzivLc6pAvLFPxQlQvT5CNHPk91zwyNQ9ZX2PzatdajUnd
axscmLdVE2HTB87W1H77iKKN8n9Xne//LUidxVX0Kg==
-----END CERTIFICATE-----
serial_number   1e:e2:21:44:5d:ed:62:d7:e8:66:20:05:76:37:02:b5:0a:4c:47:e7
现在我们就有了一个已经被根CA签名过了证书了,我们将证书内从复制粘贴到一个新建文件: cuddletech_ops.crt 我们将它导入中间CA的后端:

$ vault write cuddletech_ops/intermediate/set-signed \
> certificate=@cuddletech_ops.crt
Success! Data written to: cuddletech_ops/intermediate/set-signed
我们来验证一下:

$ curl -s http://localhost:8200/v1/cuddletech_ops/ca/pem | openssl x509 -text | head -20
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            76:12:53:41:be:18:98:2c:a1:51:4a:f8:f0:bd:b4:a3:44:7e:74:59
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Cuddletech Root CA
        Validity
            Not Before: Jul  9 09:23:39 2016 GMT
            Not After : Jul  9 09:24:09 2017 GMT
        Subject: CN=Cuddletech Ops Intermediate CA
 ...
最后要做的就是配置获取CA和CRL的url:

$ vault write cuddletech_ops/config/urls \
> issuing_certificates="http://10.0.0.22:8200/v1/cuddletech_ops/ca" \
> crl_distribution_points="http://10.0.0.22:8200/v1/cuddletech_ops/crl"
Success! Data written to: cuddletech_ops/config/urls

为一个Web服务申请一个证书

到这里为止,我们的CA就配置好了,接下来看看如何颁发证书。颁发证书需要两个步骤,第一步是创建一个角色,定义和限制生成证书的一些参数,例如秘钥类型和秘钥长度,证书类型等等。第二步就是颁发一个该角色的证书。

在中间CA后端中创建一个名为“web_server”类型的角色,该角色可生成的秘钥长度为2048 bits,最长有效期为1年,允许任意CN。

$ vault write cuddletech_ops/roles/web_server \
> key_bits=2048 \
> max_ttl=8760h \
> allow_any_name=true
Success! Data written to: cuddletech_ops/roles/web_server
接下来就可以使用这个角色去颁发证书了。

$ vault write cuddletech_ops/issue/web_server \
> common_name="ssl_test.cuddletech.com" \
> ip_sans="172.17.0.2" \
> ttl=720h
> format=pem
Key                     Value
---                     -----
lease_id                cuddletech_ops/issue/web_server/e03318f2-d005-8196-4ed5-a42f9cd55238
lease_duration          2591999
lease_renewable         false
certificate             -----BEGIN CERTIFICATE-----
MIIE7jCCAtagAwIBAgIUN+vXFuIf42v1SW+mDROUVAm+lUMwDQYJKoZIhvcNAQEL
BQAwKTEnMCUGA1UEAxMeQ3VkZGxldGVjaCBPcHMgSW50ZXJtZWRpYXRlIENBMB4X
DTE2MDcwOTA5MzE1N1oXDTE2MDgwODA5MzIyN1owIjEgMB4GA1UEAwwXc3NsX3Rl
...
issuing_ca              -----BEGIN CERTIFICATE-----
MIIF5DCCA8ygAwIBAgIUdhJTQb4YmCyhUUr48L20o0R+dFkwDQYJKoZIhvcNAQEL
...
private_key             -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEApBabDpPZIloRQUpro3tQEls0FEFvsvfraQzQJLD2dicSPZ2s
CqYyT8OXMclrapG7KKTYp79AaTW8LgNg3WvCzoMGDfhLL9m0QomzrMDzoW8Q7iQO
1MV4f6JXjGMbOMMXatKQlO32fLZln8m+/yJ3pOW0S6uatFzZ/N3+ed+gDuUc7eAO
...
private_key_type        rsa
serial_number           37:eb:d7:16:e2:1f:e3:6b:f5:49:6f:a6:0d:13:94:54:09:be:95:43
我们需要将证书(certificate)和签发CA证书也就是中间CA的证书(issuing_ca)一起写入新建文件 ssl_test.cuddletech.com.crt文件中(颁发的证书在前,CA证书在后),将私钥(private_key)写入文件 ssl_test.cuddletech.com.key 中。

接下来可以配置NGINX了!


在NGINX中测试证书

将上一步得到的 ssl_test.cuddletech.com.crt证书文件路径写入NGINX配置文件,然后启动。
server {
    listen              443 ssl;
    server_name         ssl_test.cuddletech.com;
    ssl_certificate     ssl_test.cuddletech.com.crt;
    ssl_certificate_key ssl_test.cuddletech.com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;


    location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
    }
}
在NGINX启动后,用浏览器访问,这时你会看到熟悉的“Your connection is not secure”的警告,我们需要导出根CA的证书,并添加到浏览器的受信证书列表里。导出根CA证书:
$ curl -s http://localhost:8200/v1/cuddletech/ca/pem > cuddletech_ca.pem
当你将根CA导入浏览器受信列表里后,你就会体会到使用Vault来颁发内部TLS证书是如此好用,好用到飞起来:)






  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值