From 371dcc00a448ad1117081b64ab24925a7035debe Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 26 Mar 2026 10:09:15 +0100 Subject: [PATCH 01/15] chore: Describe RBAC rules, remove unnecessary rules --- deploy/helm/opa-operator/templates/roles.yaml | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index abe1ab5e..abeae4b3 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -6,6 +6,7 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: + # For automatic cluster domain detection (list+watch required by the kube controller runtime) - apiGroups: - "" resources: @@ -20,66 +21,70 @@ rules: - nodes/proxy verbs: - get + # Manage core workload resources created per OpaCluster. + # All resources are applied via Server-Side Apply (create + patch) and tracked for + # orphan cleanup (list + delete). The get verb is required by the ReconciliationPaused + # strategy (which calls client.get() instead of apply_patch() when paused). + # Resources watched by the controller also need watch. + # - configmaps: role-group configs and discovery ConfigMaps; watched via .owns() + # - services: role service, per-rolegroup headless and metrics services; watched via .owns() + # - serviceaccounts: per-cluster ServiceAccount for the product workload pods - apiGroups: - "" resources: - - pods - configmaps - - secrets - services - - endpoints - - serviceaccounts verbs: - create - delete - get - list - patch - - update - watch - apiGroups: - - rbac.authorization.k8s.io + - "" resources: - - rolebindings + - serviceaccounts verbs: - create - delete - get - list - patch - - update - - watch + # Per-cluster RoleBinding binding the product ClusterRole to the workload ServiceAccount; + # applied via SSA and tracked for orphan cleanup; not watched by the controller. - apiGroups: - - apps + - rbac.authorization.k8s.io resources: - - daemonsets + - rolebindings verbs: - - get - create - delete + - get - list - patch - - update - - watch + # Per-rolegroup DaemonSet for OPA server pods; applied via SSA, tracked for orphan + # cleanup, and watched via .owns(). - apiGroups: - - batch + - apps resources: - - jobs + - daemonsets verbs: - create + - delete - get - list - patch - - update - watch + # Read the CRD at startup to confirm it is established before starting the controller. + # With maintenance enabled the operator also creates, patches, lists and watches CRDs + # to maintain the CRD (e.g. entering generated certificates into the conversion webhook). - apiGroups: - apiextensions.k8s.io resources: - customresourcedefinitions verbs: - get - # Required to maintain the CRD. The operator needs to do this, as it needs to enter e.g. it's - # generated certificate in the conversion webhook. {{- if .Values.maintenance.customResourceDefinitions.maintain }} - create - patch @@ -87,6 +92,7 @@ rules: - list - watch {{- end }} + # For publishing Kubernetes events from the controller reconciliation loop - apiGroups: - events.k8s.io resources: @@ -94,6 +100,7 @@ rules: verbs: - create - patch + # Watch and read OpaCluster resources to drive reconciliation - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: @@ -101,14 +108,15 @@ rules: verbs: - get - list - - patch - watch + # Patch OpaCluster status to report conditions back to the user - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: - {{ include "operator.name" . }}clusters/status verbs: - patch + # Allow binding the product ClusterRole to per-cluster ServiceAccounts - apiGroups: - rbac.authorization.k8s.io resources: @@ -126,6 +134,8 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: + # OPA workload pods read ConfigMaps (bundle ConfigMaps, product config) and Secrets + # (TLS credentials) and ServiceAccounts (for token projection) at runtime. - apiGroups: - "" resources: @@ -136,6 +146,7 @@ rules: - get - list - watch + # OPA workload pods publish Kubernetes events (e.g. from the user-info-fetcher sidecar) - apiGroups: - events.k8s.io resources: @@ -144,6 +155,7 @@ rules: - create - patch {{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} + # Allow the workload pods to use the nonroot-v2 SCC on OpenShift - apiGroups: - security.openshift.io resources: From 17e8c3eceb718d76aea718b91e718ff38e25dc59 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:10:58 +0200 Subject: [PATCH 02/15] chore: Add missing rule comments --- .../helm/opa-operator/templates/roles-opa-builder.yaml | 9 +++++---- deploy/helm/opa-operator/templates/roles.yaml | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles-opa-builder.yaml b/deploy/helm/opa-operator/templates/roles-opa-builder.yaml index e64626ea..c66b269f 100644 --- a/deploy/helm/opa-operator/templates/roles-opa-builder.yaml +++ b/deploy/helm/opa-operator/templates/roles-opa-builder.yaml @@ -1,12 +1,12 @@ +--- +# This ClusterRole is for the OPA bundle builder sidecar, which reads +# Rego rules from ConfigMaps and compiles them into bundles for OPA. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: {{ .Release.Name }}-opa-bundle-builder-clusterrole -# This role is used for the OPA bundle builder. -# It needs to read ConfigMaps and watch ConfigMaps for changes, -# because the Rego rules that are used to build the bundles are -# stored in the ConfigMaps. rules: + # Read and watch ConfigMaps containing Rego rules used to build bundles - apiGroups: - "" resources: @@ -16,6 +16,7 @@ rules: - watch - list {{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} + # Allow the bundle builder pods to use the opa-scc SCC on OpenShift - apiGroups: - security.openshift.io resources: diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index abeae4b3..ec628f90 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -41,6 +41,8 @@ rules: - list - patch - watch + # Per-cluster ServiceAccount for the product workload pods; applied via SSA + # and tracked for orphan cleanup. - apiGroups: - "" resources: From bdd4be328b252e4d817fa413486d5afa957e6e3a Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:11:49 +0200 Subject: [PATCH 03/15] chore: Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec32da9a..7637bcd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,10 @@ All notable changes to this project will be documented in this file. - Set `maxSurge=1` and `maxUnavailable=0` on the OPA DaemonSet rolling update strategy to eliminate availability gaps during rolling updates ([#819]). +- Helm deployed RBAC permissions documented, with unnecessary permissions removed ([#820]). [#819]: https://github.com/stackabletech/opa-operator/pull/819 +[#820]: https://github.com/stackabletech/opa-operator/pull/820 ## [26.3.0] - 2026-03-16 From 34a58e7cc4b95c76420da9c082c66f545eb6977d Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:12:34 +0200 Subject: [PATCH 04/15] chore: Remove the get for customresourcedefinitions for the operator clusterrole Not needed for CRD maintenance nor startup condition --- deploy/helm/opa-operator/templates/roles.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index ec628f90..4391077c 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -86,7 +86,6 @@ rules: resources: - customresourcedefinitions verbs: - - get {{- if .Values.maintenance.customResourceDefinitions.maintain }} - create - patch From d90b0d28b00d200484bb273be0d45b9ff600495b Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:15:05 +0200 Subject: [PATCH 05/15] chore: Remove nodes list/watch Not needed for clusterDomain detection --- deploy/helm/opa-operator/templates/roles.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index 4391077c..3d573e0c 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -6,14 +6,6 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: - # For automatic cluster domain detection (list+watch required by the kube controller runtime) - - apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch # For automatic cluster domain detection - apiGroups: - "" From fb04b950fbbaebebf8ba4815d7dd40f3f21759f5 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:30:52 +0200 Subject: [PATCH 06/15] chore: Remove the configmaps/secrets/serviceaccounts rule for the product clusterrole OPA doesn't interact with the Kubernetes API --- deploy/helm/opa-operator/templates/roles.yaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index 3d573e0c..f705a537 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -127,18 +127,6 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: - # OPA workload pods read ConfigMaps (bundle ConfigMaps, product config) and Secrets - # (TLS credentials) and ServiceAccounts (for token projection) at runtime. - - apiGroups: - - "" - resources: - - configmaps - - secrets - - serviceaccounts - verbs: - - get - - list - - watch # OPA workload pods publish Kubernetes events (e.g. from the user-info-fetcher sidecar) - apiGroups: - events.k8s.io From 1ced0e2d557aaf36557ed797f8f21395ca5e7844 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:34:57 +0200 Subject: [PATCH 07/15] fix: Always allow customresourcedefinitions list/watch Required for startup condition regardless of CRD maintenance --- deploy/helm/opa-operator/templates/roles.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index f705a537..165db36f 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -81,10 +81,10 @@ rules: {{- if .Values.maintenance.customResourceDefinitions.maintain }} - create - patch + {{- end }} # Required for startup condition - list - watch - {{- end }} # For publishing Kubernetes events from the controller reconciliation loop - apiGroups: - events.k8s.io From 5aea469410c9c718e47d81ee9aea6b19e87d5c83 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:38:17 +0200 Subject: [PATCH 08/15] chore: Simplify the rule comments --- deploy/helm/opa-operator/templates/roles.yaml | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index 165db36f..c394825d 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -15,12 +15,7 @@ rules: - get # Manage core workload resources created per OpaCluster. # All resources are applied via Server-Side Apply (create + patch) and tracked for - # orphan cleanup (list + delete). The get verb is required by the ReconciliationPaused - # strategy (which calls client.get() instead of apply_patch() when paused). - # Resources watched by the controller also need watch. - # - configmaps: role-group configs and discovery ConfigMaps; watched via .owns() - # - services: role service, per-rolegroup headless and metrics services; watched via .owns() - # - serviceaccounts: per-cluster ServiceAccount for the product workload pods + # orphan cleanup (list + delete). - apiGroups: - "" resources: @@ -33,8 +28,8 @@ rules: - list - patch - watch - # Per-cluster ServiceAccount for the product workload pods; applied via SSA - # and tracked for orphan cleanup. + # ServiceAccount created per OpaCluster for workload pod identity. + # Applied via SSA and tracked for orphan cleanup. - apiGroups: - "" resources: @@ -45,8 +40,8 @@ rules: - get - list - patch - # Per-cluster RoleBinding binding the product ClusterRole to the workload ServiceAccount; - # applied via SSA and tracked for orphan cleanup; not watched by the controller. + # RoleBinding created per OpaCluster to bind the product ClusterRole to the workload + # ServiceAccount. Applied via SSA and tracked for orphan cleanup. - apiGroups: - rbac.authorization.k8s.io resources: @@ -57,8 +52,8 @@ rules: - get - list - patch - # Per-rolegroup DaemonSet for OPA server pods; applied via SSA, tracked for orphan - # cleanup, and watched via .owns(). + # DaemonSet created per role group. Applied via SSA, tracked for orphan cleanup, and + # owned by the controller. - apiGroups: - apps resources: @@ -70,9 +65,8 @@ rules: - list - patch - watch - # Read the CRD at startup to confirm it is established before starting the controller. - # With maintenance enabled the operator also creates, patches, lists and watches CRDs - # to maintain the CRD (e.g. entering generated certificates into the conversion webhook). + # Required for maintaining the CRDs within the operator (including the conversion webhook info). + # Also for the startup condition check before the controller can run. - apiGroups: - apiextensions.k8s.io resources: @@ -85,7 +79,7 @@ rules: # Required for startup condition - list - watch - # For publishing Kubernetes events from the controller reconciliation loop + # Required to report reconciliation results and warnings back to the OpaCluster object. - apiGroups: - events.k8s.io resources: @@ -93,7 +87,7 @@ rules: verbs: - create - patch - # Watch and read OpaCluster resources to drive reconciliation + # Primary CRD: watched by the controller and read during reconciliation. - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: @@ -102,14 +96,14 @@ rules: - get - list - watch - # Patch OpaCluster status to report conditions back to the user + # Status subresource: updated at the end of every reconciliation. - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: - {{ include "operator.name" . }}clusters/status verbs: - patch - # Allow binding the product ClusterRole to per-cluster ServiceAccounts + # Required to bind the product ClusterRole to the per-cluster ServiceAccount. - apiGroups: - rbac.authorization.k8s.io resources: @@ -136,7 +130,7 @@ rules: - create - patch {{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} - # Allow the workload pods to use the nonroot-v2 SCC on OpenShift + # Required on OpenShift to allow the OPA pods to run as a non-root user. - apiGroups: - security.openshift.io resources: From fe683fde02120088eb66119b591bf7eabfb1c58a Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:40:10 +0200 Subject: [PATCH 09/15] chore: Remove the events.k8s.io rule from the product ClusterRole Neither OPA nor UIF interact with the Kubernetes API --- deploy/helm/opa-operator/templates/roles.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index c394825d..13726e23 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -121,14 +121,6 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: - # OPA workload pods publish Kubernetes events (e.g. from the user-info-fetcher sidecar) - - apiGroups: - - events.k8s.io - resources: - - events - verbs: - - create - - patch {{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} # Required on OpenShift to allow the OPA pods to run as a non-root user. - apiGroups: From c80b61c5582f409870a8272287e3183b174e2ff9 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:41:29 +0200 Subject: [PATCH 10/15] chore: Keep the rbac.authorization.k8s.io rules within a ClusterRole close to each other --- deploy/helm/opa-operator/templates/roles.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/roles.yaml index 13726e23..75d51918 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/roles.yaml @@ -52,6 +52,15 @@ rules: - get - list - patch + # Required to bind the product ClusterRole to the per-cluster ServiceAccount. + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + verbs: + - bind + resourceNames: + - {{ include "operator.name" . }}-clusterrole # DaemonSet created per role group. Applied via SSA, tracked for orphan cleanup, and # owned by the controller. - apiGroups: @@ -103,15 +112,6 @@ rules: - {{ include "operator.name" . }}clusters/status verbs: - patch - # Required to bind the product ClusterRole to the per-cluster ServiceAccount. - - apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - verbs: - - bind - resourceNames: - - {{ include "operator.name" . }}-clusterrole --- apiVersion: rbac.authorization.k8s.io/v1 From 4c6095635cbef57a3b3ade41e23fdd5c2ef3d267 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:43:46 +0200 Subject: [PATCH 11/15] chore: Split the roles.yaml into separate files for clusterrole-operator.yaml and clusterrole-product.yaml Also rename the opa-builder clusterrole file to be consistent --- ...lder.yaml => clusterrole-opa-builder.yaml} | 0 .../{roles.yaml => clusterrole-operator.yaml} | 20 ------------------ .../templates/clusterrole-product.yaml | 21 +++++++++++++++++++ 3 files changed, 21 insertions(+), 20 deletions(-) rename deploy/helm/opa-operator/templates/{roles-opa-builder.yaml => clusterrole-opa-builder.yaml} (100%) rename deploy/helm/opa-operator/templates/{roles.yaml => clusterrole-operator.yaml} (85%) create mode 100644 deploy/helm/opa-operator/templates/clusterrole-product.yaml diff --git a/deploy/helm/opa-operator/templates/roles-opa-builder.yaml b/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml similarity index 100% rename from deploy/helm/opa-operator/templates/roles-opa-builder.yaml rename to deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml similarity index 85% rename from deploy/helm/opa-operator/templates/roles.yaml rename to deploy/helm/opa-operator/templates/clusterrole-operator.yaml index 75d51918..17b6a336 100644 --- a/deploy/helm/opa-operator/templates/roles.yaml +++ b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml @@ -112,23 +112,3 @@ rules: - {{ include "operator.name" . }}clusters/status verbs: - patch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "operator.name" . }}-clusterrole - labels: - {{- include "operator.labels" . | nindent 4 }} -rules: -{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} - # Required on OpenShift to allow the OPA pods to run as a non-root user. - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - resourceNames: - - nonroot-v2 - verbs: - - use -{{ end }} diff --git a/deploy/helm/opa-operator/templates/clusterrole-product.yaml b/deploy/helm/opa-operator/templates/clusterrole-product.yaml new file mode 100644 index 00000000..30911bfa --- /dev/null +++ b/deploy/helm/opa-operator/templates/clusterrole-product.yaml @@ -0,0 +1,21 @@ +--- +# Product ClusterRole: bound (via per OpaCluster RoleBinding) to the ServiceAccount that OPA +# workload pods run as. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "operator.name" . }}-clusterrole + labels: + {{- include "operator.labels" . | nindent 4 }} +rules: +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} + # Required on OpenShift to allow the OPA pods to run as a non-root user. + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use +{{ end }} From b6b2c46aeee3ebe589c8ff19b4f3eb50b3a1ccce Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 14:52:46 +0200 Subject: [PATCH 12/15] chore: Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7637bcd6..bf247fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - Set `maxSurge=1` and `maxUnavailable=0` on the OPA DaemonSet rolling update strategy to eliminate availability gaps during rolling updates ([#819]). -- Helm deployed RBAC permissions documented, with unnecessary permissions removed ([#820]). +- Document Helm deployed RBAC permissions and remove unnecessary permissions ([#820]). [#819]: https://github.com/stackabletech/opa-operator/pull/819 [#820]: https://github.com/stackabletech/opa-operator/pull/820 From 5dc06dbca2365f9c2957f74318d8f722e972e0d2 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Thu, 9 Apr 2026 15:25:50 +0200 Subject: [PATCH 13/15] chore: Restore rules after discovering that the bundle-builder clusterrole is not used --- .../templates/clusterrole-opa-builder.yaml | 5 +++++ .../opa-operator/templates/clusterrole-product.yaml | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml b/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml index c66b269f..c37c9c59 100644 --- a/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml +++ b/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml @@ -1,6 +1,11 @@ --- # This ClusterRole is for the OPA bundle builder sidecar, which reads # Rego rules from ConfigMaps and compiles them into bundles for OPA. +# +# NOTE: This ClusterRole is currently not bound to any ServiceAccount. The +# bundle-builder sidecar relies on the product ClusterRole for ConfigMap access +# instead. The operator should be updated to bind this ClusterRole to the +# product ServiceAccount via a separate RoleBinding. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/deploy/helm/opa-operator/templates/clusterrole-product.yaml b/deploy/helm/opa-operator/templates/clusterrole-product.yaml index 30911bfa..0e69ca85 100644 --- a/deploy/helm/opa-operator/templates/clusterrole-product.yaml +++ b/deploy/helm/opa-operator/templates/clusterrole-product.yaml @@ -8,6 +8,17 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: + # The bundle-builder sidecar lists and watches ConfigMaps labeled opa.stackable.tech/bundle + # to compile Rego rules into bundles. It shares this ServiceAccount because the bundle-builder + # ClusterRole (clusterrole-opa-builder.yaml) is not yet bound to the product ServiceAccount. + # TODO: Wire up the bundle-builder ClusterRole binding in the operator and remove this rule. + - apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - watch {{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} # Required on OpenShift to allow the OPA pods to run as a non-root user. - apiGroups: From 2726953e8a58f836bf75b10dd9ebfb71cac44240 Mon Sep 17 00:00:00 2001 From: Nick <10092581+NickLarsenNZ@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:04:50 +0200 Subject: [PATCH 14/15] chore: Preserve comment on part of rule --- deploy/helm/opa-operator/templates/clusterrole-operator.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/helm/opa-operator/templates/clusterrole-operator.yaml b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml index 17b6a336..bc02d118 100644 --- a/deploy/helm/opa-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml @@ -81,6 +81,8 @@ rules: resources: - customresourcedefinitions verbs: + # Required to maintain the CRD. The operator needs to do this, as it needs to enter e.g. it's + # generated certificate in the conversion webhook. {{- if .Values.maintenance.customResourceDefinitions.maintain }} - create - patch From a7f39d606d1e73564245f104a4e39636ba06d889 Mon Sep 17 00:00:00 2001 From: Nick Larsen Date: Fri, 10 Apr 2026 10:10:00 +0200 Subject: [PATCH 15/15] chore: Add description to operator clusterrole --- deploy/helm/opa-operator/templates/clusterrole-operator.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/helm/opa-operator/templates/clusterrole-operator.yaml b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml index bc02d118..5805576d 100644 --- a/deploy/helm/opa-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml @@ -1,4 +1,6 @@ --- +# Operator ClusterRole: bound (via ClusterRoleBinding) to the operator's own ServiceAccount. +# Grants permissions needed by the controller to reconcile OpaCluster resources. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: