Skip to content

Commit

Permalink
support common name check for tls (#934) (#937)
Browse files Browse the repository at this point in the history
  • Loading branch information
WangXiangUSTC authored Mar 20, 2020
1 parent b9a8759 commit a5b65c5
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 6 deletions.
2 changes: 2 additions & 0 deletions cmd/drainer/drainer.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ port = 3306
# ssl-cert = "/path/to/drainer.pem"
# Path of file that contains X509 key in PEM format.
# ssl-key = "/path/to/drainer-key.pem"
# The common name which is allowed to connection with cluster components.
# cert-allowed-cn = ["binlog"]

[syncer.to.checkpoint]
# only support mysql or tidb now, you can uncomment this to control where the checkpoint is saved.
Expand Down
2 changes: 2 additions & 0 deletions cmd/pump/pump.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pd-urls = "http://127.0.0.1:2379"
# ssl-cert = "/path/to/drainer.pem"
# Path of file that contains X509 key in PEM format for connection with cluster components.
# ssl-key = "/path/to/drainer-key.pem"
# The common name which is allowed to connection with cluster components.
# cert-allowed-cn = ["binlog"]
#
# [storage]
# Set to `true` (default) for best reliability, which prevents data loss when there is a power failure.
Expand Down
34 changes: 30 additions & 4 deletions pkg/security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"strings"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/config"
)

// Config is security config
type Config struct {
SSLCA string `toml:"ssl-ca" json:"ssl-ca"`
SSLCert string `toml:"ssl-cert" json:"ssl-cert"`
SSLKey string `toml:"ssl-key" json:"ssl-key"`
SSLCA string `toml:"ssl-ca" json:"ssl-ca"`
SSLCert string `toml:"ssl-cert" json:"ssl-cert"`
SSLKey string `toml:"ssl-key" json:"ssl-key"`
CertAllowedCN []string `toml:"cert-allowed-cn" json:"cert-allowed-cn"`
}

// ToTLSConfig generates tls's config based on security section of the config.
Expand All @@ -49,7 +51,8 @@ func (c *Config) ToTLSConfig() (tlsConfig *tls.Config, err error) {
}

tlsConfig = &tls.Config{
RootCAs: certPool,
RootCAs: certPool,
ClientCAs: certPool,
}

if len(c.SSLCert) != 0 && len(c.SSLKey) != 0 {
Expand All @@ -75,6 +78,29 @@ func (c *Config) ToTLSConfig() (tlsConfig *tls.Config, err error) {
}
}

if len(c.CertAllowedCN) != 0 {
checkCN := make(map[string]struct{})
for _, cn := range c.CertAllowedCN {
cn = strings.TrimSpace(cn)
checkCN[cn] = struct{}{}
}

tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert

tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
cns := make([]string, 0, len(verifiedChains))
for _, chains := range verifiedChains {
for _, chain := range chains {
cns = append(cns, chain.Subject.CommonName)
if _, match := checkCN[chain.Subject.CommonName]; match {
return nil
}
}
}
return errors.Errorf("client certificate authentication failed. The Common Name from the client certificate %v was not found in the configuration cluster-verify-cn with value: %s", cns, c.CertAllowedCN)
}
}

return
}

Expand Down
2 changes: 2 additions & 0 deletions tests/_utils/run_drainer
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ fi
ssl-ca = "$OUT_DIR/cert/ca.pem"
ssl-cert = "$OUT_DIR/cert/drainer.pem"
ssl-key = "$OUT_DIR/cert/drainer.key"
cert-allowed-cn = ["binlog"]
EOF

drainer -log-file $OUT_DIR/drainer.log -config "$OUT_DIR/drainer-config-tmp.toml" -pd-urls https://127.0.0.1:2379 -addr 0.0.0.0:8249 -advertise-addr 127.0.0.1:8249 -node-id drainer-id $* >> $OUT_DIR/drainer.log 2>&1
1 change: 1 addition & 0 deletions tests/_utils/run_pump
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ cat - > "$OUT_DIR/pump-config.toml" <<EOF
ssl-ca = "$OUT_DIR/cert/ca.pem"
ssl-cert = "$OUT_DIR/cert/pump.pem"
ssl-key = "$OUT_DIR/cert/pump.key"
cert-allowed-cn = ["binlog"]
EOF

BINLOG_TEST=1 pump -log-file $OUT_DIR/pump_$PORT.log --addr=0.0.0.0:$PORT \
Expand Down
4 changes: 2 additions & 2 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ DNS.1 = localhost
IP.1 = 127.0.0.1
EOF
openssl ecparam -out "$TT/ca.key" -name prime256v1 -genkey
openssl req -new -batch -sha256 -subj '/CN=localhost' -key "$TT/ca.key" -out "$TT/ca.csr"
openssl req -new -batch -sha256 -subj '/CN=binlog' -key "$TT/ca.key" -out "$TT/ca.csr"
openssl x509 -req -sha256 -days 2 -in "$TT/ca.csr" -signkey "$TT/ca.key" -out "$TT/ca.pem" 2> /dev/null

for name in tidb pd tikv pump drainer client; do
openssl ecparam -out "$TT/$name.key" -name prime256v1 -genkey
openssl req -new -batch -sha256 -subj '/CN=localhost' -key "$TT/$name.key" -out "$TT/$name.csr"
openssl req -new -batch -sha256 -subj '/CN=binlog' -key "$TT/$name.key" -out "$TT/$name.csr"
openssl x509 -req -sha256 -days 1 -extensions EXT -extfile "$TT/ipsan.cnf" -in "$TT/$name.csr" -CA "$TT/ca.pem" -CAkey "$TT/ca.key" -CAcreateserial -out "$TT/$name.pem" 2> /dev/null
done
}
Expand Down

0 comments on commit a5b65c5

Please sign in to comment.