Skip to content

Commit

Permalink
Handle shard scenario for MongoDB cert names (#574)
Browse files Browse the repository at this point in the history
Signed-off-by: Tamal Saha <tamal@appscode.com>
  • Loading branch information
tamalsaha committed Sep 1, 2020
1 parent d2c80e5 commit a219c25
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 14 deletions.
12 changes: 5 additions & 7 deletions apis/kubedb/v1alpha1/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ const (
ElasticsearchMetricsPort = 9600
ElasticsearchMetricsPortName = "metrics"

MongoDBShardPort = 27017
MongoDBConfigdbPort = 27017
MongoDBMongosPort = 27017
MongoDBKeyFileSecretSuffix = "key"
MongoDBPEMSecretSuffix = "pem"
MongoDBClientCertOrganization = DatabaseNamePrefix + ":client"
MongoDBCertificateCN = "root"
MongoDBShardPort = 27017
MongoDBConfigdbPort = 27017
MongoDBMongosPort = 27017
MongoDBKeyFileSecretSuffix = "key"
MongoDBRootUsername = "root"

MySQLMetricsExporterConfigSecretSuffix = "metrics-exporter-config"
MySQLNodePort = 3306
Expand Down
60 changes: 55 additions & 5 deletions apis/kubedb/v1alpha1/mongodb_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ func (m MongoDB) ServiceName() string {
// Governing Service Name. Here, name parameter is either
// OffshootName, ShardNodeName or ConfigSvrNodeName
func (m MongoDB) GvrSvcName(name string) string {
if name == "" {
panic(fmt.Sprintf("StatefulSet name is missing for MongoDB %s/%s", m.Namespace, m.Name))
}
return name + "-gvr"
}

Expand Down Expand Up @@ -418,9 +421,44 @@ func (m *MongoDB) setDefaultTLSConfig() {
if m.Spec.TLS == nil || m.Spec.TLS.IssuerRef == nil {
return
}
m.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert), m.CertificateName(MongoDBServerCert))
m.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(m.Spec.TLS.Certificates, string(MongoDBClientCert), m.CertificateName(MongoDBClientCert))
m.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(m.Spec.TLS.Certificates, string(MongoDBMetricsExporterCert), m.CertificateName(MongoDBMetricsExporterCert))

if m.Spec.ShardTopology != nil {
m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{
Alias: string(MongoDBServerCert),
SecretName: "",
Subject: &kmapi.X509Subject{
Organizations: []string{DatabaseNamePrefix},
OrganizationalUnits: []string{string(MongoDBServerCert)},
},
})
// reset secret name to empty string, since multiple secrets will be created for each StatefulSet.
m.Spec.TLS.Certificates = kmapi.SetSecretNameForCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert), "")
} else {
m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{
Alias: string(MongoDBServerCert),
SecretName: m.CertificateName(MongoDBServerCert, ""),
Subject: &kmapi.X509Subject{
Organizations: []string{DatabaseNamePrefix},
OrganizationalUnits: []string{string(MongoDBServerCert)},
},
})
}
m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{
Alias: string(MongoDBClientCert),
SecretName: m.CertificateName(MongoDBClientCert, ""),
Subject: &kmapi.X509Subject{
Organizations: []string{DatabaseNamePrefix},
OrganizationalUnits: []string{string(MongoDBClientCert)},
},
})
m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{
Alias: string(MongoDBMetricsExporterCert),
SecretName: m.CertificateName(MongoDBMetricsExporterCert, ""),
Subject: &kmapi.X509Subject{
Organizations: []string{DatabaseNamePrefix},
OrganizationalUnits: []string{string(MongoDBMetricsExporterCert)},
},
})
}

// setDefaultProbes sets defaults only when probe fields are nil.
Expand Down Expand Up @@ -579,17 +617,29 @@ func (m *MongoDB) KeyFileRequired() bool {
}

// CertificateName returns the default certificate name and/or certificate secret name for a certificate alias
func (m *MongoDB) CertificateName(alias MongoDBCertificateAlias) string {
func (m *MongoDB) CertificateName(alias MongoDBCertificateAlias, stsName string) string {
if m.Spec.ShardTopology != nil && alias == MongoDBServerCert {
if stsName == "" {
panic(fmt.Sprintf("StatefulSet name required to compute %s certificate name for MongoDB %s/%s", alias, m.Namespace, m.Name))
}
return meta_util.NameWithSuffix(m.Name, fmt.Sprintf("%s-cert", stsName))
}
return meta_util.NameWithSuffix(m.Name, fmt.Sprintf("%s-cert", string(alias)))
}

// MustCertSecretName returns the secret name for a certificate alias
func (m *MongoDB) MustCertSecretName(alias MongoDBCertificateAlias) string {
func (m *MongoDB) MustCertSecretName(alias MongoDBCertificateAlias, stsName string) string {
if m == nil {
panic("missing MongoDB database")
} else if m.Spec.TLS == nil {
panic(fmt.Errorf("MongoDB %s/%s is missing tls spec", m.Namespace, m.Name))
}
if m.Spec.ShardTopology != nil && alias == MongoDBServerCert {
if stsName == "" {
panic(fmt.Sprintf("StatefulSet name required to compute %s certificate name for MongoDB %s/%s", alias, m.Namespace, m.Name))
}
return m.CertificateName(alias, stsName)
}
name, ok := kmapi.GetCertificateSecretName(m.Spec.TLS.Certificates, string(alias))
if !ok {
panic(fmt.Errorf("MongoDB %s/%s is missing secret name for %s certificate", m.Namespace, m.Name, alias))
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
k8s.io/apimachinery v0.18.5
k8s.io/client-go v12.0.0+incompatible
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6
kmodules.xyz/client-go v0.0.0-20200818171030-24b2ce405feb
kmodules.xyz/client-go v0.0.0-20200901064306-0f1faee534af
kmodules.xyz/crd-schema-fuzz v0.0.0-20200521005638-2433a187de95
kmodules.xyz/custom-resources v0.0.0-20200604135349-9e9f5c4fdba9
kmodules.xyz/monitoring-agent-api v0.0.0-20200828051750-42aa8e7852f3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,8 @@ kmodules.xyz/client-go v0.0.0-20200524205059-e986bc44c91b/go.mod h1:sY/eoe4ktxZE
kmodules.xyz/client-go v0.0.0-20200525195850-2fd180961371/go.mod h1:sY/eoe4ktxZEoHpr5NpAQ5s22VSwTE8psJtKVeVgLRY=
kmodules.xyz/client-go v0.0.0-20200818171030-24b2ce405feb h1:0yIIoTfkhR4JAgx8UyXbP7oAveVAOcf66+D+20Uj/Uc=
kmodules.xyz/client-go v0.0.0-20200818171030-24b2ce405feb/go.mod h1:sY/eoe4ktxZEoHpr5NpAQ5s22VSwTE8psJtKVeVgLRY=
kmodules.xyz/client-go v0.0.0-20200901064306-0f1faee534af h1:Ly3rbfwRgQumrPnXVpdQsW2UqZiBpsEe40oik8AFNAY=
kmodules.xyz/client-go v0.0.0-20200901064306-0f1faee534af/go.mod h1:sY/eoe4ktxZEoHpr5NpAQ5s22VSwTE8psJtKVeVgLRY=
kmodules.xyz/constants v0.0.0-20200506032633-a21e58ceec72/go.mod h1:DbiFk1bJ1KEO94t1SlAn7tzc+Zz95rSXgyUKa2nzPmY=
kmodules.xyz/crd-schema-fuzz v0.0.0-20200521005638-2433a187de95 h1:v0S/+ftzL6Xrs9XevgchAOJyPKlRQXPiZf87xotj3X4=
kmodules.xyz/crd-schema-fuzz v0.0.0-20200521005638-2433a187de95/go.mod h1:jpu8xFsDKd6kAWUAKk8oTu/GQGBWqhrcaDeOJdaCJnk=
Expand Down
78 changes: 78 additions & 0 deletions vendor/kmodules.xyz/client-go/api/v1/certificates.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1

import (
"reflect"

"github.com/imdario/mergo"
core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
)

type TLSConfig struct {
Expand Down Expand Up @@ -133,6 +153,34 @@ func GetCertificateSecretName(certificates []CertificateSpec, alias string) (str
return cert.SecretName, cert.SecretName != ""
}

// SetMissingSpecForCertificate sets the missing spec fields for a certificate.
// If the certificate does not exist, it will add a new certificate with the desired spec.
func SetMissingSpecForCertificate(certificates []CertificateSpec, spec CertificateSpec) []CertificateSpec {
idx, _ := GetCertificate(certificates, spec.Alias)
if idx != -1 {
err := mergo.Merge(&certificates[idx], spec, mergo.WithTransformers(stringSetMerger{}))
if err != nil {
panic(err)
}
} else {
certificates = append(certificates, spec)
}
return certificates
}

// SetSpecForCertificate sets the spec for a certificate.
// If the certificate does not exist, it will add a new certificate with the desired spec.
// Otherwise, the spec will be overwritten.
func SetSpecForCertificate(certificates []CertificateSpec, spec CertificateSpec) []CertificateSpec {
idx, _ := GetCertificate(certificates, spec.Alias)
if idx != -1 {
certificates[idx] = spec
} else {
certificates = append(certificates, spec)
}
return certificates
}

// SetMissingSecretNameForCertificate sets the missing secret name for a certificate.
// If the certificate does not exist, it will add a new certificate with the desired secret name.
func SetMissingSecretNameForCertificate(certificates []CertificateSpec, alias, secretName string) []CertificateSpec {
Expand Down Expand Up @@ -175,3 +223,33 @@ func RemoveCertificate(certificates []CertificateSpec, alias string) []Certifica
}
return append(certificates[:idx], certificates[idx+1:]...)
}

type stringSetMerger struct {
}

func (t stringSetMerger) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ == reflect.TypeOf([]string{}) {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
if dst.Len() <= 1 && src.Len() == 0 {
return nil
}
if dst.Len() == 0 && src.Len() == 1 {
dst.Set(src)
return nil
}

out := sets.NewString()
for i := 0; i < dst.Len(); i++ {
out.Insert(dst.Index(i).String())
}
for i := 0; i < src.Len(); i++ {
out.Insert(src.Index(i).String())
}
dst.Set(reflect.ValueOf(out.List()))
}
return nil
}
}
return nil
}
11 changes: 11 additions & 0 deletions vendor/kmodules.xyz/client-go/api/v1/openapi_generated.go

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

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ k8s.io/utils/net
k8s.io/utils/path
k8s.io/utils/pointer
k8s.io/utils/trace
# kmodules.xyz/client-go v0.0.0-20200818171030-24b2ce405feb
# kmodules.xyz/client-go v0.0.0-20200901064306-0f1faee534af
kmodules.xyz/client-go
kmodules.xyz/client-go/api/v1
kmodules.xyz/client-go/apiextensions
Expand Down

0 comments on commit a219c25

Please sign in to comment.