Create TLS Certificates Using CFSSL
- Objective: Generate Certificate for TLS Using cfssl
- Prerequisite:
- None
- Optionality: Optional
- Estimated time: 30min
Introduction
This guide helps you create TLS certificates as well as Kubernetes Secrets. The two separate sets of TLS certificates created can be used for two purposes: 1) connections from MySQL-compatible clients to the TiDB service, and 2) connections between the components of the TiDB cluster. After creating the certificates and Secrets, follow the instructions for configuring security when you Deploy a TiDB Cluster.
TLS certificates can be issued by multiple methods. This document describes how to use CFSSL to issue certificates.
CFSSL is CloudFlare's PKI/TLS swiss army knife. It is both a command line tool and an HTTP API server for signing, verifying, and bundling TLS certificates.
Install CFSSL
You can install cfssl
and cfssljson
in the current directory, or into any directory already in your PATH for ease of use:
Linux
Your OS's package manager may have a package for
cfssl
. If not, manually install thecfssl
andcfssljson
to a location of your choice that is in your PATH:macOS
On macOS, it's easiest to use Homebrew to install CFSSL (this also installs
cfssljson
):
Verify the installation:
Usage:
Available commands:
version
ocsprefresh
scan
bundle
sign
selfsign
crl
gencert
ocspserve
info
genkey
ocspsign
gencsr
gencrl
ocspdump
print-defaults
revoke
certinfo
serve
Top-level flags:
If the cfssl
executable can't be found, add the directory where you downloaded it to your PATH variable:
Issue Certificate
Create Certificate Directory
Create a directory to hold all certificates. You can use any directory you like, as long as you cd
to it before executing the later commands in this document.
Note that the following operations are performed under ${certificate_path}
.
Configure Certificate Authority (CA)
A Certificate Authority (CA) is an entity that issues and signs digital certificates. A digital certificate certifies the ownership of a public key by the named subject of the certificate. This allows others (relying parties) to rely upon signatures or on assertions made about the private key that corresponds to the certified public key. A CA acts as a trusted third party—trusted both by the subject (owner) of the certificate and by the party relying upon the certificate. The format of these certificates is specified by the X.509 or EMV standard.
We first need to create and customize the ca-config.json
configuration file to define our CA.
Edit ca-config.json
to make modifications. The changes we need to make are:
- Change
sigining.default.expiry
to8760h
. - Change
sigining.profiles.www
toserver
. - Change
signing.profiles.server.usage
to addserver auth
andclient auth
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"server": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
},
"client": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
Note
We need to add
client auth
in profiles.server.usages, because this server-side certificate is also used as a client certificate
Next we need to configure the Certificate Signing Request (CSR):
We need to make some modifications to the CSR:
- Change the
CN
field toTIDB
. - Change the
key.algo
filed torsa
andkey.size
to2048
. - Change the names to the values below.
{
"CN": "TiDB",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "PingCAP",
"ST": "Beijing",
"OU": "TiDB"
}
]
}
Now generate the self-signed root CA certificate and private key:
2020/04/28 11:32:55 [INFO] generating a new CA key and certificate from CSR
2020/04/28 11:32:55 [INFO] generate received request
2020/04/28 11:32:55 [INFO] received CSR
2020/04/28 11:32:55 [INFO] generating key: rsa-2048
2020/04/28 11:32:55 [INFO] encoded CSR
2020/04/28 11:32:55 [INFO] signed certificate with serial number 312652930147915274584885165112010854762084891048
Troubleshooting
[WARNING] This certificate lacks a "hosts" field.
This is normal because we are not trying to provide web services.
Issue Certificates
We need to generate certificates for inter and intra component communication. In summary, we need to generate the following certificates:
- PD Server certificate for communicating between PD instances.
- TiKV Server certificate for communicating between TiKV instances.
- TiDB Server certificate for communicating between MySQL client and TiDB Cluster.
- Cluster Client certificate for communicating between components.
- Client certificate for communicating between MySQL client and TiDB Cluster.
Issue PD Server Certificate
Edit pd-server.json
to make modifications. The changes we need to make are:
- Change the
CN
field toTiDB
. - Change the
hosts
field to add the following. Note that the entries in hosts assumes the TiDB cluster name to bemy-cluster
and namespace to bepoc
. You need to make corresponding changes.
{
"CN": "TiDB",
"hosts": [
"127.0.0.1",
"::1",
"my-cluster-pd",
"my-cluster-pd.poc",
"my-cluster-pd.poc.svc",
"my-cluster-pd-peer",
"my-cluster-pd-peer.poc",
"my-cluster-pd-peer.poc.svc",
"*.my-cluster-pd-peer",
"*.my-cluster-pd-peer.poc",
"*.my-cluster-pd-peer.poc.svc"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "PingCAP",
"ST": "Beijing",
"OU": "TiDB"
}
]
}
We can then generate the PD Server certificate with the CA:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server pd-server.json | cfssljson -bare pd-server
2020/04/23 22:55:06 [INFO] generate received request
2020/04/23 22:55:06 [INFO] received CSR
2020/04/23 22:55:06 [INFO] generating key: rsa-2048
2020/04/23 22:55:07 [INFO] encoded CSR
2020/04/23 22:55:07 [INFO] signed certificate with serial number 214389999857155365314767437017019726628791998243
We can inspect the certificate using openssl
:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
42:a7:a6:4e:32:9a:42:5c:3f:a0:66:da:60:d0:82:d7:5d:ed:54:c7
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Beijing, L=CA, O=PingCAP, OU=TiDB, CN=TiDB
Validity
Not Before: Apr 25 03:27:00 2020 GMT
Not After : Apr 25 03:27:00 2021 GMT
Subject: C=US, ST=Beijing, L=CA, O=PingCAP, OU=TiDB, CN=TiDB
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:dc:f9:9f:74:ac:eb:2d:66:44:81:b2:ba:e4:f5:
71:a5:3b:b1:ef:0f:f8:d2:0f:26:9a:b8:6e:03:3b:
65:74:73:ea:a2:ae:0f:93:d8:6a:a9:a3:a5:7f:eb:
a1:10:76:43:1f:25:dd:2c:1f:f5:23:a1:43:6f:e9:
30:d8:d4:ac:e2:a3:53:08:28:82:dc:d1:bf:e8:59:
96:f8:3c:dd:a4:65:53:02:a6:ed:66:13:7d:16:10:
ad:ad:b3:f5:50:fd:fb:fb:74:cb:c3:b3:90:d7:b1:
0f:22:85:6d:13:2f:c0:7d:ee:8b:17:cd:75:82:ea:
16:db:ca:97:4c:6c:00:94:74:c2:da:07:48:6f:db:
90:75:19:58:54:16:de:08:bc:c5:a0:62:e7:f4:69:
4f:57:31:5f:e4:ce:ca:83:6d:84:dd:64:39:d8:1e:
04:e1:64:70:ec:f6:47:b3:22:d1:57:4f:bc:a9:4f:
54:b8:29:c9:8b:64:7a:96:90:3f:98:14:be:26:b1:
a3:7c:fa:a1:4d:df:9a:c5:e4:37:2a:2b:41:70:ae:
57:82:7f:89:a3:50:56:5e:80:82:e9:e4:09:7e:d8:
8f:4f:ab:03:87:09:af:f7:31:bc:0a:2a:20:6e:3a:
e5:a3:95:4d:f5:19:71:cc:6d:d3:a9:88:29:21:ba:
51:e1
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:
3C:29:6B:01:2D:98:59:D8:E5:A7:F0:10:7E:8F:41:E9:98:F1:F1:ED
X509v3 Subject Alternative Name:
DNS:my-cluster-pd, DNS:my-cluster-pd.poc, DNS:my-cluster-pd.poc.svc, DNS:my-cluster-pd-peer, DNS:my-cluster-pd-peer.poc, DNS:my-cluster-pd-peer.poc.svc, DNS:*.my-cluster-pd-peer, DNS:*.my-cluster-pd-peer.poc, DNS:*.my-cluster-pd-peer.poc.svc, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
Signature Algorithm: sha256WithRSAEncryption
94:cf:8f:af:15:b2:4d:de:64:8c:b0:58:dd:b8:ab:8d:99:48:
23:50:29:47:27:59:af:3c:f8:17:06:ba:a8:0b:be:30:03:b0:
c0:f2:60:1c:60:4c:cd:0a:bb:9b:3d:35:7c:43:74:87:1d:51:
6e:ed:d8:d4:fe:88:04:d9:95:58:4e:8d:40:92:6e:b8:84:13:
b3:c2:83:d7:dc:38:41:7b:ce:8a:99:6f:13:fb:eb:d4:a6:2e:
f7:80:75:71:8d:03:56:66:a6:d3:1c:f9:83:3e:76:b7:d3:68:
6b:46:fe:d5:9d:7b:e2:60:f9:d3:f5:40:fd:42:de:ed:b5:02:
3b:4f:15:87:25:fc:90:5d:2d:71:74:0b:b8:56:6b:bd:33:74:
8e:76:ce:54:83:a8:0a:1e:dc:60:f0:73:d0:a1:cf:01:00:c6:
2a:f4:8a:25:c2:d9:50:39:08:f2:8f:fb:21:6e:9a:9d:04:c6:
86:5a:b4:c9:c8:c4:66:a6:9d:5d:0d:66:2e:92:83:c9:62:8f:
21:cb:68:08:2d:8c:bb:bc:7d:39:c5:6c:04:a0:aa:bc:2c:0d:
6c:39:50:12:7d:37:a5:e3:ba:5e:09:2f:a7:07:67:68:3b:67:
6e:db:f6:f8:75:8e:1b:13:94:80:1d:f8:05:8a:2d:94:70:ea:
04:c7:09:8c
Issue TiKV Server certificate
Edit tikv-server.json
to make modifications. The changes we need to make are:
- Change the
CN
field toTiDB
. - Change the
hosts
field to add the following. - Note that the entries in hosts assumes the TiDB cluster name to be
my-cluster
and namespace to bepoc
. Change to match your deployment.
{
"CN": "TiDB",
"hosts": [
"127.0.0.1",
"::1",
"my-cluster-tikv",
"my-cluster-tikv.poc",
"my-cluster-tikv.poc.svc",
"my-cluster-tikv-peer",
"my-cluster-tikv-peer.poc",
"my-cluster-tikv-peer.poc.svc",
"*.my-cluster-tikv-peer",
"*.my-cluster-tikv-peer.poc",
"*.my-cluster-tikv-peer.poc.svc"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "PingCAP",
"ST": "Beijing",
"OU": "TiDB"
}
]
}
We can then generate the TiKV Server certificate with the CA:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server tikv-server.json | cfssljson -bare tikv-server
2020/04/28 12:55:42 [INFO] generate received request
2020/04/28 12:55:42 [INFO] received CSR
2020/04/28 12:55:42 [INFO] generating key: rsa-2048
2020/04/28 12:55:42 [INFO] encoded CSR
2020/04/28 12:55:42 [INFO] signed certificate with serial number 425207623158563460200719671690261814210346624866
We can inspect the certificate using openssl
:
Issue TiDB Server Certificate
Edit tidb-server.json
to make modifications. The changes we need to make are:
- Change the
CN
field toTiDB
. - Change the
hosts
field to add the following. - Note that the entries in hosts assumes the TiDB cluster name to be
my-cluster
and namespace to bepoc
. You need to make corresponding changes.
{
"CN": "TiDB",
"hosts": [
"127.0.0.1",
"::1",
"my-cluster-tidb",
"my-cluster-tidb.poc",
"my-cluster-tidb.poc.svc",
"*.my-cluster-tidb",
"*.my-cluster-tidb.poc",
"*.my-cluster-tidb.poc.svc"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "PingCAP",
"ST": "Beijing",
"OU": "TiDB"
}
]
}
We can then generate the TiDB Server certificate with the CA:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server tidb-server.json | cfssljson -bare tidb-server
2020/04/28 13:02:06 [INFO] generate received request
2020/04/28 13:02:06 [INFO] received CSR
2020/04/28 13:02:06 [INFO] generating key: rsa-2048
2020/04/28 13:02:07 [INFO] encoded CSR
2020/04/28 13:02:07 [INFO] signed certificate with serial number 677609381869553541316763926377530091236235435217
We can inspect the certificate using openssl
:
Issue Client Certificate
Edit client.json
to make modifications. The changes we need to make are:
- Change the
CN
field toTiDB
. - Change the
hosts
field to be empty.
{
"CN": "TiDB",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "PingCAP",
"ST": "Beijing",
"OU": "TiDB"
}
]
}
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
2020/04/28 13:18:12 [INFO] generate received request
2020/04/28 13:18:12 [INFO] received CSR
2020/04/28 13:18:12 [INFO] generating key: rsa-2048
2020/04/28 13:18:12 [INFO] encoded CSR
2020/04/28 13:18:12 [INFO] signed certificate with serial number 18096070442089977328487840082232485650921646783
2020/04/28 13:18:12 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
We can inspect the certificate using openssl
:
Create Kubernetes Secret
Before performing the operations, please ensure that a Kubernetes cluster (but not a TiDB cluster) is up and running, and that the following variables have been set:
cluster_name=my-cluster
namespace=poc
certificate_path=${certificate_path} # Already set from an earlier step
If you haven't yet created the namespace for your TiDB cluster, do so now:
Create Secret for TiDB Cluster Components
Create PD Server certificate
kubectl create secret generic ${cluster_name}-pd-cluster-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/pd-server.pem \
--from-file=tls.key=${certificate_path}/pd-server-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Create TiKV Server certificate
kubectl create secret generic ${cluster_name}-tikv-cluster-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/tikv-server.pem \
--from-file=tls.key=${certificate_path}/tikv-server-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Create TiDB Server certificate
kubectl create secret generic ${cluster_name}-tidb-cluster-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/tidb-server.pem \
--from-file=tls.key=${certificate_path}/tidb-server-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Create Cluster Client certificate
kubectl create secret generic ${cluster_name}-cluster-client-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/client.pem \
--from-file=tls.key=${certificate_path}/client-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Create Secret for MySQL Client and TiDB Cluster
Create Server certificate
kubectl create secret generic ${cluster_name}-tidb-server-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/tidb-server.pem \
--from-file=tls.key=${certificate_path}/tidb-server-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Create Client certificate
kubectl create secret generic ${cluster_name}-tidb-client-secret \
--namespace=${namespace} --from-file=tls.crt=${certificate_path}/client.pem \
--from-file=tls.key=${certificate_path}/client-key.pem \
--from-file=ca.crt=${certificate_path}/ca.pem
Note
If you want to be able to connect using TLS from an application in another Kubernetes namespace, you should also create a client secret in the application's namespace.
Verify that the secrets are created
NAME TYPE DATA AGE
my-cluster-cluster-client-secret Opaque 3 27s
my-cluster-pd-cluster-secret Opaque 3 51s
my-cluster-tidb-client-secret Opaque 3 14s
my-cluster-tidb-cluster-secret Opaque 3 33s
my-cluster-tidb-server-secret Opaque 3 20s
my-cluster-tikv-cluster-secret Opaque 3 44s
default-token-jwh9v kubernetes.io/service-account-token 3 56s
Comments
0 comments
Please sign in to leave a comment.