mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-18 10:08:40 +02:00
refactor pooler tls support and set pooler pod security context (#2255)
* bump pooler image * set pooler pod security context * use hard coded RunAsUser 100 and RunAsGroup 101 for pooler pod * unify generation of TLS secret mounts * extend documentation on tls support * add unit test for testing TLS support for pooler * add e2e test for tls support
This commit is contained in:
@@ -3,7 +3,6 @@ package cluster
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -25,6 +24,9 @@ import (
|
||||
"github.com/zalando/postgres-operator/pkg/util/retryutil"
|
||||
)
|
||||
|
||||
var poolerRunAsUser = int64(100)
|
||||
var poolerRunAsGroup = int64(101)
|
||||
|
||||
// ConnectionPoolerObjects K8s objects that are belong to connection pooler
|
||||
type ConnectionPoolerObjects struct {
|
||||
Deployment *appsv1.Deployment
|
||||
@@ -261,6 +263,10 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
|
||||
makeDefaultConnectionPoolerResources(&c.OpConfig),
|
||||
connectionPoolerContainer)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not generate resource requirements: %v", err)
|
||||
}
|
||||
|
||||
effectiveDockerImage := util.Coalesce(
|
||||
connectionPoolerSpec.DockerImage,
|
||||
c.OpConfig.ConnectionPooler.Image)
|
||||
@@ -269,10 +275,6 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
|
||||
connectionPoolerSpec.Schema,
|
||||
c.OpConfig.ConnectionPooler.Schema)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not generate resource requirements: %v", err)
|
||||
}
|
||||
|
||||
secretSelector := func(key string) *v1.SecretKeySelector {
|
||||
effectiveUser := util.Coalesce(
|
||||
connectionPoolerSpec.User,
|
||||
@@ -344,62 +346,53 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
|
||||
// 2. Reference the secret in a volume
|
||||
// 3. Mount the volume to the container at /tls
|
||||
var poolerVolumes []v1.Volume
|
||||
var volumeMounts []v1.VolumeMount
|
||||
if spec.TLS != nil && spec.TLS.SecretName != "" {
|
||||
// Env vars
|
||||
crtFile := spec.TLS.CertificateFile
|
||||
keyFile := spec.TLS.PrivateKeyFile
|
||||
caFile := spec.TLS.CAFile
|
||||
mountPath := "/tls"
|
||||
mountPathCA := mountPath
|
||||
getPoolerTLSEnv := func(k string) string {
|
||||
keyName := ""
|
||||
switch k {
|
||||
case "tls.crt":
|
||||
keyName = "CONNECTION_POOLER_CLIENT_TLS_CRT"
|
||||
case "tls.key":
|
||||
keyName = "CONNECTION_POOLER_CLIENT_TLS_KEY"
|
||||
case "tls.ca":
|
||||
keyName = "CONNECTION_POOLER_CLIENT_CA_FILE"
|
||||
default:
|
||||
panic(fmt.Sprintf("TLS env key for pooler unknown %s", k))
|
||||
}
|
||||
|
||||
if crtFile == "" {
|
||||
crtFile = "tls.crt"
|
||||
return keyName
|
||||
}
|
||||
if keyFile == "" {
|
||||
keyFile = "tls.key"
|
||||
tlsEnv, tlsVolumes := generateTlsMounts(spec, getPoolerTLSEnv)
|
||||
envVars = append(envVars, tlsEnv...)
|
||||
for _, vol := range tlsVolumes {
|
||||
poolerVolumes = append(poolerVolumes, v1.Volume{
|
||||
Name: vol.Name,
|
||||
VolumeSource: vol.VolumeSource,
|
||||
})
|
||||
volumeMounts = append(volumeMounts, v1.VolumeMount{
|
||||
Name: vol.Name,
|
||||
MountPath: vol.MountPath,
|
||||
})
|
||||
}
|
||||
if caFile == "" {
|
||||
caFile = "ca.crt"
|
||||
}
|
||||
if spec.TLS.CASecretName != "" {
|
||||
mountPathCA = mountPath + "ca"
|
||||
}
|
||||
|
||||
envVars = append(
|
||||
envVars,
|
||||
v1.EnvVar{
|
||||
Name: "CONNECTION_POOLER_CLIENT_TLS_CRT", Value: filepath.Join(mountPath, crtFile),
|
||||
},
|
||||
v1.EnvVar{
|
||||
Name: "CONNECTION_POOLER_CLIENT_TLS_KEY", Value: filepath.Join(mountPath, keyFile),
|
||||
},
|
||||
v1.EnvVar{
|
||||
Name: "CONNECTION_POOLER_CLIENT_CA_FILE", Value: filepath.Join(mountPathCA, caFile),
|
||||
},
|
||||
)
|
||||
|
||||
// Volume
|
||||
mode := int32(0640)
|
||||
volume := v1.Volume{
|
||||
Name: "tls",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{
|
||||
SecretName: spec.TLS.SecretName,
|
||||
DefaultMode: &mode,
|
||||
},
|
||||
},
|
||||
}
|
||||
poolerVolumes = append(poolerVolumes, volume)
|
||||
|
||||
// Mount
|
||||
poolerContainer.VolumeMounts = []v1.VolumeMount{{
|
||||
Name: "tls",
|
||||
MountPath: "/tls",
|
||||
}}
|
||||
}
|
||||
|
||||
poolerContainer.Env = envVars
|
||||
poolerContainer.VolumeMounts = volumeMounts
|
||||
tolerationsSpec := tolerations(&spec.Tolerations, c.OpConfig.PodToleration)
|
||||
securityContext := v1.PodSecurityContext{}
|
||||
|
||||
// determine the User, Group and FSGroup for the pooler pod
|
||||
securityContext.RunAsUser = &poolerRunAsUser
|
||||
securityContext.RunAsGroup = &poolerRunAsGroup
|
||||
|
||||
effectiveFSGroup := c.OpConfig.Resources.SpiloFSGroup
|
||||
if spec.SpiloFSGroup != nil {
|
||||
effectiveFSGroup = spec.SpiloFSGroup
|
||||
}
|
||||
if effectiveFSGroup != nil {
|
||||
securityContext.FSGroup = effectiveFSGroup
|
||||
}
|
||||
|
||||
podTemplate := &v1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -412,15 +405,10 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
|
||||
Containers: []v1.Container{poolerContainer},
|
||||
Tolerations: tolerationsSpec,
|
||||
Volumes: poolerVolumes,
|
||||
SecurityContext: &securityContext,
|
||||
},
|
||||
}
|
||||
|
||||
if spec.TLS != nil && spec.TLS.SecretName != "" && spec.SpiloFSGroup != nil {
|
||||
podTemplate.Spec.SecurityContext = &v1.PodSecurityContext{
|
||||
FSGroup: spec.SpiloFSGroup,
|
||||
}
|
||||
}
|
||||
|
||||
nodeAffinity := c.nodeAffinity(c.OpConfig.NodeReadinessLabel, spec.NodeAffinity)
|
||||
if c.OpConfig.EnablePodAntiAffinity {
|
||||
labelsSet := labels.Set(c.connectionPoolerLabels(role, false).MatchLabels)
|
||||
|
||||
Reference in New Issue
Block a user