etcd通过客户端证书支持SSL/TLS以及身份验证,客户端到服务器以及对等(服务器到服务器/群集)通信。
首先需要为一个成员拥有一个CA证书和一个已签名的密钥对。 建议为集群中的每个成员创建并签署一个新的密钥对。
为方便起见,cfssl工具提供了证书生成的简单接口,我们在此提供了一个使用该工具的示例。
您还可以检查此替代指南来生成自签名密钥对。
etcd通过命令行标志或环境变量来获取几个证书相关的配置选项:
--cert-file=<path>
: 用于SSL / TLS连接到etcd的证书。 设置此选项后,可以使用HTTPS模式设置advertise-client-url。--key-file=<path>
: 证书的密钥。 必须加密--client-cert-auth
: etcd将检查由受信任CA签名的客户端证书的所有传入HTTPS请求,否则不提供有效客户端证书的请求将失败。 如果启用身份验证,则证书将提供“公共名称”字段给出的用户名的凭据。--trusted-ca-file=<path>
: 受信任的证书颁发机构。对等选项的工作方式与客户端到服务器的选项相同:
--peer-cert-file = <path>
:用于在对等体之间进行SSL / TLS连接的证书。 这将用于侦听对等地址以及向其他对等体发送请求。--peer-key-file = <path>
:证书的密钥。 必须加密--peer-client-cert-auth
:当设置时,etcd将检查来自集群的所有传入对等体请求,以获得由提供的CA签名的有效客户端证书。--peer-trusted-ca-file = <path>
:受信任的证书颁发机构。如果提供了客户端到服务器或对等证书,则还必须设置密钥。 所有这些配置选项也可以通过环境变量ETCD_CA_FILE,ETCD_PEER_CA_FILE等来实现。
为此,您需要准备好CA证书(ca.crt)和签名密钥对(server.crt,server.key)。
让我们配置etcd一步一步提供简单的HTTPS传输安全:
(/path/to 放置我们准备的证书,如何自己生产证书查看博客 https 章节。)
$ etcd -name infra0 -data-dir infra0 \
-cert-file=/path/to/server.crt -key-file=/path/to/server.key \
-advertise-client-urls=https://127.0.0.1:2379 -listen-client-urls=https://127.0.0.1:2379
这个会启动一个etcd, 现在可以用HTTPS到etcd来测试配置:
curl --cacert /path/to/ca.crt https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
你应该可以看到握手成功。 因为我们使用自己的证书颁发机构使用自签名证书,所以您需要使用--cacert
选项提供CA证书。 另一种可能性是将您的CA证书添加到系统上的可信证书(通常在/etc/ssl/certs中)。
(下面这个不清楚怎么弄暂时没成功:)OSX 10.9+用户:OSX 10.9+上的7.30.0不了解在命令行中传递的证书。 相反,您必须将虚拟ca.crt直接导入钥匙串或添加-k标志来卷曲以忽略错误。 如果要测试没有-k标志运行打开./fixtures/ca/ca.crt并按照提示。 完成测试后请删除此证书! 。
现在我们给了etcd客户端验证服务器身份和提供传输安全性的能力。 然而,我们也可以使用客户端证书来防止未经授权的访问等等。
客户端将向服务器提供证书,服务器将检查证书是否由提供的CA签名,并决定是否提供请求。
您需要与第一个示例中提到的相同的文件,以及由同一证书颁发机构签名的客户机(client.crt,client.key)的密钥对。
$ etcd -name infra0 -data-dir infra0 \
-client-cert-auth -trusted-ca-file=/path/to/ca.crt -cert-file=/path/to/server.crt -key-file=/path/to/server.key \
-advertise-client-urls https://127.0.0.1:2379 -listen-client-urls https://127.0.0.1:2379
现在尝试与上面的服务器相同的请求:
curl --cacert /path/to/ca.crt https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
该请求应该被服务器拒绝:
...
routines:SSL3_READ_BYTES:sslv3 alert bad certificate
...
为了使其成功,我们需要将CA签名的客户端证书发送给服务器:
$ curl --cacert /path/to/ca.crt --cert /path/to/client.crt --key /path/to/client.key \
-L https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
你应该可以看到:
...
SSLv3, TLS handshake, CERT verify (15):
...
TLS handshake, Finished (20)
还有来自服务器的响应:
{
"action": "set",
"node": {
"createdIndex": 12,
"key": "/foo",
"modifiedIndex": 12,
"value": "bar"
}
}
etcd支持与上述相同的模式,用于对等通信,即表示群集中的其他成员之间的通信。
假设我们有ca.crt和两个成员,用这个CA签名的自己的keypairs(member1.crt&member1.key,member2.crt&member2.key),我们启动如下的etcd:
DISCOVERY_URL=... # from https://discovery.etcd.io/new
# member1
$ etcd -name infra1 -data-dir infra1 \
-peer-client-cert-auth -peer-trusted-ca-file=/path/to/ca.crt -peer-cert-file=/path/to/member1.crt -peer-key-file=/path/to/member1.key \
-initial-advertise-peer-urls=https://10.0.1.10:2380 -listen-peer-urls=https://10.0.1.10:2380 \
-discovery ${DISCOVERY_URL}
# member2
$ etcd -name infra2 -data-dir infra2 \
-peer-client-cert-auth -peer-trusted-ca-file=/path/to/ca.crt -peer-cert-file=/path/to/member2.crt -peer-key-file=/path/to/member2.key \
-initial-advertise-peer-urls=https://10.0.1.11:2380 -listen-peer-urls=https://10.0.1.11:2380 \
-discovery ${DISCOVERY_URL}
etcd成员将组成一个群集,群集中的成员之间的所有通信都将使用客户端证书进行加密和验证。 您将在etcd的输出中看到它连接的地址使用HTTPS。
如果连接是安全的,etcd代理从其客户端终止TLS,并且使用--peer-key-file
和--peer-cert-file
中指定的代理自己的密钥/ cert与etcd成员进行通信。
代理通过给定成员的--advertise-client-urls
和--advertise-peer-urls
与etcd成员进行通信。 它将客户端请求转发到etcd成员的广告客户端URL,并通过etcd成员的广告对等网址同步初始集群配置。
当为一个etcd成员启用客户端身份验证时,管理员必须确保代理的--peer-cert-file
选项中指定的对等证书对于该身份验证是有效的。 如果启用对等体身份验证,则代理的对等证书也必须对对等体身份验证有效。
etcd v2.0.x的内部协议使用了大量的短期HTTP连接。 因此,启用TLS时,您可能需要增加心跳间隔和选择超时,以减少内部群集连接流失。 合适的启动地点是:--heartbeat-interval 500 --election-timeout 2500
.这些问题在使用较少连接的etcd v2.1.x系列版本中解决。
golang的crypto/tls
包在使用它之前检查证书公钥的密钥用法。 要使用证书公钥进行客户端认证,我们需要在创建证书公钥时将clientAuth添加到扩展密钥使用。
这是怎么做到的:
将以下部分添加到openssl.cnf:
[ ssl_client ]
...
extendedKeyUsage = clientAuth
...
创建证书时,请务必在-extensions标志中引用它:
openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client -out certs/machine.crt -infiles machine.csr
请确保您使用主题名称签署您的证书,使其成员的公共IP地址。 例如,ford-ca工具为其new-cert命令提供了--ip =选项。
如果您需要在其主题名称中为您的会员的FQDN签名证书,则可以使用主题备用名称(短IP SAN)来添加您的IP地址。 etcd-ca工具为其new-cert命令提供了--domain =选项,openssl也可以做这个事情。