From 6c79949888602b0a48636ef1933ed730614f4fb8 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 17:22:56 +0100 Subject: [PATCH 1/6] Patch clusterrole for use with psp and set serviceaccount name in configmap programatically --- pkg/operatormanager/operatormanager.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index 43c14111..a7626cc7 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -194,6 +194,16 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run // ClusterRole is not namespaced. key.Namespace = "" err = m.Get(ctx, key, &rbacv1.ClusterRole{}) + // Add our psp + + pspPolicyRule := rbacv1.PolicyRule{ + APIGroups: []string{"extensions"}, + Verbs: []string{"use"}, + Resources: []string{"podsecuritypolicies"}, + // TODO make psp name configurable + ResourceNames: []string{"postgres-operator-psp"}, + } + v.Rules = append(v.Rules, pspPolicyRule) case *rbacv1.ClusterRoleBinding: m.Log.Info("handling ClusterRoleBinding") // Set the namespace of the ServiceAccount in the ClusterRoleBinding. @@ -251,6 +261,8 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run func (m *OperatorManager) editConfigMap(cm *v1.ConfigMap, namespace, s3BucketURL string) { cm.Data["logical_backup_s3_bucket"] = s3BucketURL cm.Data["watched_namespace"] = namespace + // TODO don't use the same serviceaccount for operator and databases, see #88 + cm.Data["pod_service_account_name"] = "postgres-operator" } // ensureCleanMetadata ensures obj has clean metadata From 98d715e26cb6196880a5fbc75966a821d3f60f1a Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 17:50:04 +0100 Subject: [PATCH 2/6] Add the PSP to the chart --- .../templates/podsecuritypolicy.yaml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 charts/postgreslet/templates/podsecuritypolicy.yaml diff --git a/charts/postgreslet/templates/podsecuritypolicy.yaml b/charts/postgreslet/templates/podsecuritypolicy.yaml new file mode 100644 index 00000000..e6ac81e5 --- /dev/null +++ b/charts/postgreslet/templates/podsecuritypolicy.yaml @@ -0,0 +1,20 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: postgres-operator-psp +spec: + allowPrivilegeEscalation: true + fsGroup: + rule: RunAsAny + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - hostPath + - secret + - persistentVolumeClaim + - configMap + - emptyDir \ No newline at end of file From da9a88290d0b7450e4f43cf7d1bcb16832dfdfc6 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 17:58:03 +0100 Subject: [PATCH 3/6] Moved psp and serviceaccount names to variable --- pkg/operatormanager/operatormanager.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index a7626cc7..20edb44f 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -29,6 +29,15 @@ import ( // operatorPodMatchingLabels is for listing operator pods var operatorPodMatchingLabels = client.MatchingLabels{"name": "postgres-operator"} +// The name of our required psp +// TODO: read psp name from configmap +const pspName string = "postgres-operator-psp" + +// The serviceAccount name to use for the database pods. +// TODO: create new account per namespace +// TODO: use different account for operator and database +const serviceAccountName string = "postgres-operator" + // OperatorManager manages the operator type OperatorManager struct { client.Client @@ -201,7 +210,7 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run Verbs: []string{"use"}, Resources: []string{"podsecuritypolicies"}, // TODO make psp name configurable - ResourceNames: []string{"postgres-operator-psp"}, + ResourceNames: []string{pspName}, } v.Rules = append(v.Rules, pspPolicyRule) case *rbacv1.ClusterRoleBinding: @@ -262,7 +271,7 @@ func (m *OperatorManager) editConfigMap(cm *v1.ConfigMap, namespace, s3BucketURL cm.Data["logical_backup_s3_bucket"] = s3BucketURL cm.Data["watched_namespace"] = namespace // TODO don't use the same serviceaccount for operator and databases, see #88 - cm.Data["pod_service_account_name"] = "postgres-operator" + cm.Data["pod_service_account_name"] = serviceAccountName } // ensureCleanMetadata ensures obj has clean metadata From 23f7d33a25f7287c26bcb85fbddae07cf7bb0fa6 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 18:12:20 +0100 Subject: [PATCH 4/6] Make PSP name configurable vial CLI --- main.go | 5 +++-- pkg/operatormanager/operatormanager.go | 10 ++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 39e5c47a..a920ed48 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,7 @@ func init() { } func main() { - var metricsAddrCtrlMgr, metricsAddrSvcMgr, partitionID, tenant, ctrlClusterKubeconfig string + var metricsAddrCtrlMgr, metricsAddrSvcMgr, partitionID, tenant, ctrlClusterKubeconfig, pspName string var enableLeaderElection bool flag.StringVar(&metricsAddrSvcMgr, "metrics-addr-svc-mgr", ":8080", "The address the metric endpoint of the service cluster manager binds to.") flag.StringVar(&metricsAddrCtrlMgr, "metrics-addr-ctrl-mgr", "0", "The address the metric endpoint of the control cluster manager binds to.") @@ -55,6 +55,7 @@ func main() { flag.StringVar(&partitionID, "partition-id", "", "The partition ID of the worker-cluster.") flag.StringVar(&tenant, "tenant", "", "The tenant name.") flag.StringVar(&ctrlClusterKubeconfig, "controlplane-kubeconfig", "/var/run/secrets/postgreslet/kube/config", "The path to the kubeconfig to talk to the control plane") + flag.StringVar(&pspName, "custom-psp-name", "postgres-operator-psp", "The namem of our custom PodSecurityPolicy. Will be added to the ClusterRoles.") flag.Parse() ctrl.SetLogger(zap.New(zap.UseDevMode(true))) @@ -110,7 +111,7 @@ func main() { os.Exit(1) } - opMgr, err := operatormanager.New(svcClusterMgr.GetClient(), "external/svc-postgres-operator.yaml", scheme, ctrl.Log.WithName("OperatorManager")) + opMgr, err := operatormanager.New(svcClusterMgr.GetClient(), "external/svc-postgres-operator.yaml", scheme, ctrl.Log.WithName("OperatorManager"), pspName) if err != nil { setupLog.Error(err, "unable to create `OperatorManager`") os.Exit(1) diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index 20edb44f..232096f3 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -29,10 +29,6 @@ import ( // operatorPodMatchingLabels is for listing operator pods var operatorPodMatchingLabels = client.MatchingLabels{"name": "postgres-operator"} -// The name of our required psp -// TODO: read psp name from configmap -const pspName string = "postgres-operator-psp" - // The serviceAccount name to use for the database pods. // TODO: create new account per namespace // TODO: use different account for operator and database @@ -46,10 +42,11 @@ type OperatorManager struct { Log logr.Logger meta.MetadataAccessor *runtime.Scheme + pspName string } // New creates a new `OperatorManager` -func New(client client.Client, fileName string, scheme *runtime.Scheme, log logr.Logger) (*OperatorManager, error) { +func New(client client.Client, fileName string, scheme *runtime.Scheme, log logr.Logger, pspName string) (*OperatorManager, error) { bb, err := ioutil.ReadFile(fileName) if err != nil { return nil, fmt.Errorf("error while reading operator yaml file: %v", err) @@ -70,6 +67,7 @@ func New(client client.Client, fileName string, scheme *runtime.Scheme, log logr list: list, Scheme: scheme, Log: log, + pspName: pspName, }, nil } @@ -210,7 +208,7 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run Verbs: []string{"use"}, Resources: []string{"podsecuritypolicies"}, // TODO make psp name configurable - ResourceNames: []string{pspName}, + ResourceNames: []string{m.pspName}, } v.Rules = append(v.Rules, pspPolicyRule) case *rbacv1.ClusterRoleBinding: From 80767b28ef7d0c42239ad0d78d93cafacd661a00 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 18:40:36 +0100 Subject: [PATCH 5/6] Store the name of the PSP in the configmap in the helm chart, then pass it on to the postgreslet in the deployment template. Also: make psp name configurable via helm values. --- charts/postgreslet/templates/_helpers.tpl | 7 +++++++ charts/postgreslet/templates/configmap.yaml | 1 + charts/postgreslet/templates/deployment.yaml | 1 + charts/postgreslet/templates/podsecuritypolicy.yaml | 2 +- charts/postgreslet/values.yaml | 5 ++++- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/charts/postgreslet/templates/_helpers.tpl b/charts/postgreslet/templates/_helpers.tpl index 362e8b03..1831d07a 100644 --- a/charts/postgreslet/templates/_helpers.tpl +++ b/charts/postgreslet/templates/_helpers.tpl @@ -71,3 +71,10 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Create the name of the custom pod security policy to use +*/}} +{{- define "postgreslet.pspName" -}} +{{- default (include "postgreslet.fullname" .) .Values.postgreslet.customPspName }} +{{- end }} diff --git a/charts/postgreslet/templates/configmap.yaml b/charts/postgreslet/templates/configmap.yaml index ffe25d21..4eaff2ad 100644 --- a/charts/postgreslet/templates/configmap.yaml +++ b/charts/postgreslet/templates/configmap.yaml @@ -5,6 +5,7 @@ data: METRICS_ADDR_SVC_MGR: {{ .Values.postgreslet.metricsAddr | quote }} PARTITION_ID: {{ .Values.postgreslet.partitionId | quote }} TENANT: {{ .Values.postgreslet.tenant | quote }} + CUSTOM_PSP_NAME: {{ include "postgreslet.pspName" . | quote }} kind: ConfigMap metadata: name: {{ include "postgreslet.fullname" . }} diff --git a/charts/postgreslet/templates/deployment.yaml b/charts/postgreslet/templates/deployment.yaml index 4b61d86c..0b110159 100644 --- a/charts/postgreslet/templates/deployment.yaml +++ b/charts/postgreslet/templates/deployment.yaml @@ -44,6 +44,7 @@ spec: - --enable-leader-election=$(ENABLE_LEADER_ELECTION) - --partition-id=$(PARTITION_ID) - --tenant=$(TENANT) + - --custom-psp-name=$(CUSTOM_PSP_NAME) envFrom: - configMapRef: name: {{ include "postgreslet.fullname" . }} diff --git a/charts/postgreslet/templates/podsecuritypolicy.yaml b/charts/postgreslet/templates/podsecuritypolicy.yaml index e6ac81e5..b4910598 100644 --- a/charts/postgreslet/templates/podsecuritypolicy.yaml +++ b/charts/postgreslet/templates/podsecuritypolicy.yaml @@ -1,7 +1,7 @@ apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: - name: postgres-operator-psp + name: {{ include "postgreslet.pspName" . }} spec: allowPrivilegeEscalation: true fsGroup: diff --git a/charts/postgreslet/values.yaml b/charts/postgreslet/values.yaml index d833dce8..2d66593e 100644 --- a/charts/postgreslet/values.yaml +++ b/charts/postgreslet/values.yaml @@ -65,4 +65,7 @@ postgreslet: # tenant specifies which tenant this postgreslet is responsable for, postgres resources from other tenants will be ignored tenant: sample-tenant # metricsAddr defines the listen address of the metrics endpoint - metricsAddr: ":8080" \ No newline at end of file + metricsAddr: ":8080" + # customPspName The name to use for our custom psp + # If not set, a name is generated using the fullname template + customPspName: "" \ No newline at end of file From 9098cf311e4ce8a1ed3a26a82f0f1bf28bad5235 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Thu, 11 Feb 2021 18:44:55 +0100 Subject: [PATCH 6/6] Cleanup --- pkg/operatormanager/operatormanager.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index 232096f3..3fe5c4d3 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -202,12 +202,10 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run key.Namespace = "" err = m.Get(ctx, key, &rbacv1.ClusterRole{}) // Add our psp - pspPolicyRule := rbacv1.PolicyRule{ - APIGroups: []string{"extensions"}, - Verbs: []string{"use"}, - Resources: []string{"podsecuritypolicies"}, - // TODO make psp name configurable + APIGroups: []string{"extensions"}, + Verbs: []string{"use"}, + Resources: []string{"podsecuritypolicies"}, ResourceNames: []string{m.pspName}, } v.Rules = append(v.Rules, pspPolicyRule)