用 cfssl 生成 server/client/peer 所需要用的证书

why

之前写过一篇 openssl 生成证书的, 但是发现有 cfssl 可以更加简单清晰地来做这个事情.

证书分类

  1. client certificate: 用于服务端对客户端的认证, 如 etcdctl/docker client.
  2. server certificate: 服务端使用, 客户端以此验证服务端, 如 docker server/kube apiserver.
  3. peer certificate: 双向证书, 如 etcd 集群成员之间通信.

以下指南生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ tree
.
└── ssl
├── ca
│   ├── ca-config.json
│   ├── ca-csr.json
│   ├── ca-key.pem
│   ├── ca.csr
│   └── ca.pem
├── client
│   ├── client-key.pem
│   ├── client.csr
│   ├── client.json
│   └── client.pem
├── peer
│   ├── peer-key.pem
│   ├── peer.csr
│   ├── peer.json
│   └── peer.pem
└── server
├── server-key.pem
├── server.csr
├── server.json
└── server.pem

1. CA

1.1 默认 CA 配置

1
2
3
mkdir -p ssl/ca
cfssl print-defaults config > ssl/ca/ca-config.json
cfssl print-defaults csr > ssl/ca/ca-csr.json

1.2 修改 ssl/ca/ca-config.json

添加 .signing.profiles.peer.
2540400h 是 golang time.Duration 的最大值 290y

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
cat << 'EOF' > ssl/ca/ca-config.json 
{
"signing": {
"default": {
"expiry": "2540400h"
},
"profiles": {
"server": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF

1.3 生成 CA

1
cfssl gencert -initca ssl/ca/ca-csr.json | cfssljson -bare ssl/ca/ca -

2. Generate server certificate

2.1 server default csr

1
2
mkdir -p ssl/server
cfssl print-defaults csr > ssl/server/server.json

2.2 config csr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat << 'EOF' > ssl/server/server.json
{
"CN": "server1",
"hosts": [
"192.168.100.201",
"page.pikeszfish.me",
"www.pikeszfish.me"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"ST": "SH",
"L": "Shanghai"
}
]
}
EOF

2.3 sign it

1
cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=server ssl/server/server.json | cfssljson -bare ssl/server/server

3 Generate client certificate

3.1 client default csr

1
2
mkdir -p ssl/client
cfssl print-defaults csr > ssl/client/client.json

3.2 config csr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat << 'EOF' > ssl/client/client.json
{
"CN": "client",
"hosts": [],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"ST": "SH",
"L": "Shanghai"
}
]
}
EOF

3.3 sign it

1
cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=client ssl/client/client.json | cfssljson -bare ssl/client/client

4 Generate peer certificate

4.1 client default csr

1
2
mkdir -p ssl/peer1
cfssl print-defaults csr > ssl/peer1/peer1.json

4.2 config csr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat << 'EOF' > ssl/peer1/peer1.json
{
"CN": "peer1",
"hosts": [
"192.168.100.201",
"page.pikeszfish.me",
"www.pikeszfish.me"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"ST": "SH",
"L": "Shanghai"
}
]
}
EOF

4.3 sign it

1
cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=peer1 ssl/peer1/peer1.json | cfssljson -bare ssl/peer1/peer1

TL,DR

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
mkdir -p ssl/ca
cfssl print-defaults config > ssl/ca/ca-config.json
cfssl print-defaults csr > ssl/ca/ca-csr.json

cat << 'EOF' > ssl/ca/ca-config.json
{
"signing": {
"default": {
"expiry": "2540400h"
},
"profiles": {
"server": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "2540400h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF

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

mkdir -p ssl/server
cfssl print-defaults csr > ssl/server/server.json

cat << 'EOF' > ssl/server/server.json
{
"CN": "server1",
"hosts": [
"192.168.100.201",
"page.pikeszfish.me",
"www.pikeszfish.me"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"ST": "SH",
"L": "Shanghai"
}
]
}
EOF

cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=server ssl/server/server.json | cfssljson -bare ssl/server/server

mkdir -p ssl/client
cfssl print-defaults csr > ssl/client/client.json

cat << 'EOF' > ssl/client/client.json
{
"CN": "client",
"hosts": [],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"ST": "SH",
"L": "Shanghai"
}
]
}
EOF

cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=client ssl/client/client.json | cfssljson -bare ssl/client/client

mkdir -p ssl/peer
cfssl print-defaults csr > ssl/peer/peer.json

cat << 'EOF' > ssl/peer/peer.json
{
"CN": "example.net",
"hosts": [
"example.net",
"www.example.net"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"ST": "CA",
"L": "San Francisco"
}
]
}
EOF

cfssl gencert -ca=ssl/ca/ca.pem -ca-key=ssl/ca/ca-key.pem -config=ssl/ca/ca-config.json -profile=peer ssl/peer/peer.json | cfssljson -bare ssl/peer/peer