diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index 82a737ae6..9ae7b1c91 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -173,6 +173,9 @@ spec: enable_init_containers: type: boolean default: true + enable_cross_namespace_secret: + type: boolean + default: false enable_pod_antiaffinity: type: boolean default: false diff --git a/charts/postgres-operator/crds/postgresqls.yaml b/charts/postgres-operator/crds/postgresqls.yaml index eb628863d..aead7fe69 100644 --- a/charts/postgres-operator/crds/postgresqls.yaml +++ b/charts/postgres-operator/crds/postgresqls.yaml @@ -515,8 +515,6 @@ spec: type: integer useLoadBalancer: # deprecated type: boolean - enableNamespacedSecret: - type: boolean users: type: object additionalProperties: diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 287835a24..32160cf5a 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -97,6 +97,8 @@ configKubernetes: # - deployment-time # - downscaler/* + # allow user secrets in other namespaces than the Postgres cluster + enable_cross_namespace_secret: false # enables initContainers to run actions before Spilo is started enable_init_containers: true # toggles pod anti affinity on the Postgres pods @@ -151,7 +153,7 @@ configKubernetes: # template for database user secrets generated by the operator, # here username contains the namespace in the format namespace.username # if the user is in different namespace than cluster and cross namespace secrets - # are enabled via EnableNamespacedSecret flag. + # are enabled via `enable_cross_namespace_secret` flag in the configuration. secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" # set user and group for the spilo container (required to run Spilo as non-root process) # spilo_runasuser: 101 diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index 1b1ae852e..2217d87bb 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -264,6 +264,13 @@ configuration they are grouped under the `kubernetes` key. [admin docs](../administrator.md#pod-disruption-budget) for more information. Default is true. +* **enable_cross_namespace_secrets** + To allow secrets in a different namespace other than the Postgres cluster + namespace. Once enabled, specify the namespace in the user name under the + `users` section in the form `{namespace}.{username}`. The operator will then + create the user secret in that namespace. The part after the first `.` is + considered to be the user name. The default is `false`. + * **enable_init_containers** global option to allow for creating init containers in the cluster manifest to run actions before Spilo is started. Default is true. @@ -275,13 +282,12 @@ configuration they are grouped under the `kubernetes` key. * **secret_name_template** a template for the name of the database user secrets generated by the - operator. `{namespace}` is replaced with name of the namespace (if cross - namespace secrets are enabled via EnableNamespacedSecret flag, otherwise the - secret is in cluster's namespace and in that case it is not present in secret - name), `{username}` is replaced with name of the secret, `{cluster}` with the - name of the cluster, `{tprkind}` with the kind of CRD (formerly known as TPR) - and `{tprgroup}` with the group of the CRD. No other placeholders are allowed. - The default is + operator. `{namespace}` is replaced with name of the namespace if + `enable_cross_namespace_secret` is set, otherwise the + secret is in cluster's namespace. `{username}` is replaced with name of the + secret, `{cluster}` with the name of the cluster, `{tprkind}` with the kind + of CRD (formerly known as TPR) and `{tprgroup}` with the group of the CRD. + No other placeholders are allowed. The default is `{namespace}.{username}.{cluster}.credentials.{tprkind}.{tprgroup}`. * **cluster_domain** diff --git a/docs/user.md b/docs/user.md index 245385a2b..47d10e7e0 100644 --- a/docs/user.md +++ b/docs/user.md @@ -140,7 +140,7 @@ At the moment it is not possible to define membership of the manifest role in other roles. To define the secrets for the users in a different namespace than that of the cluster, -one can use the flag `EnableNamespacedSecret` and declare the namespace for the +one can set `enable_cross_namespace_secret` and declare the namespace for the secrets in the manifest in the following manner, ```yaml diff --git a/e2e/tests/test_e2e.py b/e2e/tests/test_e2e.py index 30d0cfe2f..5815af24d 100644 --- a/e2e/tests/test_e2e.py +++ b/e2e/tests/test_e2e.py @@ -598,29 +598,36 @@ def test_zz_cross_namespace_secrets(self): self.k8s.api.core_v1.create_namespace(v1_appnamespace) self.k8s.wait_for_namespace_creation(app_namespace) + patch_cross_namespace_secret = { + "data": { + "enable_cross_namespace_secret": "true" + } + } + self.k8s.update_config(patch_cross_namespace_secret, + step="cross namespace secrets enabled") + self.k8s.api.custom_objects_api.patch_namespaced_custom_object( 'acid.zalan.do', 'v1', 'default', 'postgresqls', 'acid-minimal-cluster', { 'spec': { - 'enableNamespacedSecret': True, 'users':{ 'appspace.db_user': [], } } }) + self.eventuallyEqual(lambda: self.k8s.count_secrets_with_label("cluster-name=acid-minimal-cluster,application=spilo", app_namespace), 1, "Secret not created for user in namespace") #reset the flag - self.k8s.api.custom_objects_api.patch_namespaced_custom_object( - 'acid.zalan.do', 'v1', 'default', - 'postgresqls', 'acid-minimal-cluster', - { - 'spec': { - 'enableNamespacedSecret': False, + unpatch_cross_namespace_secret = { + "data": { + "enable_cross_namespace_secret": "false", } - }) + } + self.k8s.update_config(unpatch_cross_namespace_secret, step="disable cross namespace secrets") + @timeout_decorator.timeout(TEST_TIMEOUT_SEC) def test_lazy_spilo_upgrade(self): diff --git a/manifests/complete-postgres-manifest.yaml b/manifests/complete-postgres-manifest.yaml index 5f995de15..6e2acbdd3 100644 --- a/manifests/complete-postgres-manifest.yaml +++ b/manifests/complete-postgres-manifest.yaml @@ -12,7 +12,6 @@ spec: dockerImage: registry.opensource.zalan.do/acid/spilo-13:2.0-p7 teamId: "acid" numberOfInstances: 2 - enableNamespacedSecret: False users: # Application/Robot users zalando: - superuser diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index 7a05135ab..96072644d 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -36,6 +36,7 @@ data: # downscaler_annotations: "deployment-time,downscaler/*" # enable_admin_role_for_users: "true" # enable_crd_validation: "true" + # enable_cross_namespace_secret: "false" # enable_database_access: "true" enable_ebs_gp3_migration: "false" # enable_ebs_gp3_migration_max_size: "1000" diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml index bd6f321dd..e869498ba 100644 --- a/manifests/postgresql-operator-default-configuration.yaml +++ b/manifests/postgresql-operator-default-configuration.yaml @@ -45,6 +45,7 @@ configuration: # downscaler_annotations: # - deployment-time # - downscaler/* + # enable_cross_namespace_secret: "false" enable_init_containers: true enable_pod_antiaffinity: false enable_pod_disruption_budget: true diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index ae91a9f38..6ca754bbb 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -730,9 +730,6 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{ Type: "boolean", Description: "Deprecated", }, - "enableNamespacedSecret": { - Type: "boolean", - }, "users": { Type: "object", AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ @@ -1029,6 +1026,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ }, }, }, + "enable_cross_namespace_secret": { + Type: "boolean", + }, "enable_init_containers": { Type: "boolean", }, diff --git a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go index cf581431b..8023864cf 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -91,6 +91,7 @@ type KubernetesMetaConfiguration struct { EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"` PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"` PodManagementPolicy string `json:"pod_management_policy,omitempty"` + EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"` } // PostgresPodResourcesDefaults defines the spec of default resources diff --git a/pkg/apis/acid.zalan.do/v1/postgresql_type.go b/pkg/apis/acid.zalan.do/v1/postgresql_type.go index 1787f5b4e..7346fb0e5 100644 --- a/pkg/apis/acid.zalan.do/v1/postgresql_type.go +++ b/pkg/apis/acid.zalan.do/v1/postgresql_type.go @@ -53,28 +53,27 @@ type PostgresSpec struct { // load balancers' source ranges are the same for master and replica services AllowedSourceRanges []string `json:"allowedSourceRanges"` - NumberOfInstances int32 `json:"numberOfInstances"` - EnableNamespacedSecret *bool `json:"enableNamespacedSecret,omitempty"` - Users map[string]UserFlags `json:"users,omitempty"` - MaintenanceWindows []MaintenanceWindow `json:"maintenanceWindows,omitempty"` - Clone *CloneDescription `json:"clone,omitempty"` - ClusterName string `json:"-"` - Databases map[string]string `json:"databases,omitempty"` - PreparedDatabases map[string]PreparedDatabase `json:"preparedDatabases,omitempty"` - SchedulerName *string `json:"schedulerName,omitempty"` - NodeAffinity *v1.NodeAffinity `json:"nodeAffinity,omitempty"` - Tolerations []v1.Toleration `json:"tolerations,omitempty"` - Sidecars []Sidecar `json:"sidecars,omitempty"` - InitContainers []v1.Container `json:"initContainers,omitempty"` - PodPriorityClassName string `json:"podPriorityClassName,omitempty"` - ShmVolume *bool `json:"enableShmVolume,omitempty"` - EnableLogicalBackup bool `json:"enableLogicalBackup,omitempty"` - LogicalBackupSchedule string `json:"logicalBackupSchedule,omitempty"` - StandbyCluster *StandbyDescription `json:"standby,omitempty"` - PodAnnotations map[string]string `json:"podAnnotations,omitempty"` - ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"` - TLS *TLSDescription `json:"tls,omitempty"` - AdditionalVolumes []AdditionalVolume `json:"additionalVolumes,omitempty"` + NumberOfInstances int32 `json:"numberOfInstances"` + Users map[string]UserFlags `json:"users,omitempty"` + MaintenanceWindows []MaintenanceWindow `json:"maintenanceWindows,omitempty"` + Clone *CloneDescription `json:"clone,omitempty"` + ClusterName string `json:"-"` + Databases map[string]string `json:"databases,omitempty"` + PreparedDatabases map[string]PreparedDatabase `json:"preparedDatabases,omitempty"` + SchedulerName *string `json:"schedulerName,omitempty"` + NodeAffinity *v1.NodeAffinity `json:"nodeAffinity,omitempty"` + Tolerations []v1.Toleration `json:"tolerations,omitempty"` + Sidecars []Sidecar `json:"sidecars,omitempty"` + InitContainers []v1.Container `json:"initContainers,omitempty"` + PodPriorityClassName string `json:"podPriorityClassName,omitempty"` + ShmVolume *bool `json:"enableShmVolume,omitempty"` + EnableLogicalBackup bool `json:"enableLogicalBackup,omitempty"` + LogicalBackupSchedule string `json:"logicalBackupSchedule,omitempty"` + StandbyCluster *StandbyDescription `json:"standby,omitempty"` + PodAnnotations map[string]string `json:"podAnnotations,omitempty"` + ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"` + TLS *TLSDescription `json:"tls,omitempty"` + AdditionalVolumes []AdditionalVolume `json:"additionalVolumes,omitempty"` // deprecated json tags InitContainersOld []v1.Container `json:"init_containers,omitempty"` diff --git a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go index bad75ffd8..584a72143 100644 --- a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go +++ b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go @@ -614,11 +614,6 @@ func (in *PostgresSpec) DeepCopyInto(out *PostgresSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.EnableNamespacedSecret != nil { - in, out := &in.EnableNamespacedSecret, &out.EnableNamespacedSecret - *out = new(bool) - **out = **in - } if in.Users != nil { in, out := &in.Users, &out.Users *out = make(map[string]UserFlags, len(*in)) diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index f56a0d1e4..c9abb10fd 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -1163,8 +1163,7 @@ func (c *Cluster) initRobotUsers() error { namespace := c.Namespace //if namespaced secrets are allowed - if c.Postgresql.Spec.EnableNamespacedSecret != nil && - *c.Postgresql.Spec.EnableNamespacedSecret { + if c.Config.OpConfig.EnableCrossNamespaceSecret { if strings.Contains(username, ".") { splits := strings.Split(username, ".") namespace = splits[0] diff --git a/pkg/cluster/cluster_test.go b/pkg/cluster/cluster_test.go index 9e7f60906..dc1f5ff03 100644 --- a/pkg/cluster/cluster_test.go +++ b/pkg/cluster/cluster_test.go @@ -1024,7 +1024,6 @@ func TestCrossNamespacedSecrets(t *testing.T) { Volume: acidv1.Volume{ Size: "1Gi", }, - EnableNamespacedSecret: boolToPointer(true), Users: map[string]acidv1.UserFlags{ "appspace.db_user": {}, "db_user": {}, @@ -1052,6 +1051,7 @@ func TestCrossNamespacedSecrets(t *testing.T) { DefaultMemoryLimit: "300Mi", PodRoleLabel: "spilo-role", }, + EnableCrossNamespaceSecret: true, }, }, client, pg, logger, eventRecorder) diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 761cf1b60..1b9cfba96 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -82,6 +82,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.EnableSidecars = util.CoalesceBool(fromCRD.Kubernetes.EnableSidecars, util.True()) result.SecretNameTemplate = fromCRD.Kubernetes.SecretNameTemplate result.OAuthTokenSecretName = fromCRD.Kubernetes.OAuthTokenSecretName + result.EnableCrossNamespaceSecret = fromCRD.Kubernetes.EnableCrossNamespaceSecret result.InfrastructureRolesSecretName = fromCRD.Kubernetes.InfrastructureRolesSecretName if fromCRD.Kubernetes.InfrastructureRolesDefs != nil { diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 52530fb12..662161053 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -207,6 +207,7 @@ type Config struct { PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"` EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"` + EnableCrossNamespaceSecret bool `name:"enable_cross_namespace_secret" default:"false"` EnablePgVersionEnvVar bool `name:"enable_pgversion_env_var" default:"true"` EnableSpiloWalPathCompat bool `name:"enable_spilo_wal_path_compat" default:"false"` MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"`