From d5b613ab92f787313fc2a2409426932a9c1461da Mon Sep 17 00:00:00 2001 From: John T Skarbek Date: Fri, 16 Oct 2026 09:43:17 -0400 Subject: [PATCH] fix(alloy): narrow the collector RBAC to required permissions The Alloy subchart grants cluster-wide read access to secrets and configmaps by default, and several rules the collector config does not use. A token read from an Alloy pod on any node can list every Secret in the cluster. Override alloy.rbac.rules and alloy.rbac.clusterRules. Keep only get, list and watch on pods and nodes (pod and node discovery) and get on nodes/metrics (cAdvisor scrape through the kubelet). --- CHANGELOG.md | 1 + README.md | 13 +++++ coder-observability/values.yaml | 16 ++++++ compiled/resources.yaml | 91 --------------------------------- 4 files changed, 30 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bab2339..f6588c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - BREAKING: replaces the `grafana-agent` subchart with Grafana Alloy (`alloy` chart 1.13.1). Rename any `grafana-agent:` values overrides to `alloy:`. - Pod `job` label changes from `/grafana-agent/grafana-agent` to `/alloy/alloy`; update queries and alerts that match the old label. - Alloy listens on port 12345 instead of 80. +- Alloy `ClusterRole` is narrowed to `pods`, `nodes` and `nodes/metrics`. It no longer grants read access to `secrets` and `configmaps`. If you add components through `alloy.extraBlocks` that need more access, override `alloy.rbac.rules` and `alloy.rbac.clusterRules`. ## v0.3.0 diff --git a/README.md b/README.md index ec9d13b..5aa9ca6 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,19 @@ values which are defined [here](https://github.com/grafana/helm-charts/tree/main | alloy.fullnameOverride | string | `"alloy"` | | | alloy.podLogsRelabelRules | string | `""` | | | alloy.podMetricsRelabelRules | string | `""` | | +| alloy.rbac.clusterRules[0].apiGroups[0] | string | `""` | | +| alloy.rbac.clusterRules[0].resources[0] | string | `"nodes"` | | +| alloy.rbac.clusterRules[0].verbs[0] | string | `"get"` | | +| alloy.rbac.clusterRules[0].verbs[1] | string | `"list"` | | +| alloy.rbac.clusterRules[0].verbs[2] | string | `"watch"` | | +| alloy.rbac.clusterRules[1].apiGroups[0] | string | `""` | | +| alloy.rbac.clusterRules[1].resources[0] | string | `"nodes/metrics"` | | +| alloy.rbac.clusterRules[1].verbs[0] | string | `"get"` | | +| alloy.rbac.rules[0].apiGroups[0] | string | `""` | | +| alloy.rbac.rules[0].resources[0] | string | `"pods"` | | +| alloy.rbac.rules[0].verbs[0] | string | `"get"` | | +| alloy.rbac.rules[0].verbs[1] | string | `"list"` | | +| alloy.rbac.rules[0].verbs[2] | string | `"watch"` | | | alloy.withOTLPReceiver | bool | `false` | | | global.alerts.enabled | bool | `true` | enable or disable alerting | | global.alerts.kind | string | `"configmap"` | the container resource kind in which alerts should be created; valid values are "prometheusrule" or "configmap" | diff --git a/coder-observability/values.yaml b/coder-observability/values.yaml index 834739a..d62ae7c 100644 --- a/coder-observability/values.yaml +++ b/coder-observability/values.yaml @@ -213,6 +213,22 @@ alloy: prometheus.io/scrape: "true" crds: create: false + # Only the permissions that the collector config uses: pod and node discovery, + # and the kubelet cAdvisor scrape. The subchart defaults also grant cluster-wide + # read access to secrets and configmaps. If you add components through + # extraBlocks that need more, override these lists. + rbac: + rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + clusterRules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["nodes/metrics"] + verbs: ["get"] withOTLPReceiver: false diff --git a/compiled/resources.yaml b/compiled/resources.yaml index c735291..20d4978 100644 --- a/compiled/resources.yaml +++ b/compiled/resources.yaml @@ -10980,87 +10980,10 @@ metadata: app.kubernetes.io/part-of: alloy app.kubernetes.io/component: rbac rules: - - apiGroups: - - "" - - discovery.k8s.io - - networking.k8s.io - resources: - - endpoints - - endpointslices - - ingresses - - pods - - services - verbs: - - get - - list - - watch - apiGroups: - "" resources: - pods - - pods/log - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - monitoring.grafana.com - resources: - - podlogs - verbs: - - get - - list - - watch - - apiGroups: - - monitoring.coreos.com - resources: - - prometheusrules - verbs: - - get - - list - - watch - - apiGroups: - - monitoring.coreos.com - resources: - - alertmanagerconfigs - verbs: - - get - - list - - watch - - apiGroups: - - monitoring.coreos.com - resources: - - podmonitors - - servicemonitors - - probes - - scrapeconfigs - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - events - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - configmaps - - secrets - verbs: - - get - - list - - watch - - apiGroups: - - apps - - extensions - resources: - - replicasets verbs: - get - list @@ -11073,26 +10996,12 @@ rules: - get - list - watch - - apiGroups: - - "" - resources: - - nodes/pods - verbs: - - get - - list - - watch - apiGroups: - "" resources: - nodes/metrics verbs: - get - - list - - watch - - nonResourceURLs: - - /metrics - verbs: - - get --- # Source: coder-observability/charts/grafana/templates/clusterrole.yaml kind: ClusterRole