Skip to content

Commit 2750f8e

Browse files
lmicciniopenshift-merge-bot[bot]
authored andcommitted
Enable MTLS memcached auth
This commit allows operators to use mtls as an authentication method against Memcached. Nova controllers will detect the presence of a purposely-created mtls certificate (authCertSecret) and use this to configure the [keystone_authtoken] section accordingly. Additional volumes/volumemounts will be appended to each pod. Note that this commit switches from MemcachedServersWithInet to MemcachedServers as keystone-middleware uses oslo.cache and as such there is no need to use "[]" to enclose the list of memcached servers even for ipv6.
1 parent e311f12 commit 2750f8e

28 files changed

+773
-30
lines changed

controllers/novaapi_controller.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ func (r *NovaAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) (re
333333
return result, err
334334
}
335335

336-
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations)
336+
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations, memcached)
337337
if (err != nil || result != ctrl.Result{}) {
338338
return result, err
339339
}
@@ -539,6 +539,13 @@ func (r *NovaAPIReconciler) generateConfigs(
539539
tlsCfg = &tls.Service{}
540540
}
541541

542+
// MTLS
543+
if memcachedInstance.GetMemcachedMTLSSecret() != "" {
544+
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
545+
templateParameters["MemcachedAuthKey"] = fmt.Sprint(memcachedv1.KeyMountPath())
546+
templateParameters["MemcachedAuthCa"] = fmt.Sprint(memcachedv1.CaMountPath())
547+
}
548+
542549
extraData := map[string]string{
543550
"my.cnf": apiDB.GetDatabaseClientConfig(tlsCfg), //(mschuppert) for now just get the default my.cnf
544551
}
@@ -567,6 +574,7 @@ func (r *NovaAPIReconciler) ensureDeployment(
567574
instance *novav1.NovaAPI,
568575
inputHash string,
569576
annotations map[string]string,
577+
memcached *memcachedv1.Memcached,
570578
) (ctrl.Result, error) {
571579
Log := r.GetLogger(ctx)
572580
serviceLabels := getAPIServiceLabels()
@@ -586,7 +594,7 @@ func (r *NovaAPIReconciler) ensureDeployment(
586594
return ctrl.Result{}, fmt.Errorf("waiting for Topology requirements: %w", err)
587595
}
588596

589-
ssSpec, err := novaapi.StatefulSet(instance, inputHash, serviceLabels, annotations, topology)
597+
ssSpec, err := novaapi.StatefulSet(instance, inputHash, serviceLabels, annotations, topology, memcached)
590598
if err != nil {
591599
instance.Status.Conditions.Set(condition.FalseCondition(
592600
condition.DeploymentReadyCondition,

controllers/novaconductor_controller.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,17 @@ func (r *NovaConductorReconciler) Reconcile(ctx context.Context, req ctrl.Reques
299299
return result, err
300300
}
301301

302-
result, err = r.ensureCellDBSynced(ctx, h, instance, serviceAnnotations)
302+
result, err = r.ensureCellDBSynced(ctx, h, instance, serviceAnnotations, memcached)
303303
if (err != nil || result != ctrl.Result{}) {
304304
return result, err
305305
}
306306

307-
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations)
307+
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations, memcached)
308308
if (err != nil || result != ctrl.Result{}) {
309309
return result, err
310310
}
311311

312-
err = r.ensureDBPurgeCronJob(ctx, h, instance, serviceAnnotations)
312+
err = r.ensureDBPurgeCronJob(ctx, h, instance, serviceAnnotations, memcached)
313313
if err != nil {
314314
return ctrl.Result{}, err
315315
}
@@ -486,6 +486,14 @@ func (r *NovaConductorReconciler) generateConfigs(
486486
if instance.Spec.TLS.CaBundleSecretName != "" {
487487
tlsCfg = &tls.Service{}
488488
}
489+
490+
// MTLS
491+
if memcachedInstance.GetMemcachedMTLSSecret() != "" {
492+
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
493+
templateParameters["MemcachedAuthKey"] = fmt.Sprint(memcachedv1.KeyMountPath())
494+
templateParameters["MemcachedAuthCa"] = fmt.Sprint(memcachedv1.CaMountPath())
495+
}
496+
489497
extraData := map[string]string{
490498
"my.cnf": cellDB.GetDatabaseClientConfig(tlsCfg), //(mschuppert) for now just get the default my.cnf
491499
}
@@ -506,13 +514,15 @@ func (r *NovaConductorReconciler) ensureCellDBSynced(
506514
h *helper.Helper,
507515
instance *novav1.NovaConductor,
508516
annotations map[string]string,
517+
memcached *memcachedv1.Memcached,
509518
) (ctrl.Result, error) {
510519
serviceLabels := map[string]string{
511520
common.AppSelector: NovaConductorLabelPrefix,
512521
}
513522
Log := r.GetLogger(ctx)
514523
dbSyncHash := instance.Status.Hash[DbSyncHash]
515-
jobDef := novaconductor.CellDBSyncJob(instance, serviceLabels, annotations)
524+
525+
jobDef := novaconductor.CellDBSyncJob(instance, serviceLabels, annotations, memcached)
516526
dbSyncJob := job.NewJob(jobDef, "dbsync", instance.Spec.PreserveJobs, r.RequeueTimeout, dbSyncHash)
517527
ctrlResult, err := dbSyncJob.DoJob(ctx, h)
518528
if (ctrlResult != ctrl.Result{}) {
@@ -547,6 +557,7 @@ func (r *NovaConductorReconciler) ensureDeployment(
547557
instance *novav1.NovaConductor,
548558
inputHash string,
549559
annotations map[string]string,
560+
memcached *memcachedv1.Memcached,
550561
) (ctrl.Result, error) {
551562
serviceLabels := map[string]string{
552563
common.AppSelector: NovaConductorLabelPrefix,
@@ -569,7 +580,7 @@ func (r *NovaConductorReconciler) ensureDeployment(
569580
return ctrl.Result{}, fmt.Errorf("waiting for Topology requirements: %w", err)
570581
}
571582

572-
ss := statefulset.NewStatefulSet(novaconductor.StatefulSet(instance, inputHash, serviceLabels, annotations, topology), r.RequeueTimeout)
583+
ss := statefulset.NewStatefulSet(novaconductor.StatefulSet(instance, inputHash, serviceLabels, annotations, topology, memcached), r.RequeueTimeout)
573584
ctrlResult, err := ss.CreateOrPatch(ctx, h)
574585
if err != nil && !k8s_errors.IsNotFound(err) {
575586
Log.Error(err, "Deployment failed")
@@ -642,11 +653,13 @@ func (r *NovaConductorReconciler) ensureDBPurgeCronJob(
642653
h *helper.Helper,
643654
instance *novav1.NovaConductor,
644655
annotations map[string]string,
656+
memcached *memcachedv1.Memcached,
645657
) error {
646658
serviceLabels := map[string]string{
647659
common.AppSelector: NovaConductorLabelPrefix,
648660
}
649-
cronDef := novaconductor.DBPurgeCronJob(instance, serviceLabels, annotations)
661+
662+
cronDef := novaconductor.DBPurgeCronJob(instance, serviceLabels, annotations, memcached)
650663
cronjob := cronjob.NewCronJob(cronDef, r.RequeueTimeout)
651664

652665
_, err := cronjob.CreateOrPatch(ctx, h)

controllers/novametadata_controller.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ func (r *NovaMetadataReconciler) Reconcile(ctx context.Context, req ctrl.Request
326326
return result, err
327327
}
328328

329-
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations)
329+
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations, memcached)
330330
if (err != nil || result != ctrl.Result{}) {
331331
return result, err
332332
}
@@ -545,6 +545,14 @@ func (r *NovaMetadataReconciler) generateConfigs(
545545
if instance.Spec.TLS.CaBundleSecretName != "" {
546546
tlsCfg = &tls.Service{}
547547
}
548+
549+
// MTLS
550+
if memcachedInstance.GetMemcachedMTLSSecret() != "" {
551+
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
552+
templateParameters["MemcachedAuthKey"] = fmt.Sprint(memcachedv1.KeyMountPath())
553+
templateParameters["MemcachedAuthCa"] = fmt.Sprint(memcachedv1.CaMountPath())
554+
}
555+
548556
extraData := map[string]string{
549557
"my.cnf": db.GetDatabaseClientConfig(tlsCfg), //(mschuppert) for now just get the default my.cnf
550558
}
@@ -572,6 +580,7 @@ func (r *NovaMetadataReconciler) ensureDeployment(
572580
instance *novav1.NovaMetadata,
573581
inputHash string,
574582
annotations map[string]string,
583+
memcached *memcachedv1.Memcached,
575584
) (ctrl.Result, error) {
576585
Log := r.GetLogger(ctx)
577586
serviceLabels := getMetadataServiceLabels(instance.Spec.CellName)
@@ -591,7 +600,7 @@ func (r *NovaMetadataReconciler) ensureDeployment(
591600
return ctrl.Result{}, fmt.Errorf("waiting for Topology requirements: %w", err)
592601
}
593602

594-
ssSpec, err := novametadata.StatefulSet(instance, inputHash, serviceLabels, annotations, topology)
603+
ssSpec, err := novametadata.StatefulSet(instance, inputHash, serviceLabels, annotations, topology, memcached)
595604
if err != nil {
596605
Log.Error(err, "Deployment failed")
597606
instance.Status.Conditions.Set(condition.FalseCondition(

controllers/novanovncproxy_controller.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ func (r *NovaNoVNCProxyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
345345
return result, err
346346
}
347347

348-
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations)
348+
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations, memcached)
349349
if (err != nil || result != ctrl.Result{}) {
350350
return result, err
351351
}
@@ -499,6 +499,14 @@ func (r *NovaNoVNCProxyReconciler) generateConfigs(
499499
if instance.Spec.TLS.CaBundleSecretName != "" {
500500
tlsCfg = &tls.Service{}
501501
}
502+
503+
// MTLS
504+
if memcachedInstance.GetMemcachedMTLSSecret() != "" {
505+
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
506+
templateParameters["MemcachedAuthKey"] = fmt.Sprint(memcachedv1.KeyMountPath())
507+
templateParameters["MemcachedAuthCa"] = fmt.Sprint(memcachedv1.CaMountPath())
508+
}
509+
502510
extraData := map[string]string{
503511
"my.cnf": cellDB.GetDatabaseClientConfig(tlsCfg), //(mschuppert) for now just get the default my.cnf
504512
}
@@ -523,6 +531,7 @@ func (r *NovaNoVNCProxyReconciler) ensureDeployment(
523531
instance *novav1.NovaNoVNCProxy,
524532
inputHash string,
525533
annotations map[string]string,
534+
memcached *memcachedv1.Memcached,
526535
) (ctrl.Result, error) {
527536
Log := r.GetLogger(ctx)
528537
serviceLabels := getNoVNCProxyServiceLabels(instance.Spec.CellName)
@@ -542,7 +551,7 @@ func (r *NovaNoVNCProxyReconciler) ensureDeployment(
542551
return ctrl.Result{}, fmt.Errorf("waiting for Topology requirements: %w", err)
543552
}
544553

545-
ssSpec, err := novncproxy.StatefulSet(instance, inputHash, serviceLabels, annotations, topology)
554+
ssSpec, err := novncproxy.StatefulSet(instance, inputHash, serviceLabels, annotations, topology, memcached)
546555
if err != nil {
547556
Log.Info("Deployment failed")
548557
instance.Status.Conditions.Set(condition.FalseCondition(

controllers/novascheduler_controller.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func (r *NovaSchedulerReconciler) Reconcile(ctx context.Context, req ctrl.Reques
309309
return result, err
310310
}
311311

312-
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations)
312+
result, err = r.ensureDeployment(ctx, h, instance, inputHash, serviceAnnotations, memcached)
313313
if (err != nil || result != ctrl.Result{}) {
314314
return result, err
315315
}
@@ -605,6 +605,14 @@ func (r *NovaSchedulerReconciler) generateConfigs(
605605
if instance.Spec.TLS.CaBundleSecretName != "" {
606606
tlsCfg = &tls.Service{}
607607
}
608+
609+
// MTLS
610+
if memcachedInstance.GetMemcachedMTLSSecret() != "" {
611+
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
612+
templateParameters["MemcachedAuthKey"] = fmt.Sprint(memcachedv1.KeyMountPath())
613+
templateParameters["MemcachedAuthCa"] = fmt.Sprint(memcachedv1.CaMountPath())
614+
}
615+
608616
extraData := map[string]string{
609617
"my.cnf": apiDB.GetDatabaseClientConfig(tlsCfg), //(mschuppert) for now just get the default my.cnf
610618
}
@@ -656,6 +664,7 @@ func (r *NovaSchedulerReconciler) ensureDeployment(
656664
instance *novav1.NovaScheduler,
657665
inputHash string,
658666
annotations map[string]string,
667+
memcached *memcachedv1.Memcached,
659668
) (ctrl.Result, error) {
660669
serviceLabels := map[string]string{
661670
common.AppSelector: NovaSchedulerLabelPrefix,
@@ -677,7 +686,7 @@ func (r *NovaSchedulerReconciler) ensureDeployment(
677686
return ctrl.Result{}, fmt.Errorf("waiting for Topology requirements: %w", err)
678687
}
679688

680-
ss := statefulset.NewStatefulSet(novascheduler.StatefulSet(instance, inputHash, serviceLabels, annotations, topology), r.RequeueTimeout)
689+
ss := statefulset.NewStatefulSet(novascheduler.StatefulSet(instance, inputHash, serviceLabels, annotations, topology, memcached), r.RequeueTimeout)
681690
ctrlResult, err := ss.CreateOrPatch(ctx, h)
682691
if err != nil && !k8s_errors.IsNotFound(err) {
683692
Log.Error(err, "Deployment failed")

pkg/novaapi/deployment.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package novaapi
1818

1919
import (
20+
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
2021
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2122
common "github.com/openstack-k8s-operators/lib-common/modules/common"
2223
affinity "github.com/openstack-k8s-operators/lib-common/modules/common/affinity"
@@ -40,6 +41,7 @@ func StatefulSet(
4041
labels map[string]string,
4142
annotations map[string]string,
4243
topology *topologyv1.Topology,
44+
memcached *memcachedv1.Memcached,
4345
) (*appsv1.StatefulSet, error) {
4446
// This allows the pod to start up slowly. The pod will only be killed
4547
// if it does not succeed a probe in 60 seconds.
@@ -102,6 +104,12 @@ func StatefulSet(
102104
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
103105
}
104106

107+
// add MTLS cert if defined
108+
if memcached.Status.MTLSCert != "" {
109+
volumes = append(volumes, memcached.CreateMTLSVolume())
110+
volumeMounts = append(volumeMounts, memcached.CreateMTLSVolumeMounts(nil, nil)...)
111+
}
112+
105113
for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} {
106114
if instance.Spec.TLS.API.Enabled(endpt) {
107115
var tlsEndptCfg tls.GenericService

pkg/novaconductor/dbpurge.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1010
"k8s.io/utils/ptr"
1111

12+
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
1213
"github.com/openstack-k8s-operators/lib-common/modules/common/env"
1314
novav1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1"
1415
"github.com/openstack-k8s-operators/nova-operator/pkg/nova"
@@ -18,6 +19,7 @@ func DBPurgeCronJob(
1819
instance *novav1.NovaConductor,
1920
labels map[string]string,
2021
annotations map[string]string,
22+
memcached *memcachedv1.Memcached,
2123
) *batchv1.CronJob {
2224
args := []string{"-c", nova.KollaServiceCommand}
2325

@@ -46,6 +48,12 @@ func DBPurgeCronJob(
4648
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
4749
}
4850

51+
// add MTLS cert if defined
52+
if memcached.Status.MTLSCert != "" {
53+
volumes = append(volumes, memcached.CreateMTLSVolume())
54+
volumeMounts = append(volumeMounts, memcached.CreateMTLSVolumeMounts(nil, nil)...)
55+
}
56+
4957
// we want to hide the fact that the job is created by the conductor
5058
// controller, but we don't have direct access to the Cell CR name, so we
5159
// remove the known conductor suffix from the Conductor CR name.

pkg/novaconductor/dbsync.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
env "github.com/openstack-k8s-operators/lib-common/modules/common/env"
2424

25+
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
2526
batchv1 "k8s.io/api/batch/v1"
2627
corev1 "k8s.io/api/core/v1"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -33,6 +34,7 @@ func CellDBSyncJob(
3334
instance *novav1.NovaConductor,
3435
labels map[string]string,
3536
annotations map[string]string,
37+
memcached *memcachedv1.Memcached,
3638
) *batchv1.Job {
3739
args := []string{"-c", nova.KollaServiceCommand}
3840

@@ -61,6 +63,12 @@ func CellDBSyncJob(
6163
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
6264
}
6365

66+
// add MTLS cert if defined
67+
if memcached.Status.MTLSCert != "" {
68+
volumes = append(volumes, memcached.CreateMTLSVolume())
69+
volumeMounts = append(volumeMounts, memcached.CreateMTLSVolumeMounts(nil, nil)...)
70+
}
71+
6472
job := &batchv1.Job{
6573
ObjectMeta: metav1.ObjectMeta{
6674
Name: instance.Name + "-db-sync",

pkg/novaconductor/deployment.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package novaconductor
1818

1919
import (
20+
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
2021
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2122
common "github.com/openstack-k8s-operators/lib-common/modules/common"
2223
affinity "github.com/openstack-k8s-operators/lib-common/modules/common/affinity"
@@ -37,6 +38,7 @@ func StatefulSet(
3738
labels map[string]string,
3839
annotations map[string]string,
3940
topology *topologyv1.Topology,
41+
memcached *memcachedv1.Memcached,
4042
) *appsv1.StatefulSet {
4143
livenessProbe := &corev1.Probe{
4244
// TODO might need tuning
@@ -93,6 +95,12 @@ func StatefulSet(
9395
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
9496
}
9597

98+
// add MTLS cert if defined
99+
if memcached.Status.MTLSCert != "" {
100+
volumes = append(volumes, memcached.CreateMTLSVolume())
101+
volumeMounts = append(volumeMounts, memcached.CreateMTLSVolumeMounts(nil, nil)...)
102+
}
103+
96104
statefulset := &appsv1.StatefulSet{
97105
ObjectMeta: metav1.ObjectMeta{
98106
Name: instance.Name,

pkg/novametadata/deployment.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package novametadata
1818

1919
import (
20+
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
2021
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2122
common "github.com/openstack-k8s-operators/lib-common/modules/common"
2223
affinity "github.com/openstack-k8s-operators/lib-common/modules/common/affinity"
@@ -38,6 +39,7 @@ func StatefulSet(
3839
labels map[string]string,
3940
annotations map[string]string,
4041
topology *topologyv1.Topology,
42+
memcached *memcachedv1.Memcached,
4143
) (*appsv1.StatefulSet, error) {
4244
// This allows the pod to start up slowly. The pod will only be killed
4345
// if it does not succeed a probe in 60 seconds.
@@ -100,6 +102,12 @@ func StatefulSet(
100102
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
101103
}
102104

105+
// add MTLS cert if defined
106+
if memcached.Status.MTLSCert != "" {
107+
volumes = append(volumes, memcached.CreateMTLSVolume())
108+
volumeMounts = append(volumeMounts, memcached.CreateMTLSVolumeMounts(nil, nil)...)
109+
}
110+
103111
if instance.Spec.TLS.GenericService.Enabled() {
104112
svc, err := instance.Spec.TLS.GenericService.ToService()
105113
if err != nil {

0 commit comments

Comments
 (0)