From 3c18c599055dd7404fd9634f51ae31e9d14fa5b7 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 13:21:08 +0200 Subject: [PATCH 01/24] Make use of gardener provided TLS certificates --- api/v1/postgres_types.go | 30 +++++++++++++++++++++++++++--- controllers/postgres_controller.go | 5 +++-- main.go | 11 +++++++++++ pkg/lbmanager/lbmanager.go | 19 ++++++++++++++----- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index e1fed82b..1a9c9fb7 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -345,7 +345,7 @@ func (p *Postgres) ToKey() *types.NamespacedName { } } -func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderSelector bool, enableLegacyStandbySelector bool, standbyClustersSourceRanges []string) *corev1.Service { +func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderSelector bool, enableLegacyStandbySelector bool, standbyClustersSourceRanges []string, tlsSubDomain string) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -353,6 +353,14 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS "metallb.universe.tf/allow-shared-ip": "spilo", } + if tlsSubDomain != "" { + lb.Annotations["cert.gardener.cloud/purpose"] = "managed" + lb.Annotations["cert.gardener.cloud/secretname"] = p.generateDatabaseName() + lb.Annotations["dns.gardener.cloud/class"] = "garden" + lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToSharedSvcLBName() + "." + tlsSubDomain + lb.Annotations["dns.gardener.cloud/ttl"] = "180" + } + lb.Namespace = p.ToPeripheralResourceNamespace() lb.Name = p.ToSharedSvcLBName() lb.SetLabels(SvcLoadBalancerLabel) @@ -420,7 +428,7 @@ func (p *Postgres) ToSharedSvcLBNamespacedName() *types.NamespacedName { } } -func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string) *corev1.Service { +func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string, tlsSubDomain string) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -430,6 +438,16 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.Name = p.ToDedicatedSvcLBName() lb.SetLabels(SvcLoadBalancerLabel) + if tlsSubDomain != "" { + lb.Annotations = map[string]string{ + "cert.gardener.cloud/purpose": "managed", + "cert.gardener.cloud/secretname": p.generateDatabaseName(), + "dns.gardener.cloud/class": "garden", + "dns.gardener.cloud/dnsnames": p.ToDedicatedSvcLBName() + "." + tlsSubDomain, + "dns.gardener.cloud/ttl": "180", + } + } + lbsr := []string{} if p.HasSourceRanges() { for _, src := range p.Spec.AccessList.SourceRanges { @@ -607,7 +625,7 @@ func (p *Postgres) ToPeripheralResourceLookupKey() types.NamespacedName { } } -func (p *Postgres) ToUnstructuredZalandoPostgresql(z *zalando.Postgresql, c *corev1.ConfigMap, sc string, pgParamBlockList map[string]bool, rbs *BackupConfig, srcDB *Postgres, patroniTTL, patroniLoopWait, patroniRetryTimeout uint32, dboIsSuperuser bool) (*unstructured.Unstructured, error) { +func (p *Postgres) ToUnstructuredZalandoPostgresql(z *zalando.Postgresql, c *corev1.ConfigMap, sc string, pgParamBlockList map[string]bool, rbs *BackupConfig, srcDB *Postgres, patroniTTL, patroniLoopWait, patroniRetryTimeout uint32, dboIsSuperuser bool, enableTlsCert bool) (*unstructured.Unstructured, error) { if z == nil { z = &zalando.Postgresql{} } @@ -734,6 +752,12 @@ func (p *Postgres) ToUnstructuredZalandoPostgresql(z *zalando.Postgresql, c *cor } } + if enableTlsCert { + z.Spec.TLS = &zalando.TLSDescription{ + SecretName: p.generateDatabaseName(), + } + } + jsonZ, err := runtime.DefaultUnstructuredConverter.ToUnstructured(z) if err != nil { return nil, fmt.Errorf("failed to convert to unstructured zalando postgresql: %w", err) diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index 7883fb7d..f095dc26 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -92,6 +92,7 @@ type PostgresReconciler struct { InitDBJobConfigMapName string EnableBootstrapStandbyFromS3 bool EnableSuperUserForDBO bool + EnableCustomTLSCert bool } // Reconcile is the entry point for postgres reconciliation. @@ -368,7 +369,7 @@ func (r *PostgresReconciler) createOrUpdateZalandoPostgresql(ctx context.Context return fmt.Errorf("failed to fetch zalando postgresql: %w", err) } - u, err := instance.ToUnstructuredZalandoPostgresql(nil, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSouceInstance, patroniTTL, patroniLoopWait, patroniRetryTimout, r.EnableSuperUserForDBO) + u, err := instance.ToUnstructuredZalandoPostgresql(nil, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSouceInstance, patroniTTL, patroniLoopWait, patroniRetryTimout, r.EnableSuperUserForDBO, r.EnableCustomTLSCert) if err != nil { return fmt.Errorf("failed to convert to unstructured zalando postgresql: %w", err) } @@ -384,7 +385,7 @@ func (r *PostgresReconciler) createOrUpdateZalandoPostgresql(ctx context.Context // Update zalando postgresql mergeFrom := client.MergeFrom(rawZ.DeepCopy()) - u, err := instance.ToUnstructuredZalandoPostgresql(rawZ, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSouceInstance, patroniTTL, patroniLoopWait, patroniRetryTimout, r.EnableSuperUserForDBO) + u, err := instance.ToUnstructuredZalandoPostgresql(rawZ, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSouceInstance, patroniTTL, patroniLoopWait, patroniRetryTimout, r.EnableSuperUserForDBO, r.EnableCustomTLSCert) if err != nil { return fmt.Errorf("failed to convert to unstructured zalando postgresql: %w", err) } diff --git a/main.go b/main.go index 910e7abe..341a064d 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ const ( initDBJobCMNameFlg = "initdb-job-configmap-name" enableBootstrapStandbyFromS3Flg = "enable-bootsrtap-standby-from-s3" enableSuperUserForDBOFlg = "enable-superuser-for-dbo" + tlsSubDomainFlg = "tls-sub-domain" ) var ( @@ -116,6 +117,7 @@ func main() { etcdPSPName string postgresletFullname string initDBJobCMName string + tlsSubDomain string enableLeaderElection bool enableCRDValidation bool @@ -277,6 +279,12 @@ func main() { viper.SetDefault(enableSuperUserForDBOFlg, false) enableSuperUserForDBO = viper.GetBool(enableSuperUserForDBOFlg) + tlsSubDomain = viper.GetString(tlsSubDomainFlg) + enableCustomTLSCert := false + if tlsSubDomain != "" { + enableCustomTLSCert = true + } + ctrl.Log.Info("flag", metricsAddrSvcMgrFlg, metricsAddrSvcMgr, metricsAddrCtrlMgrFlg, metricsAddrCtrlMgr, @@ -317,6 +325,7 @@ func main() { initDBJobCMNameFlg, initDBJobCMName, enableBootstrapStandbyFromS3Flg, enableBootstrapStandbyFromS3, enableSuperUserForDBOFlg, enableSuperUserForDBO, + tlsSubDomainFlg, tlsSubDomain, ) svcClusterConf := ctrl.GetConfigOrDie() @@ -401,6 +410,7 @@ func main() { StandbyClustersSourceRanges: standbyClusterSourceRanges, EnableLBSourceRanges: enableLBSourceRanges, EnableForceSharedIP: enableForceSharedIP, + TLSSubDomain: tlsSubDomain, } if err = (&controllers.PostgresReconciler{ CtrlClient: ctrlPlaneClusterMgr.GetClient(), @@ -428,6 +438,7 @@ func main() { InitDBJobConfigMapName: initDBJobCMName, EnableBootstrapStandbyFromS3: enableBootstrapStandbyFromS3, EnableSuperUserForDBO: enableSuperUserForDBO, + EnableCustomTLSCert: enableCustomTLSCert, }).SetupWithManager(ctrlPlaneClusterMgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Postgres") os.Exit(1) diff --git a/pkg/lbmanager/lbmanager.go b/pkg/lbmanager/lbmanager.go index 23550703..550689cd 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -21,6 +21,7 @@ type Options struct { StandbyClustersSourceRanges []string EnableLBSourceRanges bool EnableForceSharedIP bool + TLSSubDomain string } // LBManager Responsible for the creation and deletion of externally accessible Services to access the Postgresql clusters managed by the Postgreslet. @@ -59,12 +60,18 @@ func (m *LBManager) ReconcileSvcLBs(ctx context.Context, in *api.Postgres) error // CreateOrUpdateSharedSvcLB Creates or updates a Service of type LoadBalancer with a shared ip for the given Postgres resource if neccessary func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postgres) error { - if m.options.EnableForceSharedIP != true && in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { + if !m.options.EnableForceSharedIP && in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { // TODO logging? // TODO delete shared LB if neccessary (cleanup after possible config change)? return nil } + tlsSubDomain := m.options.TLSSubDomain + if in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { + // The annotation for the certificate will be handled by the DedicatedSvcLB and not by this SharedSvcLB. + tlsSubDomain = "" + } + svc := &corev1.Service{} if err := m.client.Get(ctx, client.ObjectKey{ Namespace: in.ToPeripheralResourceNamespace(), @@ -90,7 +97,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg lbIPToUse = "" } - svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges) + svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, tlsSubDomain) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges svc.Spec.LoadBalancerSourceRanges = []string{} @@ -101,7 +108,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg return nil } - updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges) + updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, tlsSubDomain) // update the selector, and only the selector (we do NOT want the change the ip or port here!!!) svc.Spec.Selector = updated.Spec.Selector // also update the source ranges @@ -112,6 +119,8 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg // leave empty / disable source ranges svc.Spec.LoadBalancerSourceRanges = []string{} } + // also update the annotations for our custom tls certs + svc.ObjectMeta.Annotations = updated.ObjectMeta.Annotations if err := m.client.Update(ctx, svc); err != nil { return fmt.Errorf("failed to update Service of type LoadBalancer (shared): %w", err) @@ -126,7 +135,7 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po // TODO logging? err := m.DeleteDedicatedSvcLB(ctx, in) if err != nil { - m.log.Info("could not delete dedicated loadbalancer") + m.log.Info("could not delete dedicated loadbalancer", "ns", in.Namespace, "pgID", in.Name) } return nil } @@ -137,7 +146,7 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po } var lbIPToUse string = *in.Spec.DedicatedLoadBalancerIP - new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges) + new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges new.Spec.LoadBalancerSourceRanges = []string{} From abc05fb1dc7fc08807cc376b12f4a1a3a6d68de1 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 13:32:22 +0200 Subject: [PATCH 02/24] ... --- api/v1/postgres_types_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1/postgres_types_test.go b/api/v1/postgres_types_test.go index 0b196a8e..cc68c50e 100644 --- a/api/v1/postgres_types_test.go +++ b/api/v1/postgres_types_test.go @@ -349,7 +349,7 @@ func TestPostgresRestoreTimestamp_ToUnstructuredZalandoPostgresql(t *testing.T) p := &Postgres{ Spec: tt.spec, } - got, _ := p.ToUnstructuredZalandoPostgresql(nil, tt.c, tt.sc, tt.pgParamBlockList, tt.rbs, tt.srcDB, 130, 10, 60, false) + got, _ := p.ToUnstructuredZalandoPostgresql(nil, tt.c, tt.sc, tt.pgParamBlockList, tt.rbs, tt.srcDB, 130, 10, 60, false, false) jsonZ, err := runtime.DefaultUnstructuredConverter.ToUnstructured(got) if err != nil { From 3e94f75d2eebe42f9347090da5cccf285a7bf360 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 13:45:04 +0200 Subject: [PATCH 03/24] Generate shorter commonName --- api/v1/postgres_types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 1a9c9fb7..86dc2b60 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -356,6 +356,7 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS if tlsSubDomain != "" { lb.Annotations["cert.gardener.cloud/purpose"] = "managed" lb.Annotations["cert.gardener.cloud/secretname"] = p.generateDatabaseName() + lb.Annotations["cert.gardener.cloud/commonName"] = p.generateDatabaseName() lb.Annotations["dns.gardener.cloud/class"] = "garden" lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToSharedSvcLBName() + "." + tlsSubDomain lb.Annotations["dns.gardener.cloud/ttl"] = "180" @@ -442,6 +443,7 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.Annotations = map[string]string{ "cert.gardener.cloud/purpose": "managed", "cert.gardener.cloud/secretname": p.generateDatabaseName(), + "cert.gardener.cloud/commonName": p.generateDatabaseName(), "dns.gardener.cloud/class": "garden", "dns.gardener.cloud/dnsnames": p.ToDedicatedSvcLBName() + "." + tlsSubDomain, "dns.gardener.cloud/ttl": "180", From 1a295a534728d8cbb548194b573bba06a00a2465 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 14:01:12 +0200 Subject: [PATCH 04/24] * remove commonName annotation * shorten DNS name --- api/v1/postgres_types.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 86dc2b60..aa417856 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -356,9 +356,8 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS if tlsSubDomain != "" { lb.Annotations["cert.gardener.cloud/purpose"] = "managed" lb.Annotations["cert.gardener.cloud/secretname"] = p.generateDatabaseName() - lb.Annotations["cert.gardener.cloud/commonName"] = p.generateDatabaseName() lb.Annotations["dns.gardener.cloud/class"] = "garden" - lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToSharedSvcLBName() + "." + tlsSubDomain + lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain lb.Annotations["dns.gardener.cloud/ttl"] = "180" } @@ -443,9 +442,8 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.Annotations = map[string]string{ "cert.gardener.cloud/purpose": "managed", "cert.gardener.cloud/secretname": p.generateDatabaseName(), - "cert.gardener.cloud/commonName": p.generateDatabaseName(), "dns.gardener.cloud/class": "garden", - "dns.gardener.cloud/dnsnames": p.ToDedicatedSvcLBName() + "." + tlsSubDomain, + "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, "dns.gardener.cloud/ttl": "180", } } From e51dc96a153d86fc0ee8c319188c996061af271c Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 14:22:01 +0200 Subject: [PATCH 05/24] Try different annotations --- api/v1/postgres_types.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index aa417856..fe3ecca5 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -354,11 +354,13 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS } if tlsSubDomain != "" { - lb.Annotations["cert.gardener.cloud/purpose"] = "managed" + // lb.Annotations["cert.gardener.cloud/purpose"] = "managed" lb.Annotations["cert.gardener.cloud/secretname"] = p.generateDatabaseName() - lb.Annotations["dns.gardener.cloud/class"] = "garden" lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain - lb.Annotations["dns.gardener.cloud/ttl"] = "180" + lb.Annotations["dns.gardener.cloud/class"] = "garden" + // lb.Annotations["dns.gardener.cloud/ttl"] = "180" + lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } lb.Namespace = p.ToPeripheralResourceNamespace() @@ -440,11 +442,13 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo if tlsSubDomain != "" { lb.Annotations = map[string]string{ - "cert.gardener.cloud/purpose": "managed", + // "cert.gardener.cloud/purpose": "managed", "cert.gardener.cloud/secretname": p.generateDatabaseName(), - "dns.gardener.cloud/class": "garden", "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, - "dns.gardener.cloud/ttl": "180", + "dns.gardener.cloud/class": "garden", + // "dns.gardener.cloud/ttl": "180", + "cert.gardener.cloud/commonname": p.Name, + "cert.gardener.cloud/dnsnames": "", } } From 2dba2812aa580ec6456472ab91bfbc5ce43afc7c Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 14:30:25 +0200 Subject: [PATCH 06/24] Add subdomain to commonName --- api/v1/postgres_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index fe3ecca5..8821feca 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -359,7 +359,7 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain lb.Annotations["dns.gardener.cloud/class"] = "garden" // lb.Annotations["dns.gardener.cloud/ttl"] = "180" - lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + "." + tlsSubDomain lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } @@ -447,7 +447,7 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, "dns.gardener.cloud/class": "garden", // "dns.gardener.cloud/ttl": "180", - "cert.gardener.cloud/commonname": p.Name, + "cert.gardener.cloud/commonname": p.Name + "." + tlsSubDomain, "cert.gardener.cloud/dnsnames": "", } } From e500fc4395b5ff6d85cda51c31137ae42ba9b007 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 14:43:53 +0200 Subject: [PATCH 07/24] use wildcard in commonName --- api/v1/postgres_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 8821feca..90bf25f7 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -359,7 +359,7 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain lb.Annotations["dns.gardener.cloud/class"] = "garden" // lb.Annotations["dns.gardener.cloud/ttl"] = "180" - lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + "." + tlsSubDomain + lb.Annotations["cert.gardener.cloud/commonname"] = "*." + tlsSubDomain lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } @@ -447,7 +447,7 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, "dns.gardener.cloud/class": "garden", // "dns.gardener.cloud/ttl": "180", - "cert.gardener.cloud/commonname": p.Name + "." + tlsSubDomain, + "cert.gardener.cloud/commonname": "*." + tlsSubDomain, "cert.gardener.cloud/dnsnames": "", } } From bd25ebc649767ff9bce89087977306406c2958e9 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 14:54:58 +0200 Subject: [PATCH 08/24] Use proper dns name instead of wildcard --- api/v1/postgres_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 90bf25f7..8821feca 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -359,7 +359,7 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain lb.Annotations["dns.gardener.cloud/class"] = "garden" // lb.Annotations["dns.gardener.cloud/ttl"] = "180" - lb.Annotations["cert.gardener.cloud/commonname"] = "*." + tlsSubDomain + lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + "." + tlsSubDomain lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } @@ -447,7 +447,7 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, "dns.gardener.cloud/class": "garden", // "dns.gardener.cloud/ttl": "180", - "cert.gardener.cloud/commonname": "*." + tlsSubDomain, + "cert.gardener.cloud/commonname": p.Name + "." + tlsSubDomain, "cert.gardener.cloud/dnsnames": "", } } From 7623905042eac99f719f5f85fd172eccee1b87c6 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 15:17:19 +0200 Subject: [PATCH 09/24] Naming --- api/v1/postgres_types.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 8821feca..3895f333 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -355,11 +355,11 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS if tlsSubDomain != "" { // lb.Annotations["cert.gardener.cloud/purpose"] = "managed" - lb.Annotations["cert.gardener.cloud/secretname"] = p.generateDatabaseName() - lb.Annotations["dns.gardener.cloud/dnsnames"] = p.Name + "." + tlsSubDomain + lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() + lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) lb.Annotations["dns.gardener.cloud/class"] = "garden" // lb.Annotations["dns.gardener.cloud/ttl"] = "180" - lb.Annotations["cert.gardener.cloud/commonname"] = p.Name + "." + tlsSubDomain + lb.Annotations["cert.gardener.cloud/commonname"] = p.ToDNSName(tlsSubDomain) lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } @@ -443,11 +443,11 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo if tlsSubDomain != "" { lb.Annotations = map[string]string{ // "cert.gardener.cloud/purpose": "managed", - "cert.gardener.cloud/secretname": p.generateDatabaseName(), - "dns.gardener.cloud/dnsnames": p.Name + "." + tlsSubDomain, + "cert.gardener.cloud/secretname": p.ToTLSSecretName(), + "dns.gardener.cloud/dnsnames": p.ToDNSName(tlsSubDomain), "dns.gardener.cloud/class": "garden", // "dns.gardener.cloud/ttl": "180", - "cert.gardener.cloud/commonname": p.Name + "." + tlsSubDomain, + "cert.gardener.cloud/commonname": p.ToDNSName(tlsSubDomain), "cert.gardener.cloud/dnsnames": "", } } @@ -622,6 +622,21 @@ func (p *Postgres) ToPeripheralResourceNamespace() string { return projectID + "-" + name } +func (p *Postgres) ToDNSName(tlsSubDomain string) string { + // We only want letters and numbers + name := alphaNumericRegExp.ReplaceAllString(string(p.Name), "") + // Limit size + maxLen := 12 + if len(name) > maxLen { + name = name[:maxLen] + } + return name + "." + tlsSubDomain +} + +func (p *Postgres) ToTLSSecretName() string { + return p.generateDatabaseName() + "-cert" +} + func (p *Postgres) ToPeripheralResourceLookupKey() types.NamespacedName { return types.NamespacedName{ Namespace: p.ToPeripheralResourceNamespace(), @@ -758,7 +773,7 @@ func (p *Postgres) ToUnstructuredZalandoPostgresql(z *zalando.Postgresql, c *cor if enableTlsCert { z.Spec.TLS = &zalando.TLSDescription{ - SecretName: p.generateDatabaseName(), + SecretName: p.ToTLSSecretName(), } } From 097582be735a8e134a14fe78c4435224bb1a93cf Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 15:44:26 +0200 Subject: [PATCH 10/24] Set spilo_fsgroup to fix tls permission issue --- pkg/operatormanager/operatormanager.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index b15ac008..d2b1657b 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -51,6 +51,8 @@ const ( SidecarsCMExporterQueriesKey string = "queries.yaml" localSidecarsCMName = "postgres-sidecars-configmap" + + spilo_fsgroup = "103" ) // operatorPodMatchingLabels is for listing operator pods @@ -427,6 +429,9 @@ func (m *OperatorManager) editConfigMap(cm *corev1.ConfigMap, namespace string, cm.Data["replication_username"] = pg.PostgresConfigReplicationUsername cm.Data["enable_pod_antiaffinity"] = strconv.FormatBool(options.PodAntiaffinity) + + // set the spilo_fsgroup for correct tls cert permissions + cm.Data["spilo_fsgroup"] = spilo_fsgroup } // ensureCleanMetadata ensures obj has clean metadata From 4f140fb26fed83f951328d81ef82a956078aaaaa Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 16 May 2024 15:57:59 +0200 Subject: [PATCH 11/24] Add additional annotation --- api/v1/postgres_types.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 3895f333..5e04dd2b 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -354,11 +354,10 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS } if tlsSubDomain != "" { - // lb.Annotations["cert.gardener.cloud/purpose"] = "managed" + lb.Annotations["cert.gardener.cloud/purpose"] = "managed" lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) lb.Annotations["dns.gardener.cloud/class"] = "garden" - // lb.Annotations["dns.gardener.cloud/ttl"] = "180" lb.Annotations["cert.gardener.cloud/commonname"] = p.ToDNSName(tlsSubDomain) lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } @@ -442,11 +441,10 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo if tlsSubDomain != "" { lb.Annotations = map[string]string{ - // "cert.gardener.cloud/purpose": "managed", + "cert.gardener.cloud/purpose": "managed", "cert.gardener.cloud/secretname": p.ToTLSSecretName(), "dns.gardener.cloud/dnsnames": p.ToDNSName(tlsSubDomain), "dns.gardener.cloud/class": "garden", - // "dns.gardener.cloud/ttl": "180", "cert.gardener.cloud/commonname": p.ToDNSName(tlsSubDomain), "cert.gardener.cloud/dnsnames": "", } From 1fa6a20ba72ecf9f82ee2cf4524adf6d1c2b6a76 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Tue, 21 May 2024 15:53:13 +0200 Subject: [PATCH 12/24] Move annotations to shared LB when both are available --- pkg/lbmanager/lbmanager.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/lbmanager/lbmanager.go b/pkg/lbmanager/lbmanager.go index 550689cd..2b12e110 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -67,7 +67,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg } tlsSubDomain := m.options.TLSSubDomain - if in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { + if in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" && !m.options.EnableForceSharedIP { // The annotation for the certificate will be handled by the DedicatedSvcLB and not by this SharedSvcLB. tlsSubDomain = "" } @@ -146,7 +146,13 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po } var lbIPToUse string = *in.Spec.DedicatedLoadBalancerIP - new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) + tlsSubDomain := m.options.TLSSubDomain + if m.options.EnableForceSharedIP { + // The annotation for the certificate will be handled by the SharedSvcLB and not by this DedicatedSvcLB. + tlsSubDomain = "" + } + + new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, tlsSubDomain) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges new.Spec.LoadBalancerSourceRanges = []string{} From 16ab026e16610f78e74f22172e4505e54bf2f740 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Tue, 21 May 2024 16:04:30 +0200 Subject: [PATCH 13/24] Reset annotations if neccessary --- api/v1/postgres_types.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 5e04dd2b..0a952058 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -439,15 +439,14 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.Name = p.ToDedicatedSvcLBName() lb.SetLabels(SvcLoadBalancerLabel) + lb.Annotations = map[string]string{} if tlsSubDomain != "" { - lb.Annotations = map[string]string{ - "cert.gardener.cloud/purpose": "managed", - "cert.gardener.cloud/secretname": p.ToTLSSecretName(), - "dns.gardener.cloud/dnsnames": p.ToDNSName(tlsSubDomain), - "dns.gardener.cloud/class": "garden", - "cert.gardener.cloud/commonname": p.ToDNSName(tlsSubDomain), - "cert.gardener.cloud/dnsnames": "", - } + lb.Annotations["cert.gardener.cloud/purpose"] = "managed" + lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() + lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) + lb.Annotations["dns.gardener.cloud/class"] = "garden" + lb.Annotations["cert.gardener.cloud/commonname"] = p.ToDNSName(tlsSubDomain) + lb.Annotations["cert.gardener.cloud/dnsnames"] = "" } lbsr := []string{} From 9f76aa050cb47ca16b61ad37353789adc351bf23 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Tue, 21 May 2024 16:19:53 +0200 Subject: [PATCH 14/24] Update annotations --- pkg/lbmanager/lbmanager.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/lbmanager/lbmanager.go b/pkg/lbmanager/lbmanager.go index 2b12e110..49c5d162 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -176,6 +176,9 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po // replace the whole spec existing.Spec = new.Spec + // also update the annotations for our custom tls certs + existing.ObjectMeta.Annotations = new.ObjectMeta.Annotations + if err := m.client.Update(ctx, existing); err != nil { return fmt.Errorf("failed to update Service of type LoadBalancer (dedicated): %w", err) } From 5822ae4b49c5e26f066ba4d92d88294efa5fea04 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 24 May 2024 14:24:26 +0200 Subject: [PATCH 15/24] Centralize logic --- api/v1/postgres_types.go | 37 ++++++++++++++++++++++++++++++-- controllers/status_controller.go | 3 ++- pkg/lbmanager/lbmanager.go | 22 ++++++------------- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 0a952058..42aab05f 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -429,7 +429,26 @@ func (p *Postgres) ToSharedSvcLBNamespacedName() *types.NamespacedName { } } -func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string, tlsSubDomain string) *corev1.Service { +func (p *Postgres) EnableSharedSVCLB(enableForceSharedIP bool) bool { + if enableForceSharedIP { + // shared IP is forced, so force it. No more questions asked. + return true + } + + if p.Spec.DedicatedLoadBalancerIP == nil { + // No dedicated ip set at all, enabled shared lb + return true + } + + if *p.Spec.DedicatedLoadBalancerIP == "" { + // Empty IP set, enable shared lb + return true + } + + return false +} + +func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string, sharedSvcLbAlsoEnabled bool, tlsSubDomain string) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -440,7 +459,7 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.SetLabels(SvcLoadBalancerLabel) lb.Annotations = map[string]string{} - if tlsSubDomain != "" { + if !sharedSvcLbAlsoEnabled && tlsSubDomain != "" { lb.Annotations["cert.gardener.cloud/purpose"] = "managed" lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) @@ -504,6 +523,20 @@ func (p *Postgres) ToDedicatedSvcLBNamespacedName() *types.NamespacedName { } } +func (p *Postgres) EnableDedicatedSVCLB() bool { + if p.Spec.DedicatedLoadBalancerIP == nil { + // No dedicated ip set at all, disable dedicated lb + return false + } + + if *p.Spec.DedicatedLoadBalancerIP == "" { + // Empty IP set, disable dedicated lb + return false + } + + return true +} + func (p *Postgres) ToPeripheralResourceName() string { return p.generateTeamID() + "-" + p.generateDatabaseName() diff --git a/controllers/status_controller.go b/controllers/status_controller.go index fcc8106a..bd0f93e8 100644 --- a/controllers/status_controller.go +++ b/controllers/status_controller.go @@ -94,13 +94,14 @@ func (r *StatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } log.Info("updating socket") - if owner.Spec.DedicatedLoadBalancerIP == nil { + if !owner.EnableDedicatedSVCLB() { // no dedicated load balancer configured, use the shared one shared := &corev1.Service{} if err := r.SvcClient.Get(ctx, *owner.ToSharedSvcLBNamespacedName(), shared); err == nil { // update IP and port owner.Status.Socket.IP = shared.Spec.LoadBalancerIP owner.Status.Socket.Port = shared.Spec.Ports[0].Port + owner.Status.AdditionalSockets = []pg.Socket{} // reset addidtional sockets } else { // Todo: Handle errors other than `NotFound` diff --git a/pkg/lbmanager/lbmanager.go b/pkg/lbmanager/lbmanager.go index 49c5d162..74b1aa27 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -60,18 +60,12 @@ func (m *LBManager) ReconcileSvcLBs(ctx context.Context, in *api.Postgres) error // CreateOrUpdateSharedSvcLB Creates or updates a Service of type LoadBalancer with a shared ip for the given Postgres resource if neccessary func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postgres) error { - if !m.options.EnableForceSharedIP && in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { + if !in.EnableSharedSVCLB(m.options.EnableForceSharedIP) { // TODO logging? // TODO delete shared LB if neccessary (cleanup after possible config change)? return nil } - tlsSubDomain := m.options.TLSSubDomain - if in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" && !m.options.EnableForceSharedIP { - // The annotation for the certificate will be handled by the DedicatedSvcLB and not by this SharedSvcLB. - tlsSubDomain = "" - } - svc := &corev1.Service{} if err := m.client.Get(ctx, client.ObjectKey{ Namespace: in.ToPeripheralResourceNamespace(), @@ -97,7 +91,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg lbIPToUse = "" } - svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, tlsSubDomain) + svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges svc.Spec.LoadBalancerSourceRanges = []string{} @@ -108,7 +102,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg return nil } - updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, tlsSubDomain) + updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) // update the selector, and only the selector (we do NOT want the change the ip or port here!!!) svc.Spec.Selector = updated.Spec.Selector // also update the source ranges @@ -131,7 +125,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg // CreateOrUpdateDedicatedSvcLB Creates or updates a Service of type LoadBalancer with a dedicated ip for the given Postgres resource if neccessary func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Postgres) error { - if in.Spec.DedicatedLoadBalancerIP == nil || *in.Spec.DedicatedLoadBalancerIP == "" { + if !in.EnableDedicatedSVCLB() { // TODO logging? err := m.DeleteDedicatedSvcLB(ctx, in) if err != nil { @@ -146,13 +140,9 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po } var lbIPToUse string = *in.Spec.DedicatedLoadBalancerIP - tlsSubDomain := m.options.TLSSubDomain - if m.options.EnableForceSharedIP { - // The annotation for the certificate will be handled by the SharedSvcLB and not by this DedicatedSvcLB. - tlsSubDomain = "" - } + sharedSvcLbAlsoEnabled := in.EnableSharedSVCLB(m.options.EnableForceSharedIP) - new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, tlsSubDomain) + new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, sharedSvcLbAlsoEnabled, m.options.TLSSubDomain) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges new.Spec.LoadBalancerSourceRanges = []string{} From d12dd1c2a30ce16e6c8db848ee7c162010c748a6 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 24 May 2024 14:25:54 +0200 Subject: [PATCH 16/24] ... --- controllers/status_controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/status_controller.go b/controllers/status_controller.go index bd0f93e8..7076d8f6 100644 --- a/controllers/status_controller.go +++ b/controllers/status_controller.go @@ -101,7 +101,7 @@ func (r *StatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr // update IP and port owner.Status.Socket.IP = shared.Spec.LoadBalancerIP owner.Status.Socket.Port = shared.Spec.Ports[0].Port - owner.Status.AdditionalSockets = []pg.Socket{} // reset addidtional sockets + owner.Status.AdditionalSockets = []pg.Socket{} // reset additional sockets } else { // Todo: Handle errors other than `NotFound` From d97a353c48f8964372e9486bf4f54cef9ca5b868 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 7 Jun 2024 15:02:23 +0200 Subject: [PATCH 17/24] Use certificate CR instead of gardener annotations --- api/v1/postgres_types.go | 21 ++------------- controllers/postgres_controller.go | 31 ++++++++++++++++++++++ go.mod | 16 +++++++----- go.sum | 41 ++++++++++++++++++++---------- main.go | 12 ++++----- pkg/lbmanager/lbmanager.go | 7 +++-- 6 files changed, 78 insertions(+), 50 deletions(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index dca394e2..0fce1760 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -345,7 +345,7 @@ func (p *Postgres) ToKey() *types.NamespacedName { } } -func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderSelector bool, enableLegacyStandbySelector bool, standbyClustersSourceRanges []string, tlsSubDomain string) *corev1.Service { +func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderSelector bool, enableLegacyStandbySelector bool, standbyClustersSourceRanges []string) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -353,15 +353,6 @@ func (p *Postgres) ToSharedSvcLB(lbIP string, lbPort int32, enableStandbyLeaderS "metallb.universe.tf/allow-shared-ip": "spilo", } - if tlsSubDomain != "" { - lb.Annotations["cert.gardener.cloud/purpose"] = "managed" - lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() - lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) - lb.Annotations["dns.gardener.cloud/class"] = "garden" - lb.Annotations["cert.gardener.cloud/commonname"] = p.ToDNSName(tlsSubDomain) - lb.Annotations["cert.gardener.cloud/dnsnames"] = "" - } - lb.Namespace = p.ToPeripheralResourceNamespace() lb.Name = p.ToSharedSvcLBName() lb.SetLabels(SvcLoadBalancerLabel) @@ -448,7 +439,7 @@ func (p *Postgres) EnableSharedSVCLB(enableForceSharedIP bool) bool { return false } -func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string, sharedSvcLbAlsoEnabled bool, tlsSubDomain string) *corev1.Service { +func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []string, sharedSvcLbAlsoEnabled bool) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -459,14 +450,6 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.SetLabels(SvcLoadBalancerLabel) lb.Annotations = map[string]string{} - if !sharedSvcLbAlsoEnabled && tlsSubDomain != "" { - lb.Annotations["cert.gardener.cloud/purpose"] = "managed" - lb.Annotations["cert.gardener.cloud/secretname"] = p.ToTLSSecretName() - lb.Annotations["dns.gardener.cloud/dnsnames"] = p.ToDNSName(tlsSubDomain) - lb.Annotations["dns.gardener.cloud/class"] = "garden" - lb.Annotations["cert.gardener.cloud/commonname"] = p.ToDNSName(tlsSubDomain) - lb.Annotations["cert.gardener.cloud/dnsnames"] = "" - } lbsr := []string{} if p.HasSourceRanges() { diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index 1ad0ed82..e4604642 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -46,6 +46,9 @@ import ( pg "github.com/fi-ts/postgreslet/api/v1" "github.com/fi-ts/postgreslet/pkg/lbmanager" "github.com/fi-ts/postgreslet/pkg/operatormanager" + + cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" ) const ( @@ -94,6 +97,7 @@ type PostgresReconciler struct { EnableBootstrapStandbyFromS3 bool EnableSuperUserForDBO bool EnableCustomTLSCert bool + TLSClusterIssuer string } // Reconcile is the entry point for postgres reconciliation. @@ -238,6 +242,12 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c } } + // Request certificate, if neccessary + if err := r.createOrUpdateCertificate(log, ctx, instance); err != nil { + r.recorder.Eventf(instance, "Warning", "Error", "failed to create certificate request: %v", err) + return ctrl.Result{}, fmt.Errorf("error while creating certificate request: %w", err) + } + // Make sure the postgres secrets exist, if necessary if err := r.ensurePostgresSecrets(log, ctx, instance); err != nil { r.recorder.Eventf(instance, "Warning", "Error", "failed to create postgres secrets: %v", err) @@ -1711,3 +1721,24 @@ func (r *PostgresReconciler) ensureInitDBJob(log logr.Logger, ctx context.Contex return nil } + +func (r *PostgresReconciler) createOrUpdateCertificate(log logr.Logger, ctx context.Context, instance *pg.Postgres) error { + + c := &cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{Name: instance.ToPeripheralResourceName(), Namespace: instance.ToPeripheralResourceNamespace()}} + if _, err := controllerutil.CreateOrUpdate(ctx, r.SvcClient, c, func() error { + c.Spec = cmapi.CertificateSpec{ + CommonName: instance.ToPeripheralResourceName(), + SecretName: instance.ToTLSSecretName(), + IssuerRef: cmmeta.ObjectReference{ + Group: "cert-manager.io", + Kind: "ClusterIssuer", + Name: r.TLSClusterIssuer, + }, + } + return nil + }); err != nil { + return fmt.Errorf("unable to create or update certificate: %w", err) + } + + return nil +} diff --git a/go.mod b/go.mod index 9b76050f..54db4af0 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/fi-ts/postgreslet go 1.22 require ( + github.com/cert-manager/cert-manager v1.10.0 github.com/go-logr/logr v1.2.4 github.com/google/uuid v1.3.0 github.com/metal-stack/firewall-controller v1.3.0 @@ -12,10 +13,10 @@ require ( github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.56.2 github.com/spf13/viper v1.12.0 github.com/zalando/postgres-operator v1.7.0 - k8s.io/api v0.25.0 - k8s.io/apiextensions-apiserver v0.25.0 - k8s.io/apimachinery v0.25.0 - k8s.io/client-go v0.25.0 + k8s.io/api v0.25.2 + k8s.io/apiextensions-apiserver v0.25.2 + k8s.io/apimachinery v0.25.2 + k8s.io/client-go v0.25.2 k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 sigs.k8s.io/controller-runtime v0.13.1 ) @@ -73,7 +74,7 @@ require ( go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.23.0 // indirect - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect + golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.2.0 // indirect @@ -90,9 +91,10 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.25.0 // indirect + k8s.io/component-base v0.25.2 // indirect k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect + k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea // indirect + sigs.k8s.io/gateway-api v0.5.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index 6d2298e4..c19d28d9 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,8 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cert-manager/cert-manager v1.10.0 h1:qWMM2nqt3pyCVKTWoS645PORJpK5XvtE0iImk9qTPsc= +github.com/cert-manager/cert-manager v1.10.0/go.mod h1:xKakpUDYRHgUry/DkvcCCgQDRSwVSeSXTlw7slT+AYo= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -166,6 +168,7 @@ github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -206,6 +209,7 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -379,6 +383,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -446,6 +451,7 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -506,6 +512,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -550,6 +557,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= @@ -598,6 +606,7 @@ go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= @@ -618,8 +627,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 h1:WJywXQVIb56P2kAvXeMGTIgQ1ZHQxR60+F9dLsodECc= +golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -750,6 +759,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1117,6 +1127,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1155,22 +1166,22 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= -k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= +k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= +k8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0= k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= -k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= -k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= +k8s.io/apiextensions-apiserver v0.25.2 h1:8uOQX17RE7XL02ngtnh3TgifY7EhekpK+/piwzQNnBo= +k8s.io/apiextensions-apiserver v0.25.2/go.mod h1:iRwwRDlWPfaHhuBfQ0WMa5skdQfrE18QXJaJvIDLvE8= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= -k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= +k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= +k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= -k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= +k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= +k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= -k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= -k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= +k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY= +k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= @@ -1179,8 +1190,8 @@ k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea h1:3QOH5+2fGsY8e1qf+GIFpg+zw/JGNrgyZRQR7/m6uWg= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8= k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= @@ -1190,6 +1201,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg= sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/gateway-api v0.5.0 h1:ze+k9fJqvmL8s1t3e4q1ST8RnN+f09dEv+gfacahlAE= +sigs.k8s.io/gateway-api v0.5.0/go.mod h1:x0AP6gugkFV8fC/oTlnOMU0pnmuzIR8LfIPRVUjxSqA= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= diff --git a/main.go b/main.go index bf89ed2f..7ef63405 100644 --- a/main.go +++ b/main.go @@ -75,7 +75,7 @@ const ( initDBJobCMNameFlg = "initdb-job-configmap-name" enableBootstrapStandbyFromS3Flg = "enable-bootsrtap-standby-from-s3" enableSuperUserForDBOFlg = "enable-superuser-for-dbo" - tlsSubDomainFlg = "tls-sub-domain" + tlsClusterIssuerFlg = "tls-cluster-issuer" ) var ( @@ -117,7 +117,7 @@ func main() { etcdPSPName string postgresletFullname string initDBJobCMName string - tlsSubDomain string + tlsClusterIssuer string enableLeaderElection bool enableCRDValidation bool @@ -279,9 +279,9 @@ func main() { viper.SetDefault(enableSuperUserForDBOFlg, false) enableSuperUserForDBO = viper.GetBool(enableSuperUserForDBOFlg) - tlsSubDomain = viper.GetString(tlsSubDomainFlg) + tlsClusterIssuer = viper.GetString(tlsClusterIssuerFlg) enableCustomTLSCert := false - if tlsSubDomain != "" { + if tlsClusterIssuer != "" { enableCustomTLSCert = true } @@ -325,7 +325,7 @@ func main() { initDBJobCMNameFlg, initDBJobCMName, enableBootstrapStandbyFromS3Flg, enableBootstrapStandbyFromS3, enableSuperUserForDBOFlg, enableSuperUserForDBO, - tlsSubDomainFlg, tlsSubDomain, + tlsClusterIssuerFlg, tlsClusterIssuer, ) svcClusterConf := ctrl.GetConfigOrDie() @@ -410,7 +410,6 @@ func main() { StandbyClustersSourceRanges: standbyClusterSourceRanges, EnableLBSourceRanges: enableLBSourceRanges, EnableForceSharedIP: enableForceSharedIP, - TLSSubDomain: tlsSubDomain, } if err = (&controllers.PostgresReconciler{ CtrlClient: ctrlPlaneClusterMgr.GetClient(), @@ -439,6 +438,7 @@ func main() { EnableBootstrapStandbyFromS3: enableBootstrapStandbyFromS3, EnableSuperUserForDBO: enableSuperUserForDBO, EnableCustomTLSCert: enableCustomTLSCert, + TLSClusterIssuer: tlsClusterIssuer, }).SetupWithManager(ctrlPlaneClusterMgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Postgres") os.Exit(1) diff --git a/pkg/lbmanager/lbmanager.go b/pkg/lbmanager/lbmanager.go index 183cdd20..32fac43b 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -21,7 +21,6 @@ type Options struct { StandbyClustersSourceRanges []string EnableLBSourceRanges bool EnableForceSharedIP bool - TLSSubDomain string } // LBManager Responsible for the creation and deletion of externally accessible Services to access the Postgresql clusters managed by the Postgreslet. @@ -94,7 +93,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg lbIPToUse = "" } - svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) + svc := in.ToSharedSvcLB(lbIPToUse, nextFreePort, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges svc.Spec.LoadBalancerSourceRanges = []string{} @@ -105,7 +104,7 @@ func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postg return nil } - updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges, m.options.TLSSubDomain) + updated := in.ToSharedSvcLB("", 0, m.options.EnableStandbyLeaderSelector, m.options.EnableLegacyStandbySelector, m.options.StandbyClustersSourceRanges) // update the selector, and only the selector (we do NOT want the change the ip or port here!!!) svc.Spec.Selector = updated.Spec.Selector // also update the source ranges @@ -145,7 +144,7 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po sharedSvcLbAlsoEnabled := in.EnableSharedSVCLB(m.options.EnableForceSharedIP) - new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, sharedSvcLbAlsoEnabled, m.options.TLSSubDomain) + new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, sharedSvcLbAlsoEnabled) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges new.Spec.LoadBalancerSourceRanges = []string{} From 986c2f802ec25c7b1ccaf8d6e9da644a290ff351 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 7 Jun 2024 15:02:44 +0200 Subject: [PATCH 18/24] Set temporariy default value for testing --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 7ef63405..75820639 100644 --- a/main.go +++ b/main.go @@ -279,6 +279,7 @@ func main() { viper.SetDefault(enableSuperUserForDBOFlg, false) enableSuperUserForDBO = viper.GetBool(enableSuperUserForDBOFlg) + viper.SetDefault(tlsClusterIssuerFlg, "pgaas-ca-issuer") // TODO remove, just for testing tlsClusterIssuer = viper.GetString(tlsClusterIssuerFlg) enableCustomTLSCert := false if tlsClusterIssuer != "" { From 3913ff4253abe82c73c6158a1079521dd2f60f33 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 7 Jun 2024 15:09:20 +0200 Subject: [PATCH 19/24] Add log --- controllers/postgres_controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index e4604642..25886e7f 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -1740,5 +1740,6 @@ func (r *PostgresReconciler) createOrUpdateCertificate(log logr.Logger, ctx cont return fmt.Errorf("unable to create or update certificate: %w", err) } + log.V(debugLogLevel).Info("certificate created or updated") return nil } From 81aa41d66d4af3e9a23ad3051fd851ff8baba9d9 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Fri, 7 Jun 2024 15:20:15 +0200 Subject: [PATCH 20/24] AddToScheme --- main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.go b/main.go index 75820639..9988f39d 100644 --- a/main.go +++ b/main.go @@ -31,7 +31,9 @@ import ( firewall "github.com/metal-stack/firewall-controller/api/v1" "github.com/spf13/viper" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + // +kubebuilder:scaffold:imports + cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" ) const ( @@ -91,6 +93,7 @@ func init() { _ = zalando.AddToScheme(scheme) _ = coreosv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme + _ = cmapi.AddToScheme(scheme) } func main() { From 3d1123fc36b873d2884332440e1576ec6ae41afb Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Tue, 11 Jun 2024 17:36:57 +0200 Subject: [PATCH 21/24] Switch secret name to static string from docs --- api/v1/postgres_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index 0fce1760..478d49c3 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -647,7 +647,7 @@ func (p *Postgres) ToDNSName(tlsSubDomain string) string { } func (p *Postgres) ToTLSSecretName() string { - return p.generateDatabaseName() + "-cert" + return "pg-tls" } func (p *Postgres) ToPeripheralResourceLookupKey() types.NamespacedName { From 472d04ae333dacf6e4edcac74a2d02a488bd6d82 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Tue, 11 Jun 2024 17:39:58 +0200 Subject: [PATCH 22/24] * Make TLS subdomain configurable too * Use (obfuscated) commonName in cert when tls subdomain is configured (and possibly publicly announced) --- controllers/postgres_controller.go | 7 ++++++- main.go | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index 25886e7f..97e416a7 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -98,6 +98,7 @@ type PostgresReconciler struct { EnableSuperUserForDBO bool EnableCustomTLSCert bool TLSClusterIssuer string + TLSSubDomain string } // Reconcile is the entry point for postgres reconciliation. @@ -1723,11 +1724,15 @@ func (r *PostgresReconciler) ensureInitDBJob(log logr.Logger, ctx context.Contex } func (r *PostgresReconciler) createOrUpdateCertificate(log logr.Logger, ctx context.Context, instance *pg.Postgres) error { + commonName := instance.ToPeripheralResourceName() + if r.TLSSubDomain != "" { + commonName = instance.ToDNSName(r.TLSSubDomain) + } c := &cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{Name: instance.ToPeripheralResourceName(), Namespace: instance.ToPeripheralResourceNamespace()}} if _, err := controllerutil.CreateOrUpdate(ctx, r.SvcClient, c, func() error { c.Spec = cmapi.CertificateSpec{ - CommonName: instance.ToPeripheralResourceName(), + CommonName: commonName, SecretName: instance.ToTLSSecretName(), IssuerRef: cmmeta.ObjectReference{ Group: "cert-manager.io", diff --git a/main.go b/main.go index 9988f39d..3d56dc65 100644 --- a/main.go +++ b/main.go @@ -78,6 +78,7 @@ const ( enableBootstrapStandbyFromS3Flg = "enable-bootsrtap-standby-from-s3" enableSuperUserForDBOFlg = "enable-superuser-for-dbo" tlsClusterIssuerFlg = "tls-cluster-issuer" + tlsSubDomainFlg = "tls-sub-domain" ) var ( @@ -121,6 +122,7 @@ func main() { postgresletFullname string initDBJobCMName string tlsClusterIssuer string + tlsSubDomain string enableLeaderElection bool enableCRDValidation bool @@ -288,6 +290,7 @@ func main() { if tlsClusterIssuer != "" { enableCustomTLSCert = true } + tlsSubDomain = viper.GetString(tlsSubDomainFlg) ctrl.Log.Info("flag", metricsAddrSvcMgrFlg, metricsAddrSvcMgr, @@ -330,6 +333,7 @@ func main() { enableBootstrapStandbyFromS3Flg, enableBootstrapStandbyFromS3, enableSuperUserForDBOFlg, enableSuperUserForDBO, tlsClusterIssuerFlg, tlsClusterIssuer, + tlsSubDomainFlg, tlsSubDomain, ) svcClusterConf := ctrl.GetConfigOrDie() @@ -443,6 +447,7 @@ func main() { EnableSuperUserForDBO: enableSuperUserForDBO, EnableCustomTLSCert: enableCustomTLSCert, TLSClusterIssuer: tlsClusterIssuer, + TLSSubDomain: tlsSubDomain, }).SetupWithManager(ctrlPlaneClusterMgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Postgres") os.Exit(1) From 8168e5cb6e5fe1645d4e7382fcf83183068ecfc6 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Wed, 12 Jun 2024 08:59:45 +0200 Subject: [PATCH 23/24] Remove (test) default value --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index 3d56dc65..14bd1ce3 100644 --- a/main.go +++ b/main.go @@ -284,7 +284,6 @@ func main() { viper.SetDefault(enableSuperUserForDBOFlg, false) enableSuperUserForDBO = viper.GetBool(enableSuperUserForDBOFlg) - viper.SetDefault(tlsClusterIssuerFlg, "pgaas-ca-issuer") // TODO remove, just for testing tlsClusterIssuer = viper.GetString(tlsClusterIssuerFlg) enableCustomTLSCert := false if tlsClusterIssuer != "" { From 4c678e692b36128e4a83fb0e49d59e52b040b4c4 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Wed, 12 Jun 2024 09:07:20 +0200 Subject: [PATCH 24/24] Disable certificate creation when not configured --- controllers/postgres_controller.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index 97e416a7..08914dd2 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -1724,6 +1724,11 @@ func (r *PostgresReconciler) ensureInitDBJob(log logr.Logger, ctx context.Contex } func (r *PostgresReconciler) createOrUpdateCertificate(log logr.Logger, ctx context.Context, instance *pg.Postgres) error { + if r.TLSClusterIssuer == "" { + log.V(debugLogLevel).Info("certificate skipped") + return nil + } + commonName := instance.ToPeripheralResourceName() if r.TLSSubDomain != "" { commonName = instance.ToDNSName(r.TLSSubDomain)