From aea9e9bd330c3fa934ca5fabcb8cb389a6356485 Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Wed, 19 Feb 2020 12:32:54 +0100 Subject: [PATCH] postgres-pod clusterrole (#832) * define postgres-pod clusterrole and align rbac in chart * align UI chart rbac with operator and update doc * operator RBAC needs podsecuritypolicy to grant it to postgres-pod --- .../templates/_helpers.tpl | 7 ++ .../templates/clusterrole.yaml | 52 +++++++++ .../templates/clusterrolebinding.yaml | 19 ++++ .../templates/deployment.yaml | 8 +- .../templates/serviceaccount.yaml | 76 +------------ charts/postgres-operator-ui/values.yaml | 15 ++- .../templates/clusterrole-postgres-pod.yaml | 53 +++++++++ .../templates/clusterrole.yaml | 64 ++++++++--- .../templates/clusterrolebinding.yaml | 2 - .../templates/configmap.yaml | 1 - .../templates/operatorconfiguration.yaml | 1 - charts/postgres-operator/values-crd.yaml | 2 + charts/postgres-operator/values.yaml | 2 + docs/administrator.md | 49 +++------ docs/reference/operator_parameters.md | 17 +-- manifests/configmap.yaml | 2 +- manifests/operator-service-account-rbac.yaml | 104 ++++++++++++++---- manifests/postgres-operator.yaml | 2 +- ...gresql-operator-default-configuration.yaml | 2 +- manifests/user-facing-clusterroles.yaml | 10 +- pkg/controller/controller.go | 21 ++-- pkg/util/config/config.go | 2 +- ui/manifests/ui-service-account-rbac.yaml | 2 - 23 files changed, 333 insertions(+), 180 deletions(-) create mode 100644 charts/postgres-operator-ui/templates/clusterrole.yaml create mode 100644 charts/postgres-operator-ui/templates/clusterrolebinding.yaml create mode 100644 charts/postgres-operator/templates/clusterrole-postgres-pod.yaml diff --git a/charts/postgres-operator-ui/templates/_helpers.tpl b/charts/postgres-operator-ui/templates/_helpers.tpl index a5e97081d..d83b9291a 100644 --- a/charts/postgres-operator-ui/templates/_helpers.tpl +++ b/charts/postgres-operator-ui/templates/_helpers.tpl @@ -24,6 +24,13 @@ If release name contains chart name it will be used as a full name. {{- end -}} {{- end -}} +{{/* +Create a service account name. +*/}} +{{- define "postgres-operator-ui.serviceAccountName" -}} +{{ default (include "postgres-operator-ui.fullname" .) .Values.serviceAccount.name }} +{{- end -}} + {{/* Create chart name and version as used by the chart label. */}} diff --git a/charts/postgres-operator-ui/templates/clusterrole.yaml b/charts/postgres-operator-ui/templates/clusterrole.yaml new file mode 100644 index 000000000..4f76400ec --- /dev/null +++ b/charts/postgres-operator-ui/templates/clusterrole.yaml @@ -0,0 +1,52 @@ +{{ if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "postgres-operator-ui.serviceAccountName" . }} + labels: + app.kubernetes.io/name: {{ template "postgres-operator-ui.name" . }} + helm.sh/chart: {{ template "postgres-operator-ui.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +rules: +- apiGroups: + - acid.zalan.do + resources: + - postgresqls + verbs: + - create + - delete + - get + - list + - patch + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list +- apiGroups: + - apps + resources: + - statefulsets + verbs: + - get + - list +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list +{{ end }} diff --git a/charts/postgres-operator-ui/templates/clusterrolebinding.yaml b/charts/postgres-operator-ui/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..7c874d3f7 --- /dev/null +++ b/charts/postgres-operator-ui/templates/clusterrolebinding.yaml @@ -0,0 +1,19 @@ +{{ if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "postgres-operator-ui.serviceAccountName" . }} + labels: + app.kubernetes.io/name: {{ template "postgres-operator-ui.name" . }} + helm.sh/chart: {{ template "postgres-operator-ui.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "postgres-operator-ui.serviceAccountName" . }} +subjects: +- kind: ServiceAccount + name: {{ include "postgres-operator-ui.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/charts/postgres-operator-ui/templates/deployment.yaml b/charts/postgres-operator-ui/templates/deployment.yaml index 924bcf000..da0280e61 100644 --- a/charts/postgres-operator-ui/templates/deployment.yaml +++ b/charts/postgres-operator-ui/templates/deployment.yaml @@ -20,7 +20,7 @@ spec: app.kubernetes.io/instance: {{ .Release.Name }} team: "acid" # Parameterize? spec: - serviceAccountName: {{ template "postgres-operator-ui.name" . }} + serviceAccountName: {{ include "postgres-operator-ui.serviceAccountName" . }} containers: - name: "service" image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}" @@ -45,8 +45,8 @@ spec: value: {{ .Values.envs.targetNamespace }} - name: "TEAMS" value: |- - [ - "acid" + [ + "acid" ] - name: "OPERATOR_UI_CONFIG" value: |- @@ -66,4 +66,4 @@ spec: "9.6", "9.5" ] - } \ No newline at end of file + } diff --git a/charts/postgres-operator-ui/templates/serviceaccount.yaml b/charts/postgres-operator-ui/templates/serviceaccount.yaml index 7bb715167..4c5a25543 100644 --- a/charts/postgres-operator-ui/templates/serviceaccount.yaml +++ b/charts/postgres-operator-ui/templates/serviceaccount.yaml @@ -1,81 +1,11 @@ +{{ if .Values.serviceAccount.create }} apiVersion: v1 kind: ServiceAccount metadata: - name: {{ template "postgres-operator-ui.name" . }} + name: {{ include "postgres-operator-ui.serviceAccountName" . }} labels: app.kubernetes.io/name: {{ template "postgres-operator-ui.name" . }} helm.sh/chart: {{ template "postgres-operator-ui.chart" . }} app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/instance: {{ .Release.Name }} - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "postgres-operator-ui.name" . }} - labels: - app.kubernetes.io/name: {{ template "postgres-operator-ui.name" . }} - helm.sh/chart: {{ template "postgres-operator-ui.chart" . }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -rules: -- apiGroups: - - acid.zalan.do - resources: - - postgresqls - verbs: - - create - - delete - - get - - list - - patch - - update -- apiGroups: - - "" - resources: - - pods - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - services - verbs: - - get - - list -- apiGroups: - - apps - resources: - - statefulsets - verbs: - - get - - list -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "postgres-operator-ui.name" . }} - labels: - app.kubernetes.io/name: {{ template "postgres-operator-ui.name" . }} - helm.sh/chart: {{ template "postgres-operator-ui.chart" . }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "postgres-operator-ui.name" . }} -subjects: -- kind: ServiceAccount -# note: the cluster role binding needs to be defined -# for every namespace the operator-ui service account lives in. - name: {{ template "postgres-operator-ui.name" . }} - namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/charts/postgres-operator-ui/values.yaml b/charts/postgres-operator-ui/values.yaml index 9351d470e..dca093410 100644 --- a/charts/postgres-operator-ui/values.yaml +++ b/charts/postgres-operator-ui/values.yaml @@ -11,6 +11,17 @@ image: tag: v1.2.0 pullPolicy: "IfNotPresent" +rbac: + # Specifies whether RBAC resources should be created + create: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + # configure UI pod resources resources: limits: @@ -22,7 +33,7 @@ resources: # configure UI ENVs envs: - # IMPORTANT: While operator chart and UI chart are idendependent, this is the interface between + # IMPORTANT: While operator chart and UI chart are idendependent, this is the interface between # UI and operator API. Insert the service name of the operator API here! operatorApiUrl: "http://postgres-operator:8080" targetNamespace: "default" @@ -44,4 +55,4 @@ ingress: tls: [] # - secretName: ui-tls # hosts: - # - ui.exmaple.org \ No newline at end of file + # - ui.exmaple.org diff --git a/charts/postgres-operator/templates/clusterrole-postgres-pod.yaml b/charts/postgres-operator/templates/clusterrole-postgres-pod.yaml new file mode 100644 index 000000000..c327d9101 --- /dev/null +++ b/charts/postgres-operator/templates/clusterrole-postgres-pod.yaml @@ -0,0 +1,53 @@ +{{ if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: postgres-pod + labels: + app.kubernetes.io/name: {{ template "postgres-operator.name" . }} + helm.sh/chart: {{ template "postgres-operator.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +rules: +# Patroni needs to watch and manage endpoints +- apiGroups: + - "" + resources: + - endpoints + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +# Patroni needs to watch pods +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - patch + - update + - watch +# to let Patroni create a headless service +- apiGroups: + - "" + resources: + - services + verbs: + - create +# to run privileged pods +- apiGroups: + - extensions + resources: + - podsecuritypolicies + resourceNames: + - privileged + verbs: + - use +{{ end }} diff --git a/charts/postgres-operator/templates/clusterrole.yaml b/charts/postgres-operator/templates/clusterrole.yaml index f7fe1634c..9a4165797 100644 --- a/charts/postgres-operator/templates/clusterrole.yaml +++ b/charts/postgres-operator/templates/clusterrole.yaml @@ -9,6 +9,7 @@ metadata: app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/instance: {{ .Release.Name }} rules: +# all verbs allowed for custom operator resources - apiGroups: - acid.zalan.do resources: @@ -16,7 +17,15 @@ rules: - postgresqls/status - operatorconfigurations verbs: - - "*" + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +# to create or get/update CRDs when starting up - apiGroups: - apiextensions.k8s.io resources: @@ -26,12 +35,14 @@ rules: - get - patch - update +# to read configuration from ConfigMaps - apiGroups: - "" resources: - configmaps verbs: - get +# to manage endpoints which are also used by Patroni - apiGroups: - "" resources: @@ -43,7 +54,9 @@ rules: - get - list - patch - - watch # needed if zalando-postgres-operator account is used for pods as well + - update + - watch +# to CRUD secrets for database access - apiGroups: - "" resources: @@ -53,6 +66,7 @@ rules: - update - delete - get +# to check nodes for node readiness label - apiGroups: - "" resources: @@ -61,6 +75,7 @@ rules: - get - list - watch +# to read or delete existing PVCs. Creation via StatefulSet - apiGroups: - "" resources: @@ -69,6 +84,7 @@ rules: - delete - get - list + # to read existing PVs. Creation should be done via dynamic provisioning - apiGroups: - "" resources: @@ -77,6 +93,7 @@ rules: - get - list - update # only for resizing AWS volumes +# to watch Spilo pods and do rolling updates. Creation via StatefulSet - apiGroups: - "" resources: @@ -86,13 +103,16 @@ rules: - get - list - watch + - update - patch +# to resize the filesystem in Spilo pods when increasing volume size - apiGroups: - "" resources: - pods/exec verbs: - create +# to CRUD services to point to Postgres cluster instances - apiGroups: - "" resources: @@ -102,6 +122,8 @@ rules: - delete - get - patch + - update +# to CRUD the StatefulSet which controls the Postgres cluster instances - apiGroups: - apps resources: @@ -112,12 +134,26 @@ rules: - get - list - patch +# to CRUD cron jobs for logical backups +- apiGroups: + - batch + resources: + - cronjobs + verbs: + - create + - delete + - get + - list + - patch + - update +# to get namespaces operator resources can run in - apiGroups: - "" resources: - namespaces verbs: - get +# to define PDBs. Update happens via delete/create - apiGroups: - policy resources: @@ -126,6 +162,7 @@ rules: - create - delete - get +# to create ServiceAccounts in each namespace the operator watches - apiGroups: - "" resources: @@ -133,30 +170,21 @@ rules: verbs: - get - create +# to create role bindings to the postgres-pod service account - apiGroups: - - "rbac.authorization.k8s.io" + - rbac.authorization.k8s.io resources: - rolebindings verbs: - get - create +# to grant privilege to run privileged pods - apiGroups: - - "rbac.authorization.k8s.io" + - extensions resources: - - clusterroles - verbs: - - bind + - podsecuritypolicies resourceNames: - - {{ include "postgres-operator.serviceAccountName" . }} -- apiGroups: - - batch - resources: - - cronjobs # enables logical backups + - privileged verbs: - - create - - delete - - get - - list - - patch - - update + - use {{ end }} diff --git a/charts/postgres-operator/templates/clusterrolebinding.yaml b/charts/postgres-operator/templates/clusterrolebinding.yaml index bfa21b42f..dbf65d00e 100644 --- a/charts/postgres-operator/templates/clusterrolebinding.yaml +++ b/charts/postgres-operator/templates/clusterrolebinding.yaml @@ -14,8 +14,6 @@ roleRef: name: {{ include "postgres-operator.serviceAccountName" . }} subjects: - kind: ServiceAccount -# note: the cluster role binding needs to be defined -# for every namespace the operator service account lives in. name: {{ include "postgres-operator.serviceAccountName" . }} namespace: {{ .Release.Namespace }} {{ end }} diff --git a/charts/postgres-operator/templates/configmap.yaml b/charts/postgres-operator/templates/configmap.yaml index 95eeb9546..0b976294e 100644 --- a/charts/postgres-operator/templates/configmap.yaml +++ b/charts/postgres-operator/templates/configmap.yaml @@ -9,7 +9,6 @@ metadata: app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/instance: {{ .Release.Name }} data: - pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }} {{ toYaml .Values.configGeneral | indent 2 }} {{ toYaml .Values.configUsers | indent 2 }} {{ toYaml .Values.configKubernetes | indent 2 }} diff --git a/charts/postgres-operator/templates/operatorconfiguration.yaml b/charts/postgres-operator/templates/operatorconfiguration.yaml index 6a301c1fb..06e9c7605 100644 --- a/charts/postgres-operator/templates/operatorconfiguration.yaml +++ b/charts/postgres-operator/templates/operatorconfiguration.yaml @@ -14,7 +14,6 @@ configuration: {{ toYaml .Values.configUsers | indent 4 }} kubernetes: oauth_token_secret_name: {{ template "postgres-operator.fullname" . }} - pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }} {{ toYaml .Values.configKubernetes | indent 4 }} postgres_pod_resources: {{ toYaml .Values.configPostgresPodResources | indent 4 }} diff --git a/charts/postgres-operator/values-crd.yaml b/charts/postgres-operator/values-crd.yaml index 1f9b5e495..08c255a04 100644 --- a/charts/postgres-operator/values-crd.yaml +++ b/charts/postgres-operator/values-crd.yaml @@ -100,6 +100,8 @@ configKubernetes: pod_management_policy: "ordered_ready" # label assigned to the Postgres pods (and services/endpoints) pod_role_label: spilo-role + # name of service account to be used by postgres cluster pods + pod_service_account_name: "postgres-pod" # Postgres pods are terminated forcefully after this timeout pod_terminate_grace_period: 5m # template for database user secrets generated by the operator diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 1be5851d2..60a0a1f04 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -93,6 +93,8 @@ configKubernetes: pod_management_policy: "ordered_ready" # label assigned to the Postgres pods (and services/endpoints) pod_role_label: spilo-role + # name of service account to be used by postgres cluster pods + pod_service_account_name: "postgres-pod" # Postgres pods are terminated forcefully after this timeout pod_terminate_grace_period: 5m # template for database user secrets generated by the operator diff --git a/docs/administrator.md b/docs/administrator.md index 2e86193c0..2175ae595 100644 --- a/docs/administrator.md +++ b/docs/administrator.md @@ -47,6 +47,12 @@ patching the CRD manifest: zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}' ``` +## Non-default cluster domain + +If your cluster uses a DNS domain other than the default `cluster.local`, this +needs to be set in the operator configuration (`cluster_domain` variable). This +is used by the operator to connect to the clusters after creation. + ## Namespaces ### Select the namespace to deploy to @@ -89,36 +95,13 @@ lacks access rights to any of them (except K8s system namespaces like 'list pods' execute at the cluster scope and fail at the first violation of access rights. -The watched namespace also needs to have a (possibly different) service account -in the case database pods need to talk to the K8s API (e.g. when using -K8s-native configuration of Patroni). The operator checks that the -`pod_service_account_name` exists in the target namespace, and, if not, deploys -there the `pod_service_account_definition` from the operator -[`Config`](../pkg/util/config/config.go) with the default value of: - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: operator -``` - -In this definition, the operator overwrites the account's name to match -`pod_service_account_name` and the `default` namespace to match the target -namespace. The operator performs **no** further syncing of this account. - -## Non-default cluster domain - -If your cluster uses a DNS domain other than the default `cluster.local`, this -needs to be set in the operator configuration (`cluster_domain` variable). This -is used by the operator to connect to the clusters after creation. - ## Role-based access control for the operator The manifest [`operator-service-account-rbac.yaml`](../manifests/operator-service-account-rbac.yaml) defines the service account, cluster roles and bindings needed for the operator -to function under access control restrictions. To deploy the operator with this -RBAC policy use: +to function under access control restrictions. The file also includes a cluster +role `postgres-pod` with privileges for Patroni to watch and manage pods and +endpoints. To deploy the operator with this RBAC policies use: ```bash kubectl create -f manifests/configmap.yaml @@ -127,14 +110,14 @@ kubectl create -f manifests/postgres-operator.yaml kubectl create -f manifests/minimal-postgres-manifest.yaml ``` -### Service account and cluster roles +### Namespaced service account and role binding -Note that the service account is named `zalando-postgres-operator`. You may have -to change the `service_account_name` in the operator ConfigMap and -`serviceAccountName` in the `postgres-operator` deployment appropriately. This -is done intentionally to avoid breaking those setups that already work with the -default `operator` account. In the future the operator should ideally be run -under the `zalando-postgres-operator` service account. +For each namespace the operator watches it creates (or reads) a service account +and role binding to be used by the Postgres Pods. The service account is bound +to the `postgres-pod` cluster role. The name and definitions of these resources +can be [configured](reference/operator_parameters.md#kubernetes-resources). +Note, that the operator performs **no** further syncing of namespaced service +accounts and role bindings. ### Give K8s users access to create/list `postgresqls` diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index e3893ea31..ca972c22b 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -152,21 +152,22 @@ configuration they are grouped under the `kubernetes` key. service account used by Patroni running on individual Pods to communicate with the operator. Required even if native Kubernetes support in Patroni is not used, because Patroni keeps pod labels in sync with the instance role. - The default is `operator`. + The default is `postgres-pod`. * **pod_service_account_definition** - The operator tries to create the pod Service Account in the namespace that - doesn't define such an account using the YAML definition provided by this - option. If not defined, a simple definition that contains only the name will - be used. The default is empty. + On Postgres cluster creation the operator tries to create the service account + for the Postgres pods if it does not exist in the namespace. The internal + default service account definition (defines only the name) can be overwritten + with this parameter. Make sure to provide a valid YAML or JSON string. The + default is empty. * **pod_service_account_role_binding_definition** - This definition must bind pod service account to a role with permission + This definition must bind the pod service account to a role with permission sufficient for the pods to start and for Patroni to access K8s endpoints; service account on its own lacks any such rights starting with K8s v1.8. If not explicitly defined by the user, a simple definition that binds the - account to the operator's own 'zalando-postgres-operator' cluster role will - be used. The default is empty. + account to the 'postgres-pod' [cluster role](../../manifests/operator-service-account-rbac.yaml#L198) + will be used. The default is empty. * **pod_terminate_grace_period** Postgres pods are [terminated forcefully](https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods) diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index d26c83edf..6b00c30f4 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -63,7 +63,7 @@ data: pod_label_wait_timeout: 10m pod_management_policy: "ordered_ready" pod_role_label: spilo-role - pod_service_account_name: "zalando-postgres-operator" + pod_service_account_name: "postgres-pod" pod_terminate_grace_period: 5m # postgres_superuser_teams: "postgres_superusers" # protected_role_names: "admin" diff --git a/manifests/operator-service-account-rbac.yaml b/manifests/operator-service-account-rbac.yaml index 5e43cc03b..80fcd89ef 100644 --- a/manifests/operator-service-account-rbac.yaml +++ b/manifests/operator-service-account-rbac.yaml @@ -1,14 +1,14 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: zalando-postgres-operator + name: postgres-operator namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: zalando-postgres-operator + name: postgres-operator rules: # all verbs allowed for custom operator resources - apiGroups: @@ -18,7 +18,14 @@ rules: - postgresqls/status - operatorconfigurations verbs: - - "*" + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch # to create or get/update CRDs when starting up - apiGroups: - apiextensions.k8s.io @@ -48,7 +55,8 @@ rules: - get - list - patch - - watch # needed if zalando-postgres-operator account is used for pods as well + - update + - watch # to CRUD secrets for database access - apiGroups: - "" @@ -96,6 +104,7 @@ rules: - get - list - watch + - update - patch # to resize the filesystem in Spilo pods when increasing volume size - apiGroups: @@ -126,6 +135,18 @@ rules: - get - list - patch +# to CRUD cron jobs for logical backups +- apiGroups: + - batch + resources: + - cronjobs + verbs: + - create + - delete + - get + - list + - patch + - update # to get namespaces operator resources can run in - apiGroups: - "" @@ -150,39 +171,82 @@ rules: verbs: - get - create -# to create role bindings to the operator service account +# to create role bindings to the postgres-pod service account - apiGroups: - - "rbac.authorization.k8s.io" + - rbac.authorization.k8s.io resources: - rolebindings verbs: - get - create -# to CRUD cron jobs for logical backups +# to grant privilege to run privileged pods - apiGroups: - - batch + - extensions resources: - - cronjobs + - podsecuritypolicies + resourceNames: + - privileged verbs: - - create - - delete - - get - - list - - patch - - update + - use --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: zalando-postgres-operator + name: postgres-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: zalando-postgres-operator + name: postgres-operator subjects: - kind: ServiceAccount -# note: the cluster role binding needs to be defined -# for every namespace the operator service account lives in. - name: zalando-postgres-operator + name: postgres-operator namespace: default + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: postgres-pod +rules: +# Patroni needs to watch and manage endpoints +- apiGroups: + - "" + resources: + - endpoints + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +# Patroni needs to watch pods +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - patch + - update + - watch +# to let Patroni create a headless service +- apiGroups: + - "" + resources: + - services + verbs: + - create +# to run privileged pods +- apiGroups: + - extensions + resources: + - podsecuritypolicies + resourceNames: + - privileged + verbs: + - use diff --git a/manifests/postgres-operator.yaml b/manifests/postgres-operator.yaml index a06abfc68..e3bc3e3e4 100644 --- a/manifests/postgres-operator.yaml +++ b/manifests/postgres-operator.yaml @@ -12,7 +12,7 @@ spec: labels: name: postgres-operator spec: - serviceAccountName: zalando-postgres-operator + serviceAccountName: postgres-operator containers: - name: postgres-operator image: registry.opensource.zalan.do/acid/postgres-operator:v1.3.1 diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml index efd1a5396..695a4e9c5 100644 --- a/manifests/postgresql-operator-default-configuration.yaml +++ b/manifests/postgresql-operator-default-configuration.yaml @@ -45,7 +45,7 @@ configuration: # pod_priority_class_name: "" pod_role_label: spilo-role # pod_service_account_definition: "" - pod_service_account_name: zalando-postgres-operator + pod_service_account_name: postgres-pod # pod_service_account_role_binding_definition: "" pod_terminate_grace_period: 5m secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" diff --git a/manifests/user-facing-clusterroles.yaml b/manifests/user-facing-clusterroles.yaml index 800aafdb9..64392a19a 100644 --- a/manifests/user-facing-clusterroles.yaml +++ b/manifests/user-facing-clusterroles.yaml @@ -11,7 +11,14 @@ rules: - postgresqls - postgresqls/status verbs: - - "*" + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch --- apiVersion: rbac.authorization.k8s.io/v1 @@ -48,4 +55,3 @@ rules: - get - list - watch - diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index f67d99c1d..3c49b9a13 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -161,11 +161,12 @@ func (c *Controller) initPodServiceAccount() { if c.opConfig.PodServiceAccountDefinition == "" { c.opConfig.PodServiceAccountDefinition = ` - { "apiVersion": "v1", - "kind": "ServiceAccount", - "metadata": { - "name": "operator" - } + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "postgres-pod" + } }` } @@ -175,13 +176,13 @@ func (c *Controller) initPodServiceAccount() { switch { case err != nil: - panic(fmt.Errorf("Unable to parse pod service account definition from the operator config map: %v", err)) + panic(fmt.Errorf("Unable to parse pod service account definition from the operator configuration: %v", err)) case groupVersionKind.Kind != "ServiceAccount": - panic(fmt.Errorf("pod service account definition in the operator config map defines another type of resource: %v", groupVersionKind.Kind)) + panic(fmt.Errorf("pod service account definition in the operator configuration defines another type of resource: %v", groupVersionKind.Kind)) default: c.PodServiceAccount = obj.(*v1.ServiceAccount) if c.PodServiceAccount.Name != c.opConfig.PodServiceAccountName { - c.logger.Warnf("in the operator config map, the pod service account name %v does not match the name %v given in the account definition; using the former for consistency", c.opConfig.PodServiceAccountName, c.PodServiceAccount.Name) + c.logger.Warnf("in the operator configuration, the pod service account name %v does not match the name %v given in the account definition; using the former for consistency", c.opConfig.PodServiceAccountName, c.PodServiceAccount.Name) c.PodServiceAccount.Name = c.opConfig.PodServiceAccountName } c.PodServiceAccount.Namespace = "" @@ -223,9 +224,9 @@ func (c *Controller) initRoleBinding() { switch { case err != nil: - panic(fmt.Errorf("Unable to parse the definition of the role binding for the pod service account definition from the operator config map: %v", err)) + panic(fmt.Errorf("unable to parse the definition of the role binding for the pod service account definition from the operator configuration: %v", err)) case groupVersionKind.Kind != "RoleBinding": - panic(fmt.Errorf("role binding definition in the operator config map defines another type of resource: %v", groupVersionKind.Kind)) + panic(fmt.Errorf("role binding definition in the operator configuration defines another type of resource: %v", groupVersionKind.Kind)) default: c.PodServiceAccountRoleBinding = obj.(*rbacv1.RoleBinding) c.PodServiceAccountRoleBinding.Namespace = "" diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index e4e429abb..ec4af6427 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -96,7 +96,7 @@ type Config struct { DockerImage string `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p16"` Sidecars map[string]string `name:"sidecar_docker_images"` // default name `operator` enables backward compatibility with the older ServiceAccountName field - PodServiceAccountName string `name:"pod_service_account_name" default:"operator"` + PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"` // value of this string must be valid JSON or YAML; see initPodServiceAccount PodServiceAccountDefinition string `name:"pod_service_account_definition" default:""` PodServiceAccountRoleBindingDefinition string `name:"pod_service_account_role_binding_definition" default:""` diff --git a/ui/manifests/ui-service-account-rbac.yaml b/ui/manifests/ui-service-account-rbac.yaml index f0a6e8bb7..2e09797a0 100644 --- a/ui/manifests/ui-service-account-rbac.yaml +++ b/ui/manifests/ui-service-account-rbac.yaml @@ -61,7 +61,5 @@ roleRef: name: postgres-operator-ui subjects: - kind: ServiceAccount -# note: the cluster role binding needs to be defined -# for every namespace the operator-ui service account lives in. name: postgres-operator-ui namespace: default