diff --git a/CHANGELOG.md b/CHANGELOG.md index ec32da9a..bf247fbf 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]). +- 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 ## [26.3.0] - 2026-03-16 diff --git a/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml b/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml new file mode 100644 index 00000000..c37c9c59 --- /dev/null +++ b/deploy/helm/opa-operator/templates/clusterrole-opa-builder.yaml @@ -0,0 +1,33 @@ +--- +# 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: + name: {{ .Release.Name }}-opa-bundle-builder-clusterrole +rules: + # Read and watch ConfigMaps containing Rego rules used to build bundles + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - 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: + - securitycontextconstraints + resourceNames: + - opa-scc + verbs: + - use +{{ end }} diff --git a/deploy/helm/opa-operator/templates/roles.yaml b/deploy/helm/opa-operator/templates/clusterrole-operator.yaml similarity index 61% rename from deploy/helm/opa-operator/templates/roles.yaml rename to deploy/helm/opa-operator/templates/clusterrole-operator.yaml index abe1ab5e..5805576d 100644 --- a/deploy/helm/opa-operator/templates/roles.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: @@ -6,13 +8,6 @@ metadata: labels: {{- include "operator.labels" . | nindent 4 }} rules: - - apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch # For automatic cluster domain detection - apiGroups: - "" @@ -20,73 +15,84 @@ 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). - apiGroups: - "" resources: - - pods - configmaps - - secrets - services - - endpoints - - serviceaccounts verbs: - create - delete - get - list - patch - - update - watch + # ServiceAccount created per OpaCluster for workload pod identity. + # Applied via SSA and tracked for orphan cleanup. - apiGroups: - - rbac.authorization.k8s.io + - "" resources: - - rolebindings + - serviceaccounts verbs: - create - delete - get - list - patch - - update - - watch + # RoleBinding created per OpaCluster to bind the product ClusterRole to the workload + # ServiceAccount. Applied via SSA and tracked for orphan cleanup. - apiGroups: - - apps + - rbac.authorization.k8s.io resources: - - daemonsets + - rolebindings verbs: - - get - create - delete + - get - list - patch - - update - - watch + # Required to bind the product ClusterRole to the per-cluster ServiceAccount. - apiGroups: - - batch + - rbac.authorization.k8s.io resources: - - jobs + - 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: + - apps + resources: + - daemonsets verbs: - create + - delete - get - list - patch - - update - watch + # 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: - 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 + {{- end }} # Required for startup condition - list - watch - {{- end }} + # Required to report reconciliation results and warnings back to the OpaCluster object. - apiGroups: - events.k8s.io resources: @@ -94,6 +100,7 @@ rules: verbs: - create - patch + # Primary CRD: watched by the controller and read during reconciliation. - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: @@ -101,55 +108,11 @@ rules: verbs: - get - list - - patch - watch + # Status subresource: updated at the end of every reconciliation. - apiGroups: - {{ include "operator.name" . }}.stackable.tech resources: - {{ include "operator.name" . }}clusters/status verbs: - patch - - apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - verbs: - - bind - resourceNames: - - {{ include "operator.name" . }}-clusterrole - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "operator.name" . }}-clusterrole - labels: - {{- include "operator.labels" . | nindent 4 }} -rules: - - apiGroups: - - "" - resources: - - configmaps - - secrets - - serviceaccounts - verbs: - - get - - list - - watch - - apiGroups: - - events.k8s.io - resources: - - events - verbs: - - create - - patch -{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} - - 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..0e69ca85 --- /dev/null +++ b/deploy/helm/opa-operator/templates/clusterrole-product.yaml @@ -0,0 +1,32 @@ +--- +# 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: + # 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: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use +{{ end }} diff --git a/deploy/helm/opa-operator/templates/roles-opa-builder.yaml b/deploy/helm/opa-operator/templates/roles-opa-builder.yaml deleted file mode 100644 index e64626ea..00000000 --- a/deploy/helm/opa-operator/templates/roles-opa-builder.yaml +++ /dev/null @@ -1,27 +0,0 @@ -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: - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - watch - - list -{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - resourceNames: - - opa-scc - verbs: - - use -{{ end }}