Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support common name check for tls #934

Merged
merged 2 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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