生成自签名证书
如果在公共网络之上构建Container Linux集群,则建议对 Linux容器服务启用加密,以防止流量拦截和中间人攻击。 为了达到这些目的,您必须使用由证书颁发机构(CA)签名的私钥和证书。 让我们使用cfssl介绍所有组件的创建过程。
注意:我们将在这里使用基本功能。 如果您需要更高级的安全选项品配置,请参阅官方的cfssl文档。
下载 cfssl
CloudFlare在github上发布了cfssl源代码和二进制文件。
我们的文档假设您将在x86_64 Linux主机上运行cfssl。
mkdir ~/bin
curl -s -L -o ~/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
curl -s -L -o ~/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x ~/bin/{cfssl,cfssljson}
export PATH=$PATH:~/bin
初始化证书颁发机构
首先,我们保存一份默认cfssl
配置选项来做修改:
mkdir ~/cfssl
cd ~/cfssl
cfssl print-defaults config > ca-config.json
cfssl print-defaults csr > ca-csr.json
Linux容器中使用的证书类型
- client certificate 用于通过服务器对客户端进行身份验证。 例如
etcdctl
,etcd proxy
,fleetctl
或docker
客户端。 - server certificate 由服务器使用并由客户机验证以用于服务器身份。 例如docker服务器或kube-apiserver。
- peer certificate 由etcd集群成员使用,他们之间相互通信。
配置CA选项
现在我们可以在ca-config.json
配置文件中配置签名选项。 默认选项包含以下预配置字段:
- profiles: www 与服务器认证(TLS Web服务器认证)X509 V3扩展和 client 与客户端认证(TLS Web客户端认证)X509 V3扩展。
- expiry: 默认是
8760h
(或 365天)
为了契合实际使用,我们将 www 重命名为 server, 除了 server auth
and client auth
以外再添加一项 peer 选项, 全部设置到期时间为 43800h (5 年):
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
你也可以修改证书签名请求文件 (CSR) ca-csr.json
:
{
"CN": "My own CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "My Company Name",
"ST": "San Francisco",
"OU": "Org Unit 1",
"OU": "Org Unit 2"
}
]
}
使用自定义的选项生成CA.:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
你将生成以下文件:
ca-key.pem
ca.csr
ca.pem
- 请保持
ca-key.pem
文件的安全。 此密钥允许在您的CA中创建任何种类的证书。 - *.csr 文件不在我们的例子中使用.
生成服务器证书
cfssl print-defaults csr > server.json
服务器证书最重要的值是 ** Common Name(CN)** 和 ** hosts **。 我们需要替换它们,例如:
...
"CN": "coreos1",
"hosts": [
"192.168.122.68",
"ext.example.com",
"coreos1.local",
"coreos1"
],
...
现在我们准备生成服务器证书和私钥:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server
或者不用 CSR json 文件去生成:
echo '{"CN":"coreos1","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server -hostname="192.168.122.68,ext.example.com,coreos1.local,coreos1" - | cfssljson -bare server
你会得到以下文件:
server-key.pem
server.csr
server.pem
生成对等证书
cfssl print-defaults csr > member1.json
替换 CN and hosts 值, 例如:
...
"CN": "member1",
"hosts": [
"192.168.122.101",
"ext.example.com",
"member1.local",
"member1"
],
...
现在我们去生成 member1 证书和私钥:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer member1.json | cfssljson -bare member1
或者不用 CSR json 文件去生成:
echo '{"CN":"member1","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer -hostname="192.168.122.101,ext.example.com,member1.local,member1" - | cfssljson -bare member1
你会得到以下文件:
member1-key.pem
member1.csr
member1.pem
==对每个etcd
成员主机名重复这些步骤。==
生成客户端证书
cfssl print-defaults csr > client.json
对于客户端证书,我们可以忽略 hosts 值,并且只将 Common Name(CN) 的值设置为 client:
...
"CN": "client",
"hosts": [""],
...
生成客户端证书:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
或者不用 CSR json 文件去生成:
echo '{"CN":"client","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client - | cfssljson -bare client
你将得到以下文件:
client-key.pem
client.csr
client.pem
TLDR(长话短说)
下载cfssl二进制文件
mkdir ~/bin
curl -s -L -o ~/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
curl -s -L -o ~/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x ~/bin/{cfssl,cfssljson}
export PATH=$PATH:~/bin
创建存储证书目录:
mkdir ~/cfssl
cd ~/cfssl
生成CA和证书
echo '{"CN":"CA","key":{"algo":"rsa","size":2048}}' | cfssl gencert -initca - | cfssljson -bare ca -
echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","server auth","client auth"]}}}' > ca-config.json
export ADDRESS=192.168.122.68,ext1.example.com,coreos1.local,coreos1
export NAME=server
echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME
export ADDRESS=
export NAME=client
echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME
验证数据
openssl x509 -in ca.pem -text -noout
openssl x509 -in server.pem -text -noout
openssl x509 -in client.pem -text -noout
注意事项
- 不要把
ca-key.pem
放到一个Linux容器配置文件中,建议把它保存在安全的地方。 这个密钥可以生成N多的证书。 - 保持 key 文件的安全。 不要忘记设置正确的文件权限,即
chmod 0600 server-key.pem
。 - 这个 TLDR 例子中的证书同时具有
server auth
和client auth
X509 V3扩展,您可以在服务器和客户端的身份验证中使用它们。 - 您可以自由地为通配符"*"地址生成密钥和证书。他们将在任何机器上工作。 它将简化证书程序,但会增加安全风险。
更多信息……
参考以下连接:
Custom Certificate Authorities
etcd Security Model