目录

CFSSL使用方法

CFSSL使用方法)


1 前言

我们在实际的工作中经常遇到制作自定义的服务器证书的场景,目前能够制作CA根证书及服务器证书有Opensslcfssl两种常用工具。

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

image-20210618204325326

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

image-20210618204559542

将复制的下载地址在准备好的工具机上进行试验。本文环境是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.jsonprofiles下的字段

-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,对服务器证书进行替换。

image-20210621165655095

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

https://typorabyethancheung911.oss-cn-shanghai.aliyuncs.com/typora/image-20210621165724858.png

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

image-20210621165750822

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

image-20210621162358930

继续查看证书其他信息

image-20210621165336628

继续查看证书其他信息

image-20210621165550124