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

tls: Enable TLS For MySQL Clients #1867

Merged
merged 4 commits into from
Mar 6, 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
8 changes: 2 additions & 6 deletions charts/tidb-cluster/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,16 @@ config-file: |-
{{- if .Values.tidb.config }}
{{ .Values.tidb.config | indent 2 }}
{{- end -}}
{{- if or .Values.enableTLSCluster .Values.tidb.tlsClient.enabled }}
{{- if or .Values.enableTLSCluster (and .Values.tidb.tlsClient .Values.tidb.tlsClient.enabled) }}
[security]
{{- end -}}
{{- if .Values.enableTLSCluster }}
cluster-ssl-ca = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
cluster-ssl-cert = "/var/lib/tidb-tls/tls.crt"
cluster-ssl-key = "/var/lib/tidb-tls/tls.key"
{{- end -}}
{{- if .Values.tidb.tlsClient.enabled }}
{{- if .Values.tidb.tlsClient.secretName }}
{{- if and .Values.tidb.tlsClient .Values.tidb.tlsClient.enabled }}
ssl-ca = "/var/lib/tidb-server-tls/ca.crt"
{{- else }}
ssl-ca = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
{{- end }}
ssl-cert = "/var/lib/tidb-server-tls/tls.crt"
ssl-key = "/var/lib/tidb-server-tls/tls.key"
{{- end -}}
Expand Down
29 changes: 11 additions & 18 deletions charts/tidb-cluster/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -432,26 +432,19 @@ tidb:
list: ["whitelist-1"]

# Whether enable TLS connection between TiDB server and MySQL client.
# Note: TLS connection is not forced on the server side, plain connections are also accepted after enableing.
# https://pingcap.com/docs/stable/how-to/secure/enable-tls-clients/
tlsClient:
# When enabled, TiDB will accept TLS encrypted connections from MySQL client
# The steps to enable this feature:
# 1. Generate a TiDB server-side certificate and a client-side certifiacete for the TiDB cluster.
# There are multiple ways to generate certificates:
# - user-provided certificates: https://pingcap.com/docs/stable/how-to/secure/enable-tls-clients/
# - use the K8s built-in certificate signing system signed certificates: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/
# - or use cert-manager signed certificates: https://cert-manager.io/
# 2. Create a K8s Secret object which contains the TiDB server-side certificate created above.
# The name of this Secret must be: <clusterName>-tidb-server-secret.
# kubectl create secret generic <clusterName>-tidb-server-secret --namespace=<namespace> --from-file=tls.crt=<path/to/tls.crt> --from-file=tls.key=<path/to/tls.key> --from-file=ca.crt=<path/to/ca.crt>
# 3. Then create the TiDB cluster with `tlsClient.enabled` set to `true`.
enabled: false
# # secretName is the name of the secret that stores user-defined tidb server certificate, key and ca...
# # If not specified but tls client is enabled, certificated signed by k8s is created automatically.
# # Create this secret with the following command:
# # kubectl create secret generic <secret-name> --namespace=<namespace> --from-file=tls.crt=<tidb server certificate file path> --from-file=tls.key=<tidb server key file path> --from-file=ca.crt=<ca file path>
# secretName: "demo-tidb-server-secret"

# Auto-generated certificate in k8s: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/
# autoGenerated:
# # Extra SAN IP list
# extraSANIPList:
# - 1.1.1.1
# - 2.2.2.2
# # Extra SAN Domain list
# extraSANDomainList:
# - example1.com
# - example2.com

# mysqlClient is used to set password for TiDB
# it must has Python MySQL client installed
Expand Down
4 changes: 0 additions & 4 deletions pkg/apis/pingcap/v1alpha1/tidbcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,6 @@ func (tidb *TiDBSpec) IsAdvertiseAddressEnabled() bool {
return *tidb.EnableAdvertiseAddress
}

func (tidb *TiDBSpec) IsUserGeneratedCertificate() bool {
return tidb.IsTLSClientEnabled() && tidb.TLSClient.SecretName != ""
}

func (tidb *TiDBSpec) ShouldSeparateSlowLog() bool {
separateSlowLog := tidb.SeparateSlowLog
if separateSlowLog == nil {
Expand Down
29 changes: 10 additions & 19 deletions pkg/apis/pingcap/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,27 +604,18 @@ type PumpStatus struct {
// TiDBTLSClient can enable TLS connection between TiDB server and MySQL client
type TiDBTLSClient struct {
// When enabled, TiDB will accept TLS encrypted connections from MySQL client
// The steps to enable this feature:
// 1. Generate a TiDB server-side certificate and a client-side certifiacete for the TiDB cluster.
// There are multiple ways to generate certificates:
// - user-provided certificates: https://pingcap.com/docs/stable/how-to/secure/enable-tls-clients/
// - use the K8s built-in certificate signing system signed certificates: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/
// - or use cert-manager signed certificates: https://cert-manager.io/
// 2. Create a K8s Secret object which contains the TiDB server-side certificate created above.
// The name of this Secret must be: <clusterName>-tidb-server-secret.
// kubectl create secret generic <clusterName>-tidb-server-secret --namespace=<namespace> --from-file=tls.crt=<path/to/tls.crt> --from-file=tls.key=<path/to/tls.key> --from-file=ca.crt=<path/to/ca.crt>
// 3. Set Enabled to `true`.
// +optional
Enabled bool `json:"enabled,omitempty"`

// Secret name which stores user-defined TiDB Server certificate, key and ca
// +optional
SecretName string `json:"secretName,omitempty"`

// Auto-generated certificate
// +optional
AutoGenerated *TiDBAutoGeneratedCertificate `json:"autoGenerated,omitempty"`
}

// TiDBAutoGeneratedCertificate is TiDB auto-generated certificate
type TiDBAutoGeneratedCertificate struct {
// Extra SAN IP list
// +optional
ExtraSANIPList []string `json:"extraSANIPList,omitempty"`

// Extra SAN Domain list
// +optional
ExtraSANDomainList []string `json:"extraSANDomainList,omitempty"`
}

// +genclient
Expand Down
33 changes: 1 addition & 32 deletions pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 6 additions & 95 deletions pkg/manager/member/tidb_member_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,6 @@ func (tmm *tidbMemberManager) syncTiDBStatefulSetForTidbCluster(tc *v1alpha1.Tid
return err
}
}
if tc.Spec.TiDB.IsTLSClientEnabled() && !tc.Spec.TiDB.IsUserGeneratedCertificate() {
err := tmm.syncTiDBServerCerts(tc)
if err != nil {
return err
}
err = tmm.syncTiDBClientCerts(tc)
if err != nil {
return err
}
}
err = tmm.setControl.CreateStatefulSet(tc, newTiDBSet)
if err != nil {
return err
Expand Down Expand Up @@ -270,80 +260,6 @@ func (tmm *tidbMemberManager) syncTiDBClusterCerts(tc *v1alpha1.TidbCluster) err
return tmm.certControl.Create(controller.GetOwnerRef(tc), certOpts)
}

// syncTiDBServerCerts creates the cert pair for TiDB if not exist, the cert
// pair is used to communicate with DB clients with encrypted connections
func (tmm *tidbMemberManager) syncTiDBServerCerts(tc *v1alpha1.TidbCluster) error {
suffix := "tidb-server"
ns := tc.GetNamespace()
tcName := tc.GetName()
svcName := controller.TiDBMemberName(tcName)

if tmm.certControl.CheckSecret(ns, svcName) {
return nil
}

svc, err := tmm.svcLister.Services(ns).Get(svcName)
if err != nil {
return err
}

hostList := []string{
svcName,
fmt.Sprintf("%s.%s", svcName, ns),
fmt.Sprintf("%s.%s.svc", svcName, ns),
"localhost",
}
ipList := []string{
"127.0.0.1", "::1",
svc.Spec.ClusterIP,
}

if tc.Spec.TiDB.TLSClient.AutoGenerated != nil {
hostList = append(hostList, tc.Spec.TiDB.TLSClient.AutoGenerated.ExtraSANDomainList...)
ipList = append(ipList, tc.Spec.TiDB.TLSClient.AutoGenerated.ExtraSANIPList...)
}

certOpts := &controller.TiDBClusterCertOptions{
Namespace: ns,
Instance: tcName,
CommonName: svcName,
HostList: hostList,
IPList: ipList,
Component: "tidb",
Suffix: suffix,
}

return tmm.certControl.Create(controller.GetOwnerRef(tc), certOpts)
}

// syncTiDBClientCerts creates the cert pair for TiDB if not exist, the cert
// pair is used for DB clients to connect to TiDB server with encrypted connections
func (tmm *tidbMemberManager) syncTiDBClientCerts(tc *v1alpha1.TidbCluster) error {
suffix := "tidb-client"
ns := tc.GetNamespace()
tcName := tc.GetName()
commonName := fmt.Sprintf("%s-%s", tcName, suffix)

if tmm.certControl.CheckSecret(ns, commonName) {
return nil
}

hostList := []string{
commonName,
}

certOpts := &controller.TiDBClusterCertOptions{
Namespace: ns,
Instance: tcName,
CommonName: commonName,
HostList: hostList,
Component: "tidb",
Suffix: suffix,
}

return tmm.certControl.Create(controller.GetOwnerRef(tc), certOpts)
}

func (tmm *tidbMemberManager) syncTiDBService(tc *v1alpha1.TidbCluster) error {

newSvc := getNewTiDBServiceOrNil(tc)
Expand Down Expand Up @@ -441,11 +357,7 @@ func getTiDBConfigMap(tc *v1alpha1.TidbCluster) (*corev1.ConfigMap, error) {
if config.Security == nil {
config.Security = &v1alpha1.Security{}
}
if tc.Spec.TiDB.IsUserGeneratedCertificate() {
config.Security.SSLCA = pointer.StringPtr(path.Join(serverCertPath, tlsSecretRootCAKey))
} else {
config.Security.SSLCA = pointer.StringPtr(serviceAccountCAPath)
}
config.Security.SSLCA = pointer.StringPtr(path.Join(serverCertPath, tlsSecretRootCAKey))
config.Security.SSLCert = pointer.StringPtr(path.Join(serverCertPath, corev1.TLSCertKey))
config.Security.SSLKey = pointer.StringPtr(path.Join(serverCertPath, corev1.TLSPrivateKeyKey))
}
Expand Down Expand Up @@ -635,12 +547,7 @@ func getNewTiDBSetForTidbCluster(tc *v1alpha1.TidbCluster, cm *corev1.ConfigMap)
})
}
if tc.Spec.TiDB.IsTLSClientEnabled() {
var secretName string
if tc.Spec.TiDB.IsUserGeneratedCertificate() {
secretName = tc.Spec.TiDB.TLSClient.SecretName
} else {
secretName = fmt.Sprintf("%s-%s", controller.TiDBMemberName(tcName), "server")
}
secretName := tlsClientSecretName(tc)
vols = append(vols, corev1.Volume{
Name: "tidb-server-tls", VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
Expand Down Expand Up @@ -911,6 +818,10 @@ func tidbStatefulSetIsUpgrading(podLister corelisters.PodLister, set *apps.State
return false, nil
}

func tlsClientSecretName(tc *v1alpha1.TidbCluster) string {
return fmt.Sprintf("%s-server-secret", controller.TiDBMemberName(tc.Name))
}

type FakeTiDBMemberManager struct {
err error
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/manager/member/tidb_member_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1650,7 +1650,7 @@ func TestGetTiDBConfigMap(t *testing.T) {
Data: map[string]string{
"startup-script": "",
"config-file": `[security]
ssl-ca = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
ssl-ca = "/var/lib/tidb-server-tls/ca.crt"
ssl-cert = "/var/lib/tidb-server-tls/tls.crt"
ssl-key = "/var/lib/tidb-server-tls/tls.key"
cluster-ssl-ca = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
Expand Down