From 0b01f03c99a7285127fac50755dbb27184a6a453 Mon Sep 17 00:00:00 2001 From: Jet Chiang Date: Thu, 26 Mar 2026 16:02:22 -0400 Subject: [PATCH 1/2] namespaced rbac Signed-off-by: Jet Chiang --- helm/kagent-tools/templates/clusterrole.yaml | 175 ++++++++++-------- .../templates/clusterrolebinding.yaml | 33 ++++ helm/kagent-tools/tests/rbac_test.yaml | 66 +++++++ helm/kagent-tools/values.yaml | 6 + 4 files changed, 204 insertions(+), 76 deletions(-) create mode 100644 helm/kagent-tools/tests/rbac_test.yaml diff --git a/helm/kagent-tools/templates/clusterrole.yaml b/helm/kagent-tools/templates/clusterrole.yaml index cdbb293..48b615b 100644 --- a/helm/kagent-tools/templates/clusterrole.yaml +++ b/helm/kagent-tools/templates/clusterrole.yaml @@ -1,95 +1,118 @@ -{{- if and (not .Values.useDefaultServiceAccount) .Values.rbac.create }} +{{- define "kagent-tools.rules" -}} {{- if .Values.rbac.readOnly }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "kagent-tools.fullname" . }}-read-role - labels: - {{- include "kagent-tools.labels" . | nindent 4 }} -rules: - # Core workload resources - - apiGroups: [""] - resources: - - pods - - services - - endpoints - - configmaps - - serviceaccounts - - persistentvolumeclaims - - replicationcontrollers - - namespaces - verbs: ["get", "list", "watch"] +# Core workload resources +- apiGroups: [""] + resources: + - pods + - services + - endpoints + - configmaps + - serviceaccounts + - persistentvolumeclaims + - replicationcontrollers + - namespaces + verbs: ["get", "list", "watch"] - # Pod logs (subresource) - - apiGroups: [""] - resources: - - pods/log - verbs: ["get", "list"] +# Pod logs (subresource) +- apiGroups: [""] + resources: + - pods/log + verbs: ["get", "list"] - # Events - - apiGroups: [""] - resources: - - events - verbs: ["get", "list", "watch"] - - apiGroups: ["events.k8s.io"] - resources: - - events - verbs: ["get", "list", "watch"] +# Events +- apiGroups: [""] + resources: + - events + verbs: ["get", "list", "watch"] +- apiGroups: ["events.k8s.io"] + resources: + - events + verbs: ["get", "list", "watch"] - # Apps workloads - - apiGroups: ["apps"] - resources: - - deployments - - statefulsets - - daemonsets - - replicasets - verbs: ["get", "list", "watch"] +# Apps workloads +- apiGroups: ["apps"] + resources: + - deployments + - statefulsets + - daemonsets + - replicasets + verbs: ["get", "list", "watch"] - # Batch workloads - - apiGroups: ["batch"] - resources: - - jobs - - cronjobs - verbs: ["get", "list", "watch"] +# Batch workloads +- apiGroups: ["batch"] + resources: + - jobs + - cronjobs + verbs: ["get", "list", "watch"] - # Networking - - apiGroups: ["networking.k8s.io"] - resources: - - ingresses - - networkpolicies - verbs: ["get", "list", "watch"] +# Networking +- apiGroups: ["networking.k8s.io"] + resources: + - ingresses + - networkpolicies + verbs: ["get", "list", "watch"] - # Autoscaling - - apiGroups: ["autoscaling"] - resources: - - horizontalpodautoscalers - verbs: ["get", "list", "watch"] - - {{- if .Values.rbac.allowSecrets }} - # Secrets (opt-in) - - apiGroups: [""] - resources: - - secrets - verbs: ["get", "list", "watch"] - {{- end }} +# Autoscaling +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["get", "list", "watch"] - {{- with .Values.rbac.additionalRules }} - # Additional user-defined rules - {{- toYaml . | nindent 2 }} - {{- end }} +{{- if .Values.rbac.allowSecrets }} +# Secrets (opt-in) +- apiGroups: [""] + resources: + - secrets + verbs: ["get", "list", "watch"] +{{- end }} +{{- with .Values.rbac.additionalRules }} +# Additional user-defined rules +{{- toYaml . | nindent 0 }} +{{- end }} {{- else }} +- apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] +{{- if .Values.rbac.clusterScoped }} +- nonResourceURLs: ["*"] + verbs: ["*"] +{{- end }} +{{- end }} +{{- end -}} + +{{- if and (not .Values.useDefaultServiceAccount) .Values.rbac.create }} +{{- if .Values.rbac.clusterScoped }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: + {{- if .Values.rbac.readOnly }} + name: {{ include "kagent-tools.fullname" . }}-read-role + {{- else }} name: {{ include "kagent-tools.fullname" . }}-cluster-admin-role + {{- end }} labels: {{- include "kagent-tools.labels" . | nindent 4 }} rules: -- apiGroups: ["*"] - resources: ["*"] - verbs: ["*"] -- nonResourceURLs: ["*"] - verbs: ["*"] + {{- include "kagent-tools.rules" . | nindent 2 }} + +{{- else }} +{{- $namespaces := .Values.rbac.namespaces | default (list (include "kagent-tools.namespace" .)) }} +{{- range $namespace := $namespaces }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + {{- if $.Values.rbac.readOnly }} + name: {{ include "kagent-tools.fullname" $ }}-read-role + {{- else }} + name: {{ include "kagent-tools.fullname" $ }}-cluster-admin-role + {{- end }} + namespace: {{ $namespace }} + labels: + {{- include "kagent-tools.labels" $ | nindent 4 }} +rules: + {{- include "kagent-tools.rules" $ | nindent 2 }} +{{- end }} {{- end }} {{- end }} diff --git a/helm/kagent-tools/templates/clusterrolebinding.yaml b/helm/kagent-tools/templates/clusterrolebinding.yaml index 3c9fe3f..d6671a2 100644 --- a/helm/kagent-tools/templates/clusterrolebinding.yaml +++ b/helm/kagent-tools/templates/clusterrolebinding.yaml @@ -1,4 +1,6 @@ {{- if and (not .Values.useDefaultServiceAccount) .Values.rbac.create }} + +{{- if .Values.rbac.clusterScoped }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: @@ -21,4 +23,35 @@ subjects: - kind: ServiceAccount name: {{ include "kagent-tools.fullname" . }} namespace: {{ include "kagent-tools.namespace" . }} + +{{- else }} +{{- $namespaces := .Values.rbac.namespaces | default (list (include "kagent-tools.namespace" .)) }} +{{- range $namespace := $namespaces }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + {{- if $.Values.rbac.readOnly }} + name: {{ include "kagent-tools.fullname" $ }}-read-rolebinding + {{- else }} + name: {{ include "kagent-tools.fullname" $ }}-cluster-admin-rolebinding + {{- end }} + namespace: {{ $namespace }} + labels: + {{- include "kagent-tools.labels" $ | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + {{- if $.Values.rbac.readOnly }} + name: {{ include "kagent-tools.fullname" $ }}-read-role + {{- else }} + name: {{ include "kagent-tools.fullname" $ }}-cluster-admin-role + {{- end }} +subjects: +- kind: ServiceAccount + name: {{ include "kagent-tools.fullname" $ }} + namespace: {{ include "kagent-tools.namespace" $ }} +{{- end }} +{{- end }} + {{- end }} diff --git a/helm/kagent-tools/tests/rbac_test.yaml b/helm/kagent-tools/tests/rbac_test.yaml new file mode 100644 index 0000000..bf73f61 --- /dev/null +++ b/helm/kagent-tools/tests/rbac_test.yaml @@ -0,0 +1,66 @@ +suite: test rbac +templates: + - role.yaml + - rolebinding.yaml +tests: + - it: should render clusterroles by default + asserts: + - isKind: + of: ClusterRole + template: role.yaml + - isKind: + of: ClusterRoleBinding + template: rolebinding.yaml + + - it: should render Roles when clusterScoped is false + set: + rbac.clusterScoped: false + asserts: + - isKind: + of: Role + template: role.yaml + - isKind: + of: RoleBinding + template: rolebinding.yaml + - equal: + path: metadata.namespace + value: NAMESPACE + template: role.yaml + - equal: + path: metadata.namespace + value: NAMESPACE + template: rolebinding.yaml + + - it: should render multiple roles and bindings when namespaces are specified and clusterScoped is false + set: + rbac.clusterScoped: false + rbac.namespaces: + - ns1 + - ns2 + asserts: + - hasDocuments: + count: 2 + template: role.yaml + - equal: + path: metadata.namespace + value: ns1 + template: role.yaml + documentIndex: 0 + - equal: + path: metadata.namespace + value: ns2 + template: role.yaml + documentIndex: 1 + - hasDocuments: + count: 2 + template: rolebinding.yaml + - equal: + path: metadata.namespace + value: ns1 + template: rolebinding.yaml + documentIndex: 0 + - equal: + path: metadata.namespace + value: ns2 + template: rolebinding.yaml + documentIndex: 1 diff --git a/helm/kagent-tools/values.yaml b/helm/kagent-tools/values.yaml index 90050e9..2246cf9 100644 --- a/helm/kagent-tools/values.yaml +++ b/helm/kagent-tools/values.yaml @@ -104,6 +104,12 @@ rbac: # When false, no ClusterRole or ClusterRoleBinding are created. # The ServiceAccount is still created allowing you to attach your own roles externally. create: true + # -- If true, creates ClusterRole and ClusterRoleBinding resources. + # If false, creates Role and RoleBinding resources instead. + clusterScoped: true + # -- When clusterScoped is false, specify additional namespaces to create Roles and RoleBindings in. + # If empty, defaults to the release namespace. + namespaces: [] # When true, deploys a read-only ClusterRole (get, list, watch) instead of cluster-admin. # Pairs well with the --read-only CLI flag which disables write operations at the application layer. # Only applies when rbac.create is true. From ed0e76f8def1d3498436c17637e5ffe7487a6999 Mon Sep 17 00:00:00 2001 From: Jet Chiang Date: Thu, 26 Mar 2026 16:12:35 -0400 Subject: [PATCH 2/2] oops forgot i renamed it Signed-off-by: Jet Chiang --- helm/kagent-tools/tests/rbac_test.yaml | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/helm/kagent-tools/tests/rbac_test.yaml b/helm/kagent-tools/tests/rbac_test.yaml index bf73f61..15d05ca 100644 --- a/helm/kagent-tools/tests/rbac_test.yaml +++ b/helm/kagent-tools/tests/rbac_test.yaml @@ -1,16 +1,16 @@ suite: test rbac templates: - - role.yaml - - rolebinding.yaml + - clusterrole.yaml + - clusterrolebinding.yaml tests: - it: should render clusterroles by default asserts: - isKind: of: ClusterRole - template: role.yaml + template: clusterrole.yaml - isKind: of: ClusterRoleBinding - template: rolebinding.yaml + template: clusterrolebinding.yaml - it: should render Roles when clusterScoped is false set: @@ -18,18 +18,18 @@ tests: asserts: - isKind: of: Role - template: role.yaml + template: clusterrole.yaml - isKind: of: RoleBinding - template: rolebinding.yaml + template: clusterrolebinding.yaml - equal: path: metadata.namespace value: NAMESPACE - template: role.yaml + template: clusterrole.yaml - equal: path: metadata.namespace value: NAMESPACE - template: rolebinding.yaml + template: clusterrolebinding.yaml - it: should render multiple roles and bindings when namespaces are specified and clusterScoped is false set: @@ -40,27 +40,27 @@ tests: asserts: - hasDocuments: count: 2 - template: role.yaml + template: clusterrole.yaml - equal: path: metadata.namespace value: ns1 - template: role.yaml + template: clusterrole.yaml documentIndex: 0 - equal: path: metadata.namespace value: ns2 - template: role.yaml + template: clusterrole.yaml documentIndex: 1 - hasDocuments: count: 2 - template: rolebinding.yaml + template: clusterrolebinding.yaml - equal: path: metadata.namespace value: ns1 - template: rolebinding.yaml + template: clusterrolebinding.yaml documentIndex: 0 - equal: path: metadata.namespace value: ns2 - template: rolebinding.yaml + template: clusterrolebinding.yaml documentIndex: 1