cfssl自签CA证书用于TLS/SSL认证技术指南

apollo008
日期作者版本备注
2020-10-25dingbinv1.0

1. cfssl 是什么

部署分布式系统服务场景下,如etcd、kubernetes、grpc servers集群时,常用的安全策略除了用户名密码策略外,经常要用到TLS加密和认证策略。一种好用的签名CA证书工具是cfssl工具集。本文讲述以cfssl自签CA证书用于TLS认证技术实践方法。

cfssl的官网地址是:https://cfssl.org。简单来说,它是美国的一个叫CloudFlare的公司开发的一款开源的工具包,它在CloudFlare公司内部被用来捆绑TLS/SSL证书链,并作为内部证书颁发机构基础架构。

2. 安装cfssl软件工具包

cfssl自签证书工具集包含3个软件:

  • cfssl: 用于签发证书;
  • cfssljson: 将cfssl签发生成的证书(json格式)变成文件承载式文件;
  • cfssl-certinfo: 验证查看证书信息。

其官网下载地址是:https://pkg.cfssl.org

本文讲述的是CentOS Linux release 7.5.1804 系统下的构建TLS/SSL证书。因此下载linux-amd64版本即可。对应下载1.2版本的如下3个文件即可。
直接执行以下3个命令即可瞬间完成下载3个可执行程序文件:

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64

​由于都是linux64系统下可执行程序包,直接重命名后放到/usr/local/bin下,并添加可执行权限即可,如下图所示:

sudo cp cfssl_linux-amd64  /usr/local/bin/cfssl
sudo chmod +x /usr/local/bin/cfssl
sudo cp cfssljson_linux-amd64 /usr/local/bin/cfssljson
sudo chmod +x /usr/local/bin/cfssljson
sudo cp cfssl-certinfo_linux-amd64  /usr/local/bin/cfssl-certinfo
sudo chmod +x /usr/local/bin/cfssl-certinfo
​
which cfssl
which cfssljson
which cfssl-certinfo

image
至此cfssl工具包安装完毕。本文同时提供1.2版本的linux-amd64架构的cfssl工具包同时提供下载地址如下:

下载链接见: https://pan.baidu.com/s/19RXgEUVBci-QFavfMMNHFQ 提取码: nj8k。
image

2. 使用cfssl创建证书实操指南

用cfssl创建我们需要的证书文件的过程分一下3个步骤:

2.1 创建CA根证书及其私钥

根证书及其私钥,也即CA证书和CA证书的私钥,是集群所有节点共享的,只需要创建一个 CA 证书即其私钥,后续创建的所有证书都由它签名。CA根证书创建后一般命名是ca.pem。 CA更证书私钥创建后一般命名是ca-key.pem。

注意:

CA根证书及其私钥,只需要创建一次即可。后续其他证书都由它签名,CA根证书及其私钥一旦改变,其它证书也就无效了。

创建CA根证书及其私钥过程可依照以下2个步骤:

2.1.1 创建CA根证书签名请求文件ca-csr.json

注意ca-csr.json中csr含义是:Certificate Signing Request,证书签名请求,因此看到 xx-csr.json,你就要知道该文件是证书签名请求文件,有了它,cfssl就可以生成证书和证书私钥了。

ca-csr.json该如何配置呢? 其实很简单,下图是截取的cfssl官网上给出的一个xx-csr.json的示例:
image

对csr文件内容解释如下:

  • CN:Common Name,所有csr文件都必须有字段,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端证书则为证书申请者的姓名。
  • hosts: 网络请求url中的合法主机名或域名集合。

    下面给出2个hosts的例子:(都包含127.0.0.1,并且都使用的是域名或主机名,并且都预留了额外3个host名带extra字样的为预留host,以备后期扩容只用)

     "hosts":[
     "127.0.0.1",
     "baseserver1.online-etcd.freedom.org",
     "baseserver2.online-etcd.freedom.org",
     "baseserver3.online-etcd.freedom.org",
     "baseserver-extra1.online-etcd.freedom.org",
     "baseserver-extra2.online-etcd.freedom.org",
     "baseserver-extra3.online-etcd.freedom.org"
     ]
     "hosts":[
     "127.0.0.1",
     "cent7ax",
     "cent7bx",
     "cent7cx",
     "extra-cent7ax",
     "extra-cent7bx",
     "extra-cent7cx"
    ]

注意:

1) 超过该集合范围的任何请求都不会被支持认证通过。
2) CA根证书及其私钥创建过程不需要甚至该字段。其它服务证书创建必须有该字段。
3) hosts设置技巧:一般都把"127.0.0.1"包含进去;推荐使用域名或vip,尽量不要用ip地址,否则后期遇到某个服务所在机器宕机要重新更换某1台或多台机器时会面临证书认证不通过的毁灭性尴尬情况,导致扩容失败,集群服务面临毁灭性灾难。这里强烈推荐用域名或vip地址,另外,如果有条件,配置之处建议多预留1-3个host地址,防止后期扩容困难。
  • key: key字段是必须有的字段,其内容一般也比较固定就是:{"algo":"rsa”,"size":2048},表示使用的加密算法rsa,密文长度2048。
  • names字段:也是必须有字段,是证书对外公开显示的一些字段,常见的有如下:
C:   (Country)所在国家简称,只能是国家字母缩写,如中国:CN
L:  (Locality) 所在地区/城市简称,如Beijing/San Francisco
ST: (State/Provice)所在州/省份简称,如Beijing/California
O:  (Organization Name) 单位名称,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端单位证书则为证书申请者所在单位名称
OU: (other)显示其他内容,常见的内容值有“System"、"Website"等
电子邮件 (Email):    简称E 字段 
多个姓名字段 :        简称G 字段 
介绍Description :   介绍字段 
电话号码:            Phone 字段,格式要求 + 国家区号 城市区号 电话号码,如: +86 732 88888888 
地址:               STREET  字段 
邮政编码:            PostalCode 字段 
显示其他内容:        简称OU 字段

综合上述,最终我们生成的ca-csr.json如下图所示:

 {
    "CN":"etcd.freedom.com",
    "key":{
      "algo":"rsa",
      "size":2048
    },
    "names":[
      {
        "C":"CN",
        "ST":"BeiJing",
        "L":"BeiJing",
        "O":"etcd-op",
        "OU":"System"
      }
    ]
  }

根据该根证书签名请求文件就可以直接通过cfssl工具包生成CA根证书及其私钥了。

2.1.2 根据CA根证书签名请求文件生成CA根证书及其私钥

直接执行命令:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

注意:cfssljson -bare + 命名文件名,如本例中的ca,表示生成ca.pem和ca-key.pem,分别为证书和私钥文件。
image
生成的ca.pem是CA根证书文件,ca-key.pem是其私钥文件。其内容大体如下样式:
image
至此,CA根证书及其私钥文件已经生成,便可以用它们来签发其他认证文件了。

2.2 根据CA根证书及其私钥签名生成其它证书及其私钥

利用CA根证书及其私钥文件签发生成其它证书及其私钥,分为以下3个步骤执行操作:

2.2.1 创建CA根证书配置文件

CA根证书配置文件,一般命名为ca-config.json,它用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景 (profile)。

一个ca-config.json例子如下:

{
  "signing":{
    "default":{
      "expiry":"175200h"
    },
    "profiles":{
      "etcd-op":{
        "expiry":"175200h",
        "usages":[
          "signing",
          "key encipherment",
          "server auth",
          "client auth"
        ]
      }
    }
  }
}
expiry: 175200h表示20年有效期
profiles: 指定证书使用场景,下面的etcd-op是一个场景名称,后续签名生成证书及其私钥时需要指定该场景(profile)名称
signing:表示该证书可用于签名其它证书,生成的 ca.pem 证书中 CA=TRUE
server auth:表示 client 可以用该该证书对 server 提供的证书进行验证
client auth:表示 server 可以用该该证书对 client 提供的证书进行验证

2.2.2 创建目标证书签名请求文件

签名生成证书及其私钥,首先需要创建csr即证书签名请求文件,如下所示为一个csr证书签名请求文件的示例:

{
  "CN":"etcd.freedom.com",
  "key":{
    "algo":"rsa",
    "size":2048
  },
  "hosts":[
    "127.0.0.1",
    "cent7ax",
    "cent7bx",
    "cent7cx",
    "extra-cent7ax",
    "extra-cent7bx",
    "extra-cent7cx"
  ],
  "names":[
    {
      "C":"CN",
      "ST":"BeiJing",
      "L":"BeiJing",
      "O":"etcd-op",
      "OU":"System"
    }
  ]
}

将上述内容内存为签名请求文件,比如etcd-csr.json。

2.2.3 根据CA根证书及其私钥签名生成目标证书和私钥

执行命令:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd-op etcd-csr.json | cfssljson -bare etcd

image
如上图,其中的报错可以忽略。
image
上图所示为最终签名生成的证书及其私钥文件,其中etcd.pem为证书文件,etcd-key.pem为私钥文件。其格式大体与前文提及的ca.pem和ca-key.pem相同。都是一个证书文件,一个是私钥文件,二者配成生成。

2.3 校验证书

2.3.1 使用openssl命令校验证书

执行命令:

openssl x509  -noout -text -in  etcd.pem
[root@cent7ax cfssl_dir.bak]# openssl x509  -noout -text -in  etcd.pem 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            28:fd:f7:a1:e9:f2:03:0b:51:16:18:37:8f:64:46:a9:b6:72:95:67
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=BeiJing, L=BeiJing, O=etcd-op, OU=System, CN=etcd.freedom.com
        Validity
            Not Before: Nov 25 01:47:00 2020 GMT
            Not After : Nov 20 01:47:00 2040 GMT
        Subject: C=CN, ST=BeiJing, L=BeiJing, O=etcd-op, OU=System, CN=etcd.freedom.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ca:4f:a2:09:9f:12:7c:81:a8:09:4d:6f:c3:96:
                    c0:69:da:fc:9d:10:33:4c:2a:56:ba:06:20:3e:2f:
                    52:2f:15:36:a1:11:89:f7:98:56:b6:8f:38:85:82:
                    02:2c:ac:a8:b1:9e:71:6d:fe:e5:06:1f:a7:7a:3e:
                    9c:be:e2:9d:75:3e:69:1b:9e:06:eb:00:1b:74:60:
                    c3:6c:cc:f8:f4:c9:2c:12:d1:aa:2a:72:3f:5b:e0:
                    d0:45:57:f0:ad:88:6e:a0:59:c4:e4:5d:53:cb:6f:
                    ec:8e:fe:33:32:9f:99:ad:e6:3b:ca:ad:7d:4b:19:
                    8c:eb:7d:92:8e:8e:09:8b:a7:49:2a:1e:73:35:eb:
                    e3:59:4f:87:be:8d:12:cb:23:41:f5:34:bf:1a:4d:
                    04:c0:7c:70:99:8f:ce:51:ca:1c:7c:99:45:0e:b1:
                    d7:91:63:58:4c:a3:73:55:cb:d1:8e:eb:de:cd:5b:
                    89:35:30:4d:45:08:c6:09:de:e2:b0:de:56:aa:13:
                    ac:39:cb:e5:2d:06:06:24:63:fa:eb:c8:20:e0:b8:
                    bb:55:bf:d1:83:4a:9a:dc:2c:56:6c:16:7b:e3:06:
                    53:55:d8:d3:57:e3:82:09:3f:8b:91:1b:b8:68:d1:
                    0f:8f:98:4e:07:fc:94:65:69:6f:bd:59:a7:38:08:
                    79:27
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                F0:73:FD:7B:11:AF:96:CF:C7:BF:65:FE:BD:27:5C:39:44:D0:04:CC
            X509v3 Authority Key Identifier: 
                keyid:0F:D9:11:F9:9F:B8:72:B3:25:01:F2:3E:0A:D0:0E:7F:65:D2:91:0A

        X509v3 Subject Alternative Name: 
            DNS:cent7ax, DNS:cent7bx, DNS:cent7cx, DNS:extra-cent7ax, DNS:extra-cent7bx, DNS:extra-cent7cx, IP Address:127.0.0.1
Signature Algorithm: sha256WithRSAEncryption
     83:ce:62:56:62:1c:71:cd:9f:83:44:76:7a:7b:44:60:c2:6c:
     78:ff:91:62:6c:8e:39:61:d4:d3:f8:74:c0:71:65:c3:80:50:
     d1:2c:f3:d6:40:bc:1f:7e:3b:f6:e0:2c:82:4f:6b:8c:09:48:
     22:d7:ea:96:ba:94:99:72:9d:ae:c2:06:15:37:7f:9b:20:02:
     a7:d7:62:eb:7d:7e:93:53:5f:21:80:f8:b6:1c:8d:40:2f:09:
     75:16:db:3f:4e:01:22:d2:7d:a7:eb:e2:49:d6:06:7b:3c:07:
     1c:90:b0:ae:bc:9d:77:8b:a2:a9:5d:57:d9:1a:e8:0a:2a:1d:
     62:86:d8:dd:b8:9f:14:a4:cd:23:36:a9:c4:c6:40:ec:1a:58:
     f5:a1:6e:d3:37:7f:68:36:90:d5:9f:17:ea:a5:4d:47:71:89:
     5a:c9:bc:48:d2:77:54:e4:9e:cd:51:af:de:f2:d9:e4:53:95:
     46:07:a7:73:6a:8b:b1:e5:51:b5:fd:82:c1:73:1e:62:b6:0d:
     8b:30:e6:12:f2:11:d7:0b:97:2c:97:c3:b9:3b:be:31:4a:a3:
     89:18:8b:ed:76:95:67:e3:b5:53:f4:33:a1:0a:aa:1e:88:37:
     f2:f4:d2:56:18:0c:79:84:dd:7a:9a:2f:99:2f:e5:fa:f6:9a:
     d5:ea:09:b8
  • 确认 Issuer 字段的内容和 ca-csr.json 一致;
  • 确认 Subject 字段的内容和 etcd-csr.json 一致;
  • 确认 X509v3 Subject Alternative Name 字段的内容和 etcd-csr.json 一致;
  • 确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.jsonetcd-opprofile 一致;

2.3.2 使用cfssl-certinfo命令校验证书

执行命令:

cfssl-certinfo -cert etcd.pem
[root@cent7ax cfssl_dir.bak]# cfssl-certinfo -cert etcd.pem 
{
 "subject": {
 "common_name": "etcd.freedom.com",
 "country": "CN",
 "organization": "etcd-op",
 "organizational_unit": "System",
 "locality": "BeiJing",
 "province": "BeiJing",
 "names": [
 "CN",
 "BeiJing",
 "BeiJing",
 "etcd-op",
 "System",
 "etcd.freedom.com"
 ]
 },
 "issuer": {
 "common_name": "etcd.freedom.com",
 "country": "CN",
 "organization": "etcd-op",
 "organizational_unit": "System",
 "locality": "BeiJing",
 "province": "BeiJing",
 "names": [
 "CN",
 "BeiJing",
 "BeiJing",
 "etcd-op",
 "System",
 "etcd.freedom.com"
 ]
 },
 "serial_number": "234023291199234768277633047351258036366090605927",
 "sans": [
 "cent7ax",
 "cent7bx",
 "cent7cx",
 "extra-cent7ax",
 "extra-cent7bx",
 "extra-cent7cx",
 "127.0.0.1"
 ],
 "not_before": "2020-11-25T01:47:00Z",
 "not_after": "2040-11-20T01:47:00Z",
 "sigalg": "SHA256WithRSA",
 "authority_key_id": "F:D9:11:F9:9F:B8:72:B3:25:1:F2:3E:A:D0:E:7F:65:D2:91:A",
 "subject_key_id": "F0:73:FD:7B:11:AF:96:CF:C7:BF:65:FE:BD:27:5C:39:44:D0:4:CC",
 "pem": "-----BEGIN CERTIFICATE-----nMIIERjCCAy6gAwIBAgIUKP33oenyAwtRFhg3j2RGqbZylWcwDQYJKoZIhvcNAQELnBQAwbzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0JlnaUppbmcxEDAOBgNVBAoTB2V0Y2Qtb3AxDzANBgNVBAsTBlN5c3RlbTEZMBcGA1UEnAxMQZXRjZC5mcmVlZG9tLmNvbTAeFw0yMDExMjUwMTQ3MDBaFw00MDExMjAwMTQ3nMDBaMG8xCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlKaW5nMRAwDgYDVQQHEwdCnZWlKaW5nMRAwDgYDVQQKEwdldGNkLW9wMQ8wDQYDVQQLEwZTeXN0ZW0xGTAXBgNVnBAMTEGV0Y2QuZnJlZWRvbS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKnAoIBAQDKT6IJnxJ8gagJTW/DlsBp2vydEDNMKla6BiA+L1IvFTahEYn3mFa2jziFnggIsrKixnnFt/uUGH6d6Ppy+4p11PmkbngbrABt0YMNszPj0ySwS0aoqcj9b4NBFnV/CtiG6gWcTkXVPLb+yO/jMyn5mt5jvKrX1LGYzrfZKOjgmLp0kqHnM16+NZT4e+njRLLI0H1NL8aTQTAfHCZj85Ryhx8mUUOsdeRY1hMo3NVy9GO697NW4k1ME1FCMYJn3uKw3laqE6w5y+UtBgYkY/rryCDguLtVv9GDSprcLFZsFnvjBlNV2NNX44IJP4uRnG7ho0Q+PmE4H/JRlaW+9Wac4CHknAgMBAAGjgdkwgdYwDgYDVR0PAQH/BAQDAgWgnMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GnA1UdDgQWBBTwc/17Ea+Wz8e/Zf69J1w5RNAEzDAfBgNVHSMEGDAWgBQP2RH5n7hynsyUB8j4K0A5/ZdKRCjBXBgNVHREEUDBOggdjZW50N2F4ggdjZW50N2J4ggdjZW50nN2N4gg1leHRyYS1jZW50N2F4gg1leHRyYS1jZW50N2J4gg1leHRyYS1jZW50N2N4nhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCDzmJWYhxxzZ+DRHZ6e0Rgwmx4/5FinbI45YdTT+HTAcWXDgFDRLPPWQLwffjv24CyCT2uMCUgi1+qWupSZcp2uwgYVN3+bnIAKn12LrfX6TU18hgPi2HI1ALwl1Fts/TgEi0n2n6+JJ1gZ7PAcckLCuvJ13i6KpnXVfZGugKKh1ihtjduJ8UpM0jNqnExkDsGlj1oW7TN39oNpDVnxfqpU1HcYlaybxIn0ndU5J7NUa/e8tnkU5VGB6dzaoux5VG1/YLBcx5itg2LMOYS8hHXC5csl8O5O74xnSqOJGIvtdpVn47VT9DOhCqoeiDfy9NJWGAx5hN16mi+ZL+X69prV6gm4n-----END CERTIFICATE-----n"
}

2.4 分发证书

最后将上面签名生成的证书文件etcd.pem及其私钥文件etcd-key.pem 拷贝到集群所有需要的地方,即分发证书。典型使用场景有:

  • etcd-server集群的安装部署
  • grpc servers集群的安装部署
  • kubernetes集群的安装部署

等场景都需要使用证书认证。

阅读 5k

A programmer who loves life

137 声望
9 粉丝
0 条评论

A programmer who loves life

137 声望
9 粉丝
文章目录
宣传栏