mirror of
https://github.com/mariadb-operator/mariadb-operator.git
synced 2025-08-08 06:35:58 +00:00
260 lines
8.3 KiB
Go
260 lines
8.3 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
mariadbv1alpha1 "github.com/mariadb-operator/mariadb-operator/v25/api/v1alpha1"
|
|
certctrl "github.com/mariadb-operator/mariadb-operator/v25/pkg/controller/certificate"
|
|
"github.com/mariadb-operator/mariadb-operator/v25/pkg/controller/secret"
|
|
"github.com/mariadb-operator/mariadb-operator/v25/pkg/hash"
|
|
"github.com/mariadb-operator/mariadb-operator/v25/pkg/metadata"
|
|
"github.com/mariadb-operator/mariadb-operator/v25/pkg/pki"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/utils/ptr"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
)
|
|
|
|
func (r *MaxScaleReconciler) reconcileTLS(ctx context.Context, req *requestMaxScale) (ctrl.Result, error) {
|
|
if !req.mxs.IsTLSEnabled() {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
if err := r.reconcileTLSCerts(ctx, req.mxs); err != nil {
|
|
return ctrl.Result{}, err
|
|
}
|
|
if err := r.reconcileTLSCABundle(ctx, req.mxs); err != nil {
|
|
return ctrl.Result{}, err
|
|
}
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
func (r *MaxScaleReconciler) reconcileTLSCerts(ctx context.Context, mxs *mariadbv1alpha1.MaxScale) error {
|
|
tls := ptr.Deref(mxs.Spec.TLS, mariadbv1alpha1.MaxScaleTLS{})
|
|
|
|
// MaxScale TLS can't communicate with a non-TLS MariaDB server
|
|
if tls.ServerCASecretRef == nil || tls.ServerCertSecretRef == nil {
|
|
return errors.New("'spec.tls.serverCASecretRef' and 'spec.tls.ServerCertSecretRef' fields" +
|
|
"must be set in order to communicate with MariaDB server")
|
|
}
|
|
|
|
adminCertOpts := []certctrl.CertReconcilerOpt{
|
|
certctrl.WithCABundle(mxs.TLSCABundleSecretKeyRef(), mxs.Namespace),
|
|
certctrl.WithCA(
|
|
tls.AdminCASecretRef == nil,
|
|
mxs.TLSAdminCASecretKey(),
|
|
),
|
|
certctrl.WithCert(
|
|
tls.AdminCertSecretRef == nil,
|
|
mxs.TLSAdminCertSecretKey(),
|
|
mxs.TLSAdminDNSNames(),
|
|
),
|
|
certctrl.WithServerCertKeyUsage(),
|
|
certctrl.WithCertIssuerRef(tls.AdminCertIssuerRef),
|
|
certctrl.WithRelatedObject(mxs),
|
|
}
|
|
if _, err := r.CertReconciler.Reconcile(ctx, adminCertOpts...); err != nil {
|
|
return fmt.Errorf("error reconciling admin cert: %v", err)
|
|
}
|
|
|
|
listenerCertOpts := []certctrl.CertReconcilerOpt{
|
|
certctrl.WithCABundle(mxs.TLSCABundleSecretKeyRef(), mxs.Namespace),
|
|
certctrl.WithCA(
|
|
tls.ListenerCASecretRef == nil,
|
|
mxs.TLSAdminCASecretKey(),
|
|
),
|
|
certctrl.WithCert(
|
|
tls.ListenerCertSecretRef == nil,
|
|
mxs.TLSListenerCertSecretKey(),
|
|
mxs.TLSListenerDNSNames(),
|
|
),
|
|
certctrl.WithServerCertKeyUsage(),
|
|
certctrl.WithCertIssuerRef(tls.ListenerCertIssuerRef),
|
|
certctrl.WithRelatedObject(mxs),
|
|
}
|
|
if _, err := r.CertReconciler.Reconcile(ctx, listenerCertOpts...); err != nil {
|
|
return fmt.Errorf("error reconciling listener cert: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *MaxScaleReconciler) reconcileTLSCABundle(ctx context.Context, mxs *mariadbv1alpha1.MaxScale) error {
|
|
logger := log.FromContext(ctx).WithName("ca-bundle")
|
|
|
|
caBundleKeySelector := mxs.TLSCABundleSecretKeyRef()
|
|
adminCAKeySelector := mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSAdminCASecretKey().Name,
|
|
},
|
|
Key: pki.CACertKey,
|
|
}
|
|
listenerCAKeySelector := mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSListenerCASecretKey().Name,
|
|
},
|
|
Key: pki.CACertKey,
|
|
}
|
|
serverCAKeySelector := mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSServerCASecretKey().Name,
|
|
},
|
|
Key: pki.CACertKey,
|
|
}
|
|
caKeySelectors := []mariadbv1alpha1.SecretKeySelector{
|
|
caBundleKeySelector,
|
|
adminCAKeySelector,
|
|
listenerCAKeySelector,
|
|
serverCAKeySelector,
|
|
}
|
|
var caBundles [][]byte
|
|
|
|
for _, caKeySelector := range caKeySelectors {
|
|
ca, err := r.RefResolver.SecretKeyRef(ctx, caKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
if !apierrors.IsNotFound(err) {
|
|
return fmt.Errorf("error getting CA Secret \"%s\": %v", caKeySelector.Name, err)
|
|
}
|
|
logger.V(1).Info("CA Secret not found", "secret-name", caKeySelector.Name)
|
|
}
|
|
caBundles = append(caBundles, []byte(ca))
|
|
}
|
|
|
|
bundle, err := pki.BundleCertificatePEMs(
|
|
caBundles,
|
|
pki.WithLogger(logger),
|
|
pki.WithSkipExpired(true),
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating CA bundle: %v", err)
|
|
}
|
|
|
|
secretReq := secret.SecretRequest{
|
|
Metadata: []*mariadbv1alpha1.Metadata{mxs.Spec.InheritMetadata},
|
|
Owner: mxs,
|
|
Key: types.NamespacedName{
|
|
Name: caBundleKeySelector.Name,
|
|
Namespace: mxs.Namespace,
|
|
},
|
|
Data: map[string][]byte{
|
|
caBundleKeySelector.Key: bundle,
|
|
},
|
|
}
|
|
return r.SecretReconciler.Reconcile(ctx, &secretReq)
|
|
}
|
|
|
|
func (r *MaxScaleReconciler) getTLSAnnotations(ctx context.Context, mxs *mariadbv1alpha1.MaxScale) (map[string]string, error) {
|
|
if !mxs.IsTLSEnabled() {
|
|
return nil, nil
|
|
}
|
|
annotations, err := r.getTLSAdminAnnotations(ctx, mxs)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting client annotations: %v", err)
|
|
}
|
|
|
|
secretSelectorsByAnn := map[string]mariadbv1alpha1.SecretKeySelector{
|
|
metadata.TLSListenerCertAnnotation: {
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSListenerCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
},
|
|
metadata.TLSServerCertAnnotation: {
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSServerCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
},
|
|
}
|
|
|
|
for annotation, secretKeySelector := range secretSelectorsByAnn {
|
|
cert, err := r.RefResolver.SecretKeyRef(ctx, secretKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting Secret \"%s\": %v", secretKeySelector.Name, err)
|
|
}
|
|
annotations[annotation] = hash.Hash(cert)
|
|
}
|
|
|
|
return annotations, nil
|
|
}
|
|
|
|
func (r *MaxScaleReconciler) getTLSAdminAnnotations(ctx context.Context, mxs *mariadbv1alpha1.MaxScale) (map[string]string, error) {
|
|
if !mxs.IsTLSEnabled() {
|
|
return nil, nil
|
|
}
|
|
annotations := make(map[string]string)
|
|
|
|
ca, err := r.RefResolver.SecretKeyRef(ctx, mxs.TLSCABundleSecretKeyRef(), mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting CA bundle: %v", err)
|
|
}
|
|
annotations[metadata.TLSCAAnnotation] = hash.Hash(ca)
|
|
|
|
adminCertKeySelector := mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSAdminCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
}
|
|
adminCert, err := r.RefResolver.SecretKeyRef(ctx, adminCertKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting admin cert: %v", err)
|
|
}
|
|
annotations[metadata.TLSAdminCertAnnotation] = hash.Hash(adminCert)
|
|
|
|
return annotations, nil
|
|
}
|
|
|
|
func (r *MaxScaleReconciler) getTLSStatus(ctx context.Context, mxs *mariadbv1alpha1.MaxScale) (*mariadbv1alpha1.MaxScaleTLSStatus, error) {
|
|
if !mxs.IsTLSEnabled() {
|
|
return nil, nil
|
|
}
|
|
var tlsStatus mariadbv1alpha1.MaxScaleTLSStatus
|
|
|
|
certStatus, err := getCertificateStatus(ctx, r.RefResolver, mxs.TLSCABundleSecretKeyRef(), mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting CA bundle status: %v", err)
|
|
}
|
|
tlsStatus.CABundle = certStatus
|
|
|
|
secretKeySelector := mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSAdminCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
}
|
|
certStatus, err = getCertificateStatus(ctx, r.RefResolver, secretKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting admin certificate status: %v", err)
|
|
}
|
|
tlsStatus.AdminCert = ptr.To(certStatus[0])
|
|
|
|
secretKeySelector = mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSListenerCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
}
|
|
certStatus, err = getCertificateStatus(ctx, r.RefResolver, secretKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting listener certificate status: %v", err)
|
|
}
|
|
tlsStatus.ListenerCert = ptr.To(certStatus[0])
|
|
|
|
secretKeySelector = mariadbv1alpha1.SecretKeySelector{
|
|
LocalObjectReference: mariadbv1alpha1.LocalObjectReference{
|
|
Name: mxs.TLSServerCertSecretKey().Name,
|
|
},
|
|
Key: pki.TLSCertKey,
|
|
}
|
|
certStatus, err = getCertificateStatus(ctx, r.RefResolver, secretKeySelector, mxs.Namespace)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting server certificate status: %v", err)
|
|
}
|
|
tlsStatus.ServerCert = ptr.To(certStatus[0])
|
|
|
|
return &tlsStatus, nil
|
|
}
|