Found on the first real use of the restricted identity: assessing the VeleroBackupFailed issue (#251) needs backups.velero.io (latest apps-daily run is PartiallyFailed — data-mover pod unschedulable on an unbound PVC), and the ClusterRole had neither velero.io nor CNPG. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NV7bZzZLeoFUEdAeCSLEei
136 lines
4.6 KiB
YAML
136 lines
4.6 KiB
YAML
# Least-privilege identity for the CI diagnostic agents (alert-monitor and
|
|
# issue-fix pipelines, see .woodpecker/). The pipelines mint a short-lived
|
|
# (1 h) token for this ServiceAccount at run time via `kubectl create token`
|
|
# — no long-lived credential exists anywhere.
|
|
#
|
|
# Scope: read-only on workload/config/CRD state cluster-wide, plus the
|
|
# Prometheus and Alertmanager HTTP APIs via the apiserver service proxy.
|
|
# Secrets are deliberately NOT readable: the agents write their findings into
|
|
# public Gitea issues/PRs, so nothing secret may be readable in the first
|
|
# place. pods/log IS granted — it is what turns guessed diagnoses into
|
|
# verified ones (e.g. the pve-exporter 401) — accepting the residual risk
|
|
# that a workload logs something sensitive; the agent prompts forbid pasting
|
|
# bulk output.
|
|
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
name: ci-diagnostics
|
|
namespace: monitoring
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRole
|
|
metadata:
|
|
name: ci-diagnostics-readonly
|
|
rules:
|
|
- apiGroups: [""]
|
|
resources:
|
|
- pods
|
|
- pods/log
|
|
- events
|
|
- nodes
|
|
- namespaces
|
|
- services
|
|
- endpoints
|
|
- persistentvolumeclaims
|
|
- persistentvolumes
|
|
- configmaps
|
|
- resourcequotas
|
|
- limitranges
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["apps"]
|
|
resources: ["deployments", "statefulsets", "daemonsets", "replicasets", "controllerrevisions"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["batch"]
|
|
resources: ["jobs", "cronjobs"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["events.k8s.io"]
|
|
resources: ["events"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["networking.k8s.io"]
|
|
resources: ["ingresses", "networkpolicies"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["cilium.io"]
|
|
resources: ["ciliumnetworkpolicies", "ciliumclusterwidenetworkpolicies"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups:
|
|
- kustomize.toolkit.fluxcd.io
|
|
- helm.toolkit.fluxcd.io
|
|
- source.toolkit.fluxcd.io
|
|
- image.toolkit.fluxcd.io
|
|
- notification.toolkit.fluxcd.io
|
|
resources: ["*"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["external-secrets.io"]
|
|
resources: ["externalsecrets", "secretstores", "clustersecretstores"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["monitoring.coreos.com"]
|
|
resources: ["prometheusrules", "servicemonitors", "podmonitors", "probes", "prometheuses", "alertmanagers"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["cert-manager.io"]
|
|
resources: ["certificates", "certificaterequests", "issuers", "clusterissuers"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["ceph.rook.io"]
|
|
resources: ["*"]
|
|
verbs: ["get", "list"]
|
|
# Velero backup/restore state — needed to assess VeleroBackupFailed-class
|
|
# alerts (found missing on the first real triage of issue #251). NOTE for
|
|
# agents: `get backup -n velero` resolves to CNPG's backups.postgresql
|
|
# first — always use the full form `backups.velero.io`.
|
|
- apiGroups: ["velero.io"]
|
|
resources: ["*"]
|
|
verbs: ["get", "list"]
|
|
# CNPG cluster/backup state — same reasoning for database alerts.
|
|
- apiGroups: ["postgresql.cnpg.io"]
|
|
resources: ["*"]
|
|
verbs: ["get", "list"]
|
|
- apiGroups: ["storage.k8s.io"]
|
|
resources: ["storageclasses", "volumeattachments"]
|
|
verbs: ["get", "list"]
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRoleBinding
|
|
metadata:
|
|
name: ci-diagnostics-readonly
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: ClusterRole
|
|
name: ci-diagnostics-readonly
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: ci-diagnostics
|
|
namespace: monitoring
|
|
---
|
|
# Prometheus + Alertmanager HTTP APIs through the apiserver service proxy —
|
|
# the same path the alert-monitor fetch step uses (see the netpol note in
|
|
# .woodpecker/alert-monitor.yml). resourceNames list both the bare and the
|
|
# :port-qualified form because the proxy URL carries the port in the name
|
|
# segment and RBAC matches it verbatim.
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: Role
|
|
metadata:
|
|
name: ci-diagnostics-service-proxy
|
|
namespace: monitoring
|
|
rules:
|
|
- apiGroups: [""]
|
|
resources: ["services/proxy"]
|
|
verbs: ["get"]
|
|
resourceNames:
|
|
- kube-prometheus-stack-prometheus
|
|
- "kube-prometheus-stack-prometheus:9090"
|
|
- kube-prometheus-stack-alertmanager
|
|
- "kube-prometheus-stack-alertmanager:9093"
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: RoleBinding
|
|
metadata:
|
|
name: ci-diagnostics-service-proxy
|
|
namespace: monitoring
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: Role
|
|
name: ci-diagnostics-service-proxy
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: ci-diagnostics
|
|
namespace: monitoring
|