diff --git a/charts/tidb-cluster/templates/_helpers.tpl b/charts/tidb-cluster/templates/_helpers.tpl index 78439fd4aa..eaaced7add 100644 --- a/charts/tidb-cluster/templates/_helpers.tpl +++ b/charts/tidb-cluster/templates/_helpers.tpl @@ -91,7 +91,7 @@ config-file: |- {{- if .Values.tidb.config }} {{ .Values.tidb.config | indent 2 }} {{- end -}} - {{- if or .Values.enableTLSCluster .Values.tidb.enableTLSClient }} + {{- if or .Values.enableTLSCluster .Values.tidb.tlsClient.enabled }} [security] {{- end -}} {{- if .Values.enableTLSCluster }} @@ -99,8 +99,12 @@ config-file: |- cluster-ssl-cert = "/var/lib/tidb-tls/cert" cluster-ssl-key = "/var/lib/tidb-tls/key" {{- end -}} - {{- if .Values.tidb.enableTLSClient }} + {{- if .Values.tidb.tlsClient.enabled }} + {{- if .Values.tidb.tlsClient.secretName }} + ssl-ca = "/var/lib/tidb-server-tls/ca" + {{- else }} ssl-ca = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + {{- end }} ssl-cert = "/var/lib/tidb-server-tls/cert" ssl-key = "/var/lib/tidb-server-tls/key" {{- end -}} diff --git a/charts/tidb-cluster/templates/tidb-cluster.yaml b/charts/tidb-cluster/templates/tidb-cluster.yaml index d625d1ac69..3a94ea400b 100644 --- a/charts/tidb-cluster/templates/tidb-cluster.yaml +++ b/charts/tidb-cluster/templates/tidb-cluster.yaml @@ -92,18 +92,9 @@ spec: {{- end }} maxFailoverCount: {{ .Values.tikv.maxFailoverCount | default 3 }} tidb: - enableTLSClient: {{ .Values.tidb.enableTLSClient | default false }} - {{- if .Values.tidb.extraSANIPList }} - extraSANIPList: - {{- range .Values.tidb.extraSANIPList }} - - {{ . }} - {{- end }} - {{- end }} - {{- if .Values.tidb.extraSANDomainList }} - extraSANDomainList: - {{- range .Values.tidb.extraSANDomainList }} - - {{ . }} - {{- end }} + {{- if .Values.tidb.tlsClient }} + tlsClient: +{{ toYaml .Values.tidb.tlsClient | indent 6 }} {{- end }} replicas: {{ .Values.tidb.replicas }} image: {{ .Values.tidb.image }} diff --git a/charts/tidb-cluster/values.yaml b/charts/tidb-cluster/values.yaml index 253468e9fd..93b894711f 100644 --- a/charts/tidb-cluster/values.yaml +++ b/charts/tidb-cluster/values.yaml @@ -428,18 +428,26 @@ tidb: list: ["whitelist-1"] # Whether enable TLS connection between TiDB server and MySQL client. - # When enabled, TiDB will accept TLS encrypted connections from MySQL client, certificates will be generated - # automatically. # Note: TLS connection is not forced on the server side, plain connections are also accepted after enableing. - enableTLSClient: false - # # extra SAN IP list when you set tidb.enableTLSClient to true - # extraSANIPList: - # - 1.1.1.1 - # - 2.2.2.2 - # # extra SAN Domain List when you set tidb.enableTLSClient to true - # extraSANDomainList: - # - example1.com - # - example2.com + tlsClient: + # When enabled, TiDB will accept TLS encrypted connections from MySQL client + 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 --namespace= --from-file=cert= --from-file=key= --from-file=ca= + # 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 diff --git a/manifests/crd.yaml b/manifests/crd.yaml index cb174a7766..6200881614 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -3779,21 +3779,6 @@ spec: cluster-level updateStrategy if present Optional: Defaults to cluster-level setting' type: string - enableTLSClient: - description: 'Whether enable the TLS connection between the SQL - client and TiDB server Optional: Defaults to false' - type: boolean - extraSANDomainList: - description: extra SAN Domain list when setting EnableTLSClient - to true - items: - type: string - type: array - extraSANIPList: - description: extra SAN IP list when setting EnableTLSClient to true - items: - type: string - type: array hostNetwork: description: 'Whether Hostnetwork of the component is enabled. Override the cluster-level setting if present Optional: Defaults to cluster-level @@ -3988,6 +3973,7 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object type: object + tlsClient: {} tolerations: description: 'Tolerations of the component. Override the cluster-level tolerations if non-empty Optional: Defaults to cluster-level setting' diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index dabd175b7b..bf5e202ba5 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -3548,39 +3548,10 @@ func schema_pkg_apis_pingcap_v1alpha1_TiDBSpec(ref common.ReferenceCallback) com Format: "", }, }, - "enableTLSClient": { + "tlsClient": { SchemaProps: spec.SchemaProps{ - Description: "Whether enable the TLS connection between the SQL client and TiDB server Optional: Defaults to false", - Type: []string{"boolean"}, - Format: "", - }, - }, - "extraSANIPList": { - SchemaProps: spec.SchemaProps{ - Description: "extra SAN IP list when setting EnableTLSClient to true", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - "extraSANDomainList": { - SchemaProps: spec.SchemaProps{ - Description: "extra SAN Domain list when setting EnableTLSClient to true", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - }, + Description: "Whether enable the TLS connection between the SQL client and TiDB server Optional: Defaults to nil", + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBTLSClient"), }, }, "slowLogTailer": { @@ -3614,7 +3585,7 @@ func schema_pkg_apis_pingcap_v1alpha1_TiDBSpec(ref common.ReferenceCallback) com }, }, Dependencies: []string{ - "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBConfig", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBServiceSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBSlowLogTailerSpec", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBConfig", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBServiceSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBSlowLogTailerSpec", "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.TiDBTLSClient", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } diff --git a/pkg/apis/pingcap/v1alpha1/tidbcluster.go b/pkg/apis/pingcap/v1alpha1/tidbcluster.go index dc936c025f..67d8cf2e23 100644 --- a/pkg/apis/pingcap/v1alpha1/tidbcluster.go +++ b/pkg/apis/pingcap/v1alpha1/tidbcluster.go @@ -339,11 +339,11 @@ func (tc *TidbCluster) IsTiDBBinlogEnabled() bool { } func (tidb *TiDBSpec) IsTLSClientEnabled() bool { - enableTLSClient := tidb.EnableTLSClient - if enableTLSClient == nil { - return defaultEnableTLSClient - } - return *enableTLSClient + return tidb.TLSClient != nil && tidb.TLSClient.Enabled +} + +func (tidb *TiDBSpec) IsUserGeneratedCertificate() bool { + return tidb.IsTLSClientEnabled() && tidb.TLSClient.SecretName != "" } func (tidb *TiDBSpec) ShouldSeparateSlowLog() bool { diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 3e5ac3f278..1b2c134fbd 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -308,15 +308,9 @@ type TiDBSpec struct { SeparateSlowLog *bool `json:"separateSlowLog,omitempty"` // Whether enable the TLS connection between the SQL client and TiDB server - // Optional: Defaults to false + // Optional: Defaults to nil // +optional - EnableTLSClient *bool `json:"enableTLSClient,omitempty"` - - // extra SAN IP list when setting EnableTLSClient to true - ExtraSANIPList []string `json:"extraSANIPList,omitempty"` - - // extra SAN Domain list when setting EnableTLSClient to true - ExtraSANDomainList []string `json:"extraSANDomainList,omitempty"` + TLSClient *TiDBTLSClient `json:"tlsClient,omitempty"` // The spec of the slow log tailer sidecar // +optional @@ -602,6 +596,32 @@ type PumpStatus struct { StatefulSet *apps.StatefulSetStatus `json:"statefulSet,omitempty"` } +// 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 + // +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 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go index b45b2e3116..25aa9a0013 100644 --- a/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -2190,6 +2190,32 @@ func (in *TiDBAccessConfig) DeepCopy() *TiDBAccessConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TiDBAutoGeneratedCertificate) DeepCopyInto(out *TiDBAutoGeneratedCertificate) { + *out = *in + if in.ExtraSANIPList != nil { + in, out := &in.ExtraSANIPList, &out.ExtraSANIPList + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExtraSANDomainList != nil { + in, out := &in.ExtraSANDomainList, &out.ExtraSANDomainList + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TiDBAutoGeneratedCertificate. +func (in *TiDBAutoGeneratedCertificate) DeepCopy() *TiDBAutoGeneratedCertificate { + if in == nil { + return nil + } + out := new(TiDBAutoGeneratedCertificate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TiDBConfig) DeepCopyInto(out *TiDBConfig) { *out = *in @@ -2464,20 +2490,10 @@ func (in *TiDBSpec) DeepCopyInto(out *TiDBSpec) { *out = new(bool) **out = **in } - if in.EnableTLSClient != nil { - in, out := &in.EnableTLSClient, &out.EnableTLSClient - *out = new(bool) - **out = **in - } - if in.ExtraSANIPList != nil { - in, out := &in.ExtraSANIPList, &out.ExtraSANIPList - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.ExtraSANDomainList != nil { - in, out := &in.ExtraSANDomainList, &out.ExtraSANDomainList - *out = make([]string, len(*in)) - copy(*out, *in) + if in.TLSClient != nil { + in, out := &in.TLSClient, &out.TLSClient + *out = new(TiDBTLSClient) + (*in).DeepCopyInto(*out) } if in.SlowLogTailer != nil { in, out := &in.SlowLogTailer, &out.SlowLogTailer @@ -2542,6 +2558,27 @@ func (in *TiDBStatus) DeepCopy() *TiDBStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TiDBTLSClient) DeepCopyInto(out *TiDBTLSClient) { + *out = *in + if in.AutoGenerated != nil { + in, out := &in.AutoGenerated, &out.AutoGenerated + *out = new(TiDBAutoGeneratedCertificate) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TiDBTLSClient. +func (in *TiDBTLSClient) DeepCopy() *TiDBTLSClient { + if in == nil { + return nil + } + out := new(TiDBTLSClient) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TiKVBlockCacheConfig) DeepCopyInto(out *TiKVBlockCacheConfig) { *out = *in diff --git a/pkg/manager/member/tidb_member_manager.go b/pkg/manager/member/tidb_member_manager.go index f431dea865..58100034ef 100644 --- a/pkg/manager/member/tidb_member_manager.go +++ b/pkg/manager/member/tidb_member_manager.go @@ -108,12 +108,13 @@ func (tmm *tidbMemberManager) Sync(tc *v1alpha1.TidbCluster) error { return err } - // Sync Tidb StatefulSet - if err := tmm.syncTiDBStatefulSetForTidbCluster(tc); err != nil { + // Sync TiDB Service before syncing TiDB StatefulSet + if err := tmm.syncTiDBService(tc); err != nil { return err } - return tmm.syncTiDBService(tc) + // Sync TiDB StatefulSet + return tmm.syncTiDBStatefulSetForTidbCluster(tc) } func (tmm *tidbMemberManager) syncTiDBHeadlessServiceForTidbCluster(tc *v1alpha1.TidbCluster) error { @@ -181,7 +182,7 @@ func (tmm *tidbMemberManager) syncTiDBStatefulSetForTidbCluster(tc *v1alpha1.Tid return err } } - if tc.Spec.TiDB.IsTLSClientEnabled() { + if tc.Spec.TiDB.IsTLSClientEnabled() && !tc.Spec.TiDB.IsUserGeneratedCertificate() { err := tmm.syncTiDBServerCerts(tc) if err != nil { return err @@ -288,13 +289,15 @@ func (tmm *tidbMemberManager) syncTiDBServerCerts(tc *v1alpha1.TidbCluster) erro fmt.Sprintf("%s.%s.svc", svcName, ns), "localhost", } - hostList = append(hostList, tc.Spec.TiDB.ExtraSANDomainList...) - ipList := []string{ "127.0.0.1", "::1", svc.Spec.ClusterIP, } - ipList = append(ipList, tc.Spec.TiDB.ExtraSANIPList...) + + 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, @@ -434,7 +437,11 @@ func getTiDBConfigMap(tc *v1alpha1.TidbCluster) (*corev1.ConfigMap, error) { if config.Security == nil { config.Security = &v1alpha1.Security{} } - config.Security.SSLCA = pointer.StringPtr(serviceAccountCAPath) + if tc.Spec.TiDB.IsUserGeneratedCertificate() { + config.Security.SSLCA = pointer.StringPtr(path.Join(serverCertPath, "ca")) + } else { + config.Security.SSLCA = pointer.StringPtr(serviceAccountCAPath) + } config.Security.SSLCert = pointer.StringPtr(path.Join(serverCertPath, "cert")) config.Security.SSLKey = pointer.StringPtr(path.Join(serverCertPath, "key")) } @@ -622,10 +629,16 @@ 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") + } vols = append(vols, corev1.Volume{ Name: "tidb-server-tls", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: fmt.Sprintf("%s-%s", controller.TiDBMemberName(tcName), "server"), + SecretName: secretName, }, }, }) diff --git a/pkg/manager/member/tidb_member_manager_test.go b/pkg/manager/member/tidb_member_manager_test.go index a6b973d102..23a523992d 100644 --- a/pkg/manager/member/tidb_member_manager_test.go +++ b/pkg/manager/member/tidb_member_manager_test.go @@ -1617,8 +1617,8 @@ func TestGetTiDBConfigMap(t *testing.T) { ComponentSpec: v1alpha1.ComponentSpec{ ConfigUpdateStrategy: &updateStrategy, }, - EnableTLSClient: pointer.BoolPtr(true), - Config: &v1alpha1.TiDBConfig{}, + TLSClient: &v1alpha1.TiDBTLSClient{Enabled: true}, + Config: &v1alpha1.TiDBConfig{}, }, }, },