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..15d05ca --- /dev/null +++ b/helm/kagent-tools/tests/rbac_test.yaml @@ -0,0 +1,66 @@ +suite: test rbac +templates: + - clusterrole.yaml + - clusterrolebinding.yaml +tests: + - it: should render clusterroles by default + asserts: + - isKind: + of: ClusterRole + template: clusterrole.yaml + - isKind: + of: ClusterRoleBinding + template: clusterrolebinding.yaml + + - it: should render Roles when clusterScoped is false + set: + rbac.clusterScoped: false + asserts: + - isKind: + of: Role + template: clusterrole.yaml + - isKind: + of: RoleBinding + template: clusterrolebinding.yaml + - equal: + path: metadata.namespace + value: NAMESPACE + template: clusterrole.yaml + - equal: + path: metadata.namespace + value: NAMESPACE + template: clusterrolebinding.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: clusterrole.yaml + - equal: + path: metadata.namespace + value: ns1 + template: clusterrole.yaml + documentIndex: 0 + - equal: + path: metadata.namespace + value: ns2 + template: clusterrole.yaml + documentIndex: 1 + - hasDocuments: + count: 2 + template: clusterrolebinding.yaml + - equal: + path: metadata.namespace + value: ns1 + template: clusterrolebinding.yaml + documentIndex: 0 + - equal: + path: metadata.namespace + value: ns2 + template: clusterrolebinding.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.