diff --git a/api/v1/postgres_types.go b/api/v1/postgres_types.go index e5140d69..478d49c3 100644 --- a/api/v1/postgres_types.go +++ b/api/v1/postgres_types.go @@ -420,7 +420,26 @@ func (p *Postgres) ToSharedSvcLBNamespacedName() *types.NamespacedName { } } -func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSourceRanges []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) *corev1.Service { lb := &corev1.Service{} lb.Spec.Type = "LoadBalancer" @@ -430,6 +449,8 @@ func (p *Postgres) ToDedicatedSvcLB(lbIP string, lbPort int32, standbyClustersSo lb.Name = p.ToDedicatedSvcLBName() lb.SetLabels(SvcLoadBalancerLabel) + lb.Annotations = map[string]string{} + lbsr := []string{} if p.HasSourceRanges() { for _, src := range p.Spec.AccessList.SourceRanges { @@ -485,6 +506,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() @@ -600,6 +635,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 "pg-tls" +} + func (p *Postgres) ToPeripheralResourceLookupKey() types.NamespacedName { return types.NamespacedName{ Namespace: p.ToPeripheralResourceNamespace(), @@ -607,7 +657,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 +784,12 @@ func (p *Postgres) ToUnstructuredZalandoPostgresql(z *zalando.Postgresql, c *cor } } + if enableTlsCert { + z.Spec.TLS = &zalando.TLSDescription{ + SecretName: p.ToTLSSecretName(), + } + } + 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/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 { diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index f345a4cb..08914dd2 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 ( @@ -93,6 +96,9 @@ type PostgresReconciler struct { InitDBJobConfigMapName string EnableBootstrapStandbyFromS3 bool EnableSuperUserForDBO bool + EnableCustomTLSCert bool + TLSClusterIssuer string + TLSSubDomain string } // Reconcile is the entry point for postgres reconciliation. @@ -237,6 +243,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) @@ -373,7 +385,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, restoreSourceInstance, patroniTTL, patroniLoopWait, patroniRetryTimeout, r.EnableSuperUserForDBO) + u, err := instance.ToUnstructuredZalandoPostgresql(nil, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSourceInstance, patroniTTL, patroniLoopWait, patroniRetryTimeout, r.EnableSuperUserForDBO, r.EnableCustomTLSCert) if err != nil { return fmt.Errorf("failed to convert to unstructured zalando postgresql: %w", err) } @@ -389,7 +401,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, restoreSourceInstance, patroniTTL, patroniLoopWait, patroniRetryTimeout, r.EnableSuperUserForDBO) + u, err := instance.ToUnstructuredZalandoPostgresql(rawZ, sidecarsCM, r.StorageClass, r.PgParamBlockList, restoreBackupConfig, restoreSourceInstance, patroniTTL, patroniLoopWait, patroniRetryTimeout, r.EnableSuperUserForDBO, r.EnableCustomTLSCert) if err != nil { return fmt.Errorf("failed to convert to unstructured zalando postgresql: %w", err) } @@ -1710,3 +1722,34 @@ 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 { + if r.TLSClusterIssuer == "" { + log.V(debugLogLevel).Info("certificate skipped") + return nil + } + + 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: commonName, + 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) + } + + log.V(debugLogLevel).Info("certificate created or updated") + return nil +} diff --git a/controllers/status_controller.go b/controllers/status_controller.go index d446940b..ffb61309 100644 --- a/controllers/status_controller.go +++ b/controllers/status_controller.go @@ -97,13 +97,14 @@ func (r *StatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } log.V(debugLogLevel).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 additional sockets } else { // Todo: Handle errors other than `NotFound` 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 2671b539..14bd1ce3 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 ( @@ -75,6 +77,8 @@ const ( initDBJobCMNameFlg = "initdb-job-configmap-name" enableBootstrapStandbyFromS3Flg = "enable-bootsrtap-standby-from-s3" enableSuperUserForDBOFlg = "enable-superuser-for-dbo" + tlsClusterIssuerFlg = "tls-cluster-issuer" + tlsSubDomainFlg = "tls-sub-domain" ) var ( @@ -90,6 +94,7 @@ func init() { _ = zalando.AddToScheme(scheme) _ = coreosv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme + _ = cmapi.AddToScheme(scheme) } func main() { @@ -116,6 +121,8 @@ func main() { etcdPSPName string postgresletFullname string initDBJobCMName string + tlsClusterIssuer string + tlsSubDomain string enableLeaderElection bool enableCRDValidation bool @@ -277,6 +284,13 @@ func main() { viper.SetDefault(enableSuperUserForDBOFlg, false) enableSuperUserForDBO = viper.GetBool(enableSuperUserForDBOFlg) + tlsClusterIssuer = viper.GetString(tlsClusterIssuerFlg) + enableCustomTLSCert := false + if tlsClusterIssuer != "" { + enableCustomTLSCert = true + } + tlsSubDomain = viper.GetString(tlsSubDomainFlg) + ctrl.Log.Info("flag", metricsAddrSvcMgrFlg, metricsAddrSvcMgr, metricsAddrCtrlMgrFlg, metricsAddrCtrlMgr, @@ -317,6 +331,8 @@ func main() { initDBJobCMNameFlg, initDBJobCMName, enableBootstrapStandbyFromS3Flg, enableBootstrapStandbyFromS3, enableSuperUserForDBOFlg, enableSuperUserForDBO, + tlsClusterIssuerFlg, tlsClusterIssuer, + tlsSubDomainFlg, tlsSubDomain, ) svcClusterConf := ctrl.GetConfigOrDie() @@ -428,6 +444,9 @@ func main() { InitDBJobConfigMapName: initDBJobCMName, EnableBootstrapStandbyFromS3: enableBootstrapStandbyFromS3, EnableSuperUserForDBO: enableSuperUserForDBO, + EnableCustomTLSCert: enableCustomTLSCert, + TLSClusterIssuer: tlsClusterIssuer, + TLSSubDomain: tlsSubDomain, }).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 41973946..32fac43b 100644 --- a/pkg/lbmanager/lbmanager.go +++ b/pkg/lbmanager/lbmanager.go @@ -59,7 +59,7 @@ 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 necessary func (m *LBManager) CreateOrUpdateSharedSvcLB(ctx context.Context, in *api.Postgres) error { - if m.options.EnableForceSharedIP != true && in.Spec.DedicatedLoadBalancerIP != nil && *in.Spec.DedicatedLoadBalancerIP != "" { + if !in.EnableSharedSVCLB(m.options.EnableForceSharedIP) { // TODO logging? err := m.DeleteSharedSvcLB(ctx, in) if err != nil { @@ -115,6 +115,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) @@ -125,7 +127,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 necessary 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 { @@ -140,7 +142,9 @@ func (m *LBManager) CreateOrUpdateDedicatedSvcLB(ctx context.Context, in *api.Po } var lbIPToUse string = *in.Spec.DedicatedLoadBalancerIP - new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges) + sharedSvcLbAlsoEnabled := in.EnableSharedSVCLB(m.options.EnableForceSharedIP) + + new := in.ToDedicatedSvcLB(lbIPToUse, nextFreePort, m.options.StandbyClustersSourceRanges, sharedSvcLbAlsoEnabled) if !m.options.EnableLBSourceRanges { // leave empty / disable source ranges new.Spec.LoadBalancerSourceRanges = []string{} @@ -164,6 +168,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) } diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index 2e01b6eb..4b0f573d 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -52,6 +52,7 @@ const ( localSidecarsCMName = "postgres-sidecars-configmap" + spilo_fsgroup = "103" debugLogLevel int = 1 ) @@ -433,6 +434,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