github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/plan/tls_utils.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package plan 21 22 import ( 23 "bytes" 24 "context" 25 "strings" 26 "text/template" 27 28 "github.com/Masterminds/sprig/v3" 29 "github.com/pkg/errors" 30 v1 "k8s.io/api/core/v1" 31 "k8s.io/apimachinery/pkg/types" 32 33 dbaasv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 34 "github.com/1aal/kubeblocks/pkg/constant" 35 "github.com/1aal/kubeblocks/pkg/controller/builder" 36 client2 "github.com/1aal/kubeblocks/pkg/controller/client" 37 "github.com/1aal/kubeblocks/pkg/controller/factory" 38 ) 39 40 // ComposeTLSSecret composes a TSL secret object. 41 // REVIEW/TODO: 42 // 1. missing public function doc 43 // 2. should avoid using Go template to call a function, this is too hacky & costly, 44 // should just call underlying registered Go template function. 45 func ComposeTLSSecret(namespace, clusterName, componentName string) (*v1.Secret, error) { 46 name := GenerateTLSSecretName(clusterName, componentName) 47 secret := builder.NewSecretBuilder(namespace, name). 48 AddLabels(constant.AppInstanceLabelKey, clusterName). 49 AddLabels(constant.KBManagedByKey, constant.AppName). 50 SetStringData(map[string]string{}). 51 GetObject() 52 53 const tpl = `{{- $cert := genSelfSignedCert "KubeBlocks" nil nil 365 }} 54 {{ $cert.Cert }} 55 {{ $cert.Key }} 56 ` 57 out, err := buildFromTemplate(tpl, nil) 58 if err != nil { 59 return nil, err 60 } 61 index := strings.Index(out, "-----BEGIN RSA PRIVATE KEY-----") 62 if index < 0 { 63 return nil, errors.Errorf("wrong cert format: %s", out) 64 } 65 cert := out[:index] 66 key := out[index:] 67 secret.StringData[factory.CAName] = cert 68 secret.StringData[factory.CertName] = cert 69 secret.StringData[factory.KeyName] = key 70 return secret, nil 71 } 72 73 func GenerateTLSSecretName(clusterName, componentName string) string { 74 return clusterName + "-" + componentName + "-tls-certs" 75 } 76 77 func buildFromTemplate(tpl string, vars interface{}) (string, error) { 78 fmap := sprig.TxtFuncMap() 79 t := template.Must(template.New("tls").Funcs(fmap).Parse(tpl)) 80 var b bytes.Buffer 81 err := t.Execute(&b, vars) 82 if err != nil { 83 return "", err 84 } 85 return b.String(), nil 86 } 87 88 func CheckTLSSecretRef(ctx context.Context, cli client2.ReadonlyClient, namespace string, 89 secretRef *dbaasv1alpha1.TLSSecretRef) error { 90 if secretRef == nil { 91 return errors.New("issuer.secretRef shouldn't be nil when issuer is UserProvided") 92 } 93 94 secret := &v1.Secret{} 95 if err := cli.Get(ctx, types.NamespacedName{Namespace: namespace, Name: secretRef.Name}, secret); err != nil { 96 return err 97 } 98 if secret.StringData == nil { 99 return errors.New("tls secret's data field shouldn't be nil") 100 } 101 keys := []string{secretRef.CA, secretRef.Cert, secretRef.Key} 102 for _, key := range keys { 103 if _, ok := secret.StringData[key]; !ok { 104 return errors.Errorf("tls secret's data[%s] field shouldn't be empty", key) 105 } 106 } 107 return nil 108 } 109 110 func GetTLSKeyWord(cType string) string { 111 switch cType { 112 case "mysql": 113 return "ssl_cert" 114 case "postgresql": 115 return "ssl_cert_file" 116 case "redis": 117 return "tls-cert-file" 118 default: 119 return "unsupported-character-type" 120 } 121 }