CFSSL使用方法)
1 前言
我们在实际的工作中经常遇到制作自定义的服务器证书的场景,目前能够制作CA根证书及服务器证书有Openssl
及cfssl
两种常用工具。
Openssl
的用法可以参考《数字证书那点事(附CP4D及VCenter7定制TLS证书部署案例参考)》这篇文章。
访问地址:https://mp.weixin.qq.com/s/A9kww8ODzIVtHI7IOLLs0A
cfssl
使用相对简单,本文采用cfssl 1.6.0版本进行简单介绍。
这里按照替换VMware VCenter 7
的的服务器证书做案例。
第一步:安装,直接二进制安装。也可以基于go get/go install
。当然也可以在mac平台下通过brew安装cfssl工具。
第二步:编辑配置文件和CA根证书请求配置文件,均为json
格式。默认配置文件可以通过cfssl print-defaults config
生成,默认请求文件可以通过cfssl print-defaults csr
生成。推荐采用CAT EOF
方式。
第三步:生成CA根证书。输入是CA证书请求配置文件,输出是三个文件,分别是CA根证书私钥、CA根证书、CA根证书请求文件。
第四步:编辑服务器或者客户端的证书请求配置文件,另外一个输入文件是第二步的配置文件,输出三个文件,分别是服务器或客户端证书,请求文件以及服务器或客户端的秘钥文件。
2 安装
可能需要科学上网访问下载地址
下载地址:https://github.com/cloudflare/cfssl/releases

可以在浏览器中右键复制具体的链接的下载地址。

将复制的下载地址在准备好的工具机上进行试验。本文环境是CentOS Stream release 8
。
1
2
3
4
5
6
7
8
9
10
11
|
# 逐个下载二进制文件至当前路径,也可以使用`-O`参数直接下载到/usr/local/bin目录下。
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl_1.6.0_linux_amd64
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl-certinfo_1.6.0_linux_amd64
$ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssljson_1.6.0_linux_amd64
# 赋予执行权限
$ chmod +x cfssl*
#拷贝二进制文件至执行目录
$ cp cfssl-certinfo_1.6.0_linux_amd64 /usr/local/bin/cfssl-certinfo
$ cp cfssl_1.6.0_linux_amd64 /usr/local/bin/cfssl
$ cp cfssljson_1.6.0_linux_amd64 /usr/local/bin/cfssljson
|
验证版本
1
2
3
|
$ cfssl version
Version: 1.6.0
Runtime: go1.12.12
|
3 开始使用
3.1 获取默认设置
我们首先看下程序默认的几个配置文件和证书请求配置文件模板。
1
2
|
$ cfssl print-defaults config > ca-config.json
$ cfssl print-defaults csr > ca-csr.json
|
验证
1.6版本的默认的配置文件ca-config.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
$ cat ca-config.json
{
"signing": {
"default": {
"expiry": "168h"
},
"profiles": {
"www": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
|
1.6版本的默认的证书请求文件ca-csr.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
$ cat ca-csr.json
{
"CN": "example.net",
"hosts": [
"example.net",
"www.example.net"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"ST": "CA",
"L": "San Francisco"
}
]
}
|
我们可以直接采用cat EOF
方式快速生成自定义的配置文件。
修改配置文件ca-config.json
将其中profiles
修改为自己组织相对贴切的配置名称,有效期为825天(谷歌浏览器支持最长的证书有效期,即19800小时)
我们这里定义了两个配置模板
1、CjServer:用于服务器证书认证场景,我们后续使用这个。
2、CjClient:用于客户端证书认证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "19800h"
},
"profiles": {
"CjServer": {
"expiry": "19800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"CjClient": {
"expiry": "19800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
EOF
|
注意这里profiles
字段下名称,其中CjServer
下注明server auth
用于服务器端认证,后续在生成服务器证书时候,需要使用这个名称作为cfssl命令的配置文件名称作为参数传入。
修改请求配置文件ca-csr.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
cat > ca-csr.json <<EOF
{
"CN": "CA",
"hosts": [
"cj.io",
"www.cj.io"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Shanghai",
"L": "Shanghai",
"O": "cj.io",
"OU": "infrastructure"
}
]
}
EOF
|
3.2 生成CA证书
接下来可以直接生成CA证书
1
2
3
4
5
6
7
|
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2021/06/18 21:34:00 [INFO] generating a new CA key and certificate from CSR
2021/06/18 21:34:00 [INFO] generate received request
2021/06/18 21:34:00 [INFO] received CSR
2021/06/18 21:34:00 [INFO] generating key: ecdsa-256
2021/06/18 21:34:00 [INFO] encoded CSR
2021/06/18 21:34:00 [INFO] signed certificate with serial number 49119197832097434053285907634036405122538087837
|
cfssljson -bare ca这里的ca
是生成文件的前缀名称。
最终生成三个输出文件
1
2
3
4
5
6
7
|
$ tree
.
|-- ca-config.json
|-- ca-csr.json
|-- ca-key.pem # 根证书私钥
|-- ca.csr # 根证书请求文件
|-- ca.pem # CA根证书
|
3.3 生成服务器证书
先手动配置服务器证书请求配置文件,这里是 vc7-csr.json
CN
字段这里其实已经无所谓了
从Chrome 58开始,只通过校验SAN属性验证证书的有效性。
SAN(Subject Alternative Name) 是 SSL 标准 x509 中定义的一个扩展。使用了 SAN 字段的 SSL 证书,可以扩展此证书支持的域名,使得一个证书可以支持多个不同域名的解析。
SAN属性定义在hosts
属性内。
建议将私钥的加密算法修改为rsa
,秘钥长度为2048。保持最大兼容性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$ cat > vc7-csr.json <<EOF
{
"CN": "vcenter7.vmware7.cj.io",
"hosts": [
"vcenter7.vmware7.cj.io",
"192.168.100.250"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Shanghai",
"L": "Shanghai",
"O": "cj.io",
"OU": "infrastructure"
}
]
}
EOF
|
接下来正式使用命令生成服务器证书。
1
2
3
4
5
6
7
|
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=CjServer svc7-csr.json | cfssljson -bare vc7
2021/06/18 22:00:49 [INFO] generate received request
2021/06/18 22:00:49 [INFO] received CSR
2021/06/18 22:00:49 [INFO] generating key: ecdsa-256
2021/06/18 22:00:49 [INFO] encoded CSR
2021/06/18 22:00:49 [INFO] signed certificate with serial number 634415720135636604370065819212549332214977176938
|
注意这里-profile=CjServer
,对应的是ca-config.json
的profiles
下的字段
-bare vc7
代表这里输出的文件前缀为vc7
如果提示错误,例如:
1
2
|
{"code":5100,"message":"Invalid policy: no key usage available"}
Failed to parse input: unexpected end of JSON input
|
往往是提供的-profile
参数中的配置文件名在ca-config.json
中无法匹配。
输出文件验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@localhost cfssl]# tree
.
|-- ca-config.json
|-- ca-csr.json
|-- ca-key.pem
|-- ca.csr
|-- ca.pem
|-- cfssl-bundle_1.6.0_linux_amd64
|-- cfssl-certinfo_1.6.0_linux_amd64
|-- cfssl_1.6.0_linux_amd64
|-- cfssljson_1.6.0_linux_amd64
|-- vc7-key.pem
|-- vc7.csr
|-- vc7.pem
|-- vc7-csr.json
|
3.4 证书验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
$ cfssl-certinfo -cert vc7.pem
{
"subject": {
"common_name": "vcenter7.vmware7.cj.io",
"country": "CN",
"organization": "cj.io",
"organizational_unit": "infrastructure",
"locality": "Shanghai",
"province": "Shanghai",
"names": [
"CN",
"Shanghai",
"Shanghai",
"cj.io",
"infrastructure",
"vcenter7.vmware7.cj.io"
]
},
"issuer": {
"common_name": "CA",
"country": "CN",
"organization": "cj.io",
"organizational_unit": "infrastructure",
"locality": "Shanghai",
"province": "Shanghai",
"names": [
"CN",
"Shanghai",
"Shanghai",
"cj.io",
"infrastructure",
"CA"
]
},
"serial_number": "276418019776528630294564872665785780190539038564",
"sans": [
"vcenter7.vmware7.cj.io",
"192.168.100.250"
],
"not_before": "2021-06-21T08:00:00Z",
"not_after": "2023-09-24T08:00:00Z",
"sigalg": "SHA256WithRSA",
"authority_key_id": "D5:36:EA:1E:0B:A1:2B:40:E5:39:C4:AE:6D:F7:51:7B:76:AD:5E:80",
"subject_key_id": "E8:86:33:58:B6:32:2A:9E:68:35:F5:DC:24:2E:B6:03:4A:BA:AD:3E",
"pem": "-----BEGIN CERTIFICATE-----\nMIIEFDCCAvygAwIBAgIUMGsDP8gv9upteJrcqxCKKlBiP2QwDQYJKoZIhvcNAQEL\nBQAwaTELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFNoYW5naGFpMREwDwYDVQQHEwhT\naGFuZ2hhaTEOMAwGA1UEChMFY2ouaW8xFzAVBgNVBAsTDmluZnJhc3RydWN0dXJl\nMQswCQYDVQQDEwJDQTAeFw0yMTA2MjEwODAwMDBaFw0yMzA5MjQwODAwMDBaMH0x\nCzAJBgNVBAYTAkNOMREwDwYDVQQIEwhTaGFuZ2hhaTERMA8GA1UEBxMIU2hhbmdo\nYWkxDjAMBgNVBAoTBWNqLmlvMRcwFQYDVQQLEw5pbmZyYXN0cnVjdHVyZTEfMB0G\nA1UEAxMWdmNlbnRlcjcudm13YXJlNy5jai5pbzCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAKx0lB8+OmInafxfKu+fRdA3z3fiH4xfkHSUMhTOOcmgXYL4\nN1jv+D5uqPK/FmA97QToms9KTF7JDSAA7vPbOK/pZbObpXtn5SdJtG4RwRZfTrOD\nRro5RQfe8WgKW1zsH6a2BaRIGEOWD2qSMqwGH6YQeJ6xrOsup2YUHsrCzxwKT5tT\nLQpqIyb8JAat1agzoGGBmCD9F0MLGB5ZpNi3RFqxURm7ikCimUGLzfwtgow69BF8\nJ4r5NArNMfFHx9HOyo0QE6C7f+cqKK9rrnzBqDJnSHre3wD+LvnZaTBrMTvNYjWC\nmg/0WpLpFN3C6KnGfHWNJa7BMEcP32i/mTwy0W0CAwEAAaOBnzCBnDAOBgNVHQ8B\nAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNV\nHQ4EFgQU6IYzWLYyKp5oNfXcJC62A0q6rT4wHwYDVR0jBBgwFoAU1TbqHguhK0Dl\nOcSubfdRe3atXoAwJwYDVR0RBCAwHoIWdmNlbnRlcjcudm13YXJlNy5jai5pb4cE\nwKhk+jANBgkqhkiG9w0BAQsFAAOCAQEAGuMNn9orTJVvi2xjA7hTpQFE0kIEP+Kr\nm758DOsTE/JS1YTM0JEDhADQzD97stRZ/F7/ENCZ2zxGOZkKOo/oUZ7Mxcy/LSyV\nt6ZFLhCqsfQCeatcg3E6REpe5j1kxxf6lgAyOqw9tG8oaHMKBEaCoAOMCEh/egEe\nZFYL/S+odKHZZnYZqcq5078AAH1V0SNzryX1Zv1HrVgUfdYxBydUWdGVVvi1d0Ul\n907/g0Tr77vRrf5+htHLYyIk047s7aSkZICnxoxA1BfB7qmBWiCdVvjFvTAoGKsq\nfPAR4jcHL0a+i6PYC0QhJiweXuMgTw7Mt0Y+gRIqkxF8T819lRypCg==\n-----END CERTIFICATE-----\n"
}
|
注意其中"sans"
字段和所设计的域名是否匹配。
4 使用证书
登录VMware VCenter 7
,对服务器证书进行替换。

选择“替换为外部CA证书(需要私钥)”

依次选择生成的服务器证书,CA根证书及CA根证书私钥。

替换后,可以查看浏览器地址栏左侧查看证书详细情况。

继续查看证书其他信息

继续查看证书其他信息
