分类
devops

手工部署etcd单节点之安全篇

Table of Contents

本文介绍etcd单节点开启tls安全认证。

准备证书

cat > config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "876000h"
      },
      "client": {
        "usages": ["signing", "key encipherment", "client auth"],
        "expiry": "876000h"
      },
      "peer": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "876000h"
      }
    }
  }
}
EOF


cat > ca-csr.json <<EOF
{
  "CN": "root-ca",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "dyrnq"
    }
  ],
  "ca": {
    "expiry": "876000h"
 }
}
EOF

cat > server-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "172.17.0.2",
    "etcd",
    "etcd.default",
    "etcd.default.svc",
    "etcd.local"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "dyrnq"
    }
  ]
}
EOF
cat > client-csr.json <<EOF
{
  "CN": "etcd",
  "key": {
    "algo": "rsa",
    "size": 4096
  },
  "names": [
    {
      "O": "etcd"
    }
  ]
}
EOF

cat server-csr.json;

cfssl gencert -initca ca-csr.json | cfssljson -bare ca
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=config.json -profile=kubernetes server-csr.json | cfssljson -bare server
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=config.json -profile=client client-csr.json | cfssljson -bare client
root@31e6422c8769:/cert# tree
.
|-- ca-csr.json
|-- ca-key.pem
|-- ca.csr
|-- ca.pem
|-- client-csr.json
|-- client-key.pem
|-- client.csr
|-- client.pem
|-- config.json
|-- server-csr.json
|-- server-key.pem
|-- server.csr
`-- server.pem

0 directories, 13 files
mkdir -p /etc/etcd/certs;
cp *.pem /etc/etcd/certs;

单向

name: 'default'
data-dir: /opt/etcd-data
enable-v2: false
debug: false
logger: zap
log-outputs: [stderr]
listen-client-urls: https://0.0.0.0:2379
client-transport-security:
  cert-file: /etc/etcd/certs/server.pem
  key-file: /etc/etcd/certs/server-key.pem
  client-cert-auth: false
  trusted-ca-file:
  auto-tls: false

此时直接调用会报错

root@31e6422c8769:/# etcdctl --endpoints="172.17.0.2:2379" get foo
root@31e6422c8769:/# etcdctl --endpoints="172.17.0.2:2379" --debug get foo
ETCDCTL_CACERT=
ETCDCTL_CERT=
ETCDCTL_COMMAND_TIMEOUT=5s
ETCDCTL_DEBUG=true
ETCDCTL_DIAL_TIMEOUT=2s
ETCDCTL_DISCOVERY_SRV=
ETCDCTL_DISCOVERY_SRV_NAME=
ETCDCTL_ENDPOINTS=[172.17.0.2:2379]
ETCDCTL_HEX=false
ETCDCTL_INSECURE_DISCOVERY=true
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
ETCDCTL_INSECURE_TRANSPORT=true
ETCDCTL_KEEPALIVE_TIME=2s
ETCDCTL_KEEPALIVE_TIMEOUT=6s
ETCDCTL_KEY=
ETCDCTL_PASSWORD=
ETCDCTL_USER=
ETCDCTL_WRITE_OUT=simple
WARNING: 2020/12/29 12:35:57 Adjusting keepalive ping interval to minimum period of 10s
WARNING: 2020/12/29 12:35:57 Adjusting keepalive ping interval to minimum period of 10s
INFO: 2020/12/29 12:35:57 parsed scheme: "endpoint"
INFO: 2020/12/29 12:35:57 ccResolverWrapper: sending new addresses to cc: [{172.17.0.2:2379  <nil> 0 <nil>}]
INFO: 2020/12/29 12:35:57 transport: loopyWriter.run returning. connection error: desc = "transport is closing"
INFO: 2020/12/29 12:35:58 transport: loopyWriter.run returning. connection error: desc = "transport is closing"
INFO: 2020/12/29 12:36:00 transport: loopyWriter.run returning. connection error: desc = "transport is closing"
{"level":"warn","ts":"2020-12-29T12:36:02.513Z","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-46e7f0cd-47db-4283-948f-857aafc131b7/172.17.0.2:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: all SubConns are in TransientFailure, latest connection error: connection closed"}
Error: context deadline exceeded
{"level":"info","ts":"2020-12-29T12:38:50.285Z","caller":"embed/serve.go:191","msg":"serving client traffic securely","address":"[::]:2379"}
{"level":"warn","ts":"2020-12-29T12:38:53.204Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:43860","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:38:54.211Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:43902","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:38:55.904Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:43918","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:39:10.151Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:44040","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:39:11.167Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:44048","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:39:12.569Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:44054","server-name":"","error":"tls: client didn't provide a certificate"}
{"level":"warn","ts":"2020-12-29T12:39:14.846Z","caller":"embed/config_logging.go:279","msg":"rejected connection","remote-addr":"172.17.0.2:44110","server-name":"","error":"tls: client didn't provide a certificate"}

带上--cacert参数

root@31e6422c8769:/# etcdctl --endpoints="172.17.0.2:2379" --cacert=/etc/etcd/certs/ca.pem  get foo
foo
bar

双向

name: 'default'
data-dir: /opt/etcd-data
enable-v2: false
debug: false
logger: zap
log-outputs: [stderr]
listen-client-urls: https://0.0.0.0:2379
client-transport-security:
  cert-file: /etc/etcd/certs/server.pem
  key-file: /etc/etcd/certs/server-key.pem
  client-cert-auth: true
  trusted-ca-file: /etc/etcd/certs/ca.pem
  auto-tls: false
root@31e6422c8769:/# etcdctl --endpoints="172.17.0.2:2379" --cacert=/etc/etcd/certs/ca.pem --debug  get foo
ETCDCTL_CACERT=/etc/etcd/certs/ca.pem
ETCDCTL_CERT=
ETCDCTL_COMMAND_TIMEOUT=5s
ETCDCTL_DEBUG=true
ETCDCTL_DIAL_TIMEOUT=2s
ETCDCTL_DISCOVERY_SRV=
ETCDCTL_DISCOVERY_SRV_NAME=
ETCDCTL_ENDPOINTS=[172.17.0.2:2379]
ETCDCTL_HEX=false
ETCDCTL_INSECURE_DISCOVERY=true
ETCDCTL_INSECURE_SKIP_TLS_VERIFY=false
ETCDCTL_INSECURE_TRANSPORT=true
ETCDCTL_KEEPALIVE_TIME=2s
ETCDCTL_KEEPALIVE_TIMEOUT=6s
ETCDCTL_KEY=
ETCDCTL_PASSWORD=
ETCDCTL_USER=
ETCDCTL_WRITE_OUT=simple
WARNING: 2020/12/29 12:39:10 Adjusting keepalive ping interval to minimum period of 10s
WARNING: 2020/12/29 12:39:10 Adjusting keepalive ping interval to minimum period of 10s
INFO: 2020/12/29 12:39:10 parsed scheme: "endpoint"
INFO: 2020/12/29 12:39:10 ccResolverWrapper: sending new addresses to cc: [{172.17.0.2:2379  <nil> 0 <nil>}]
WARNING: 2020/12/29 12:39:10 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:10 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:11 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:11 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:12 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:12 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:14 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
WARNING: 2020/12/29 12:39:14 grpc: addrConn.createTransport failed to connect to {172.17.0.2:2379  <nil> 0 <nil>}. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
{"level":"warn","ts":"2020-12-29T12:39:15.143Z","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-8af2d4bb-3830-48dc-a457-42cdf934fce4/172.17.0.2:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: authentication handshake failed: remote error: tls: bad certificate\""}
Error: context deadline exceeded

这时候光带--cacert参数也会报错,得带上--cert--key参数

root@31e6422c8769:/# etcdctl --endpoints="172.17.0.2:2379" --cacert=/etc/etcd/certs/ca.pem --cert=/etc/etcd/certs/client.pem --key=/etc/etcd/certs/client-key.pem  get foo
foo
bar