Permissions
What each Harthelm component may do in the cluster.
To install
You create everything in the release namespace, and cluster-wide a ClusterRole, ClusterRoleBinding,
ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding (plus whatever extraObjects holds). Granting a
ClusterRole requires holding its permissions, so in practice this is cluster admin.
With Argo CD, the AppProject must allow these cluster-scoped kinds and the release namespace as a destination.
What Harthelm gets
With rbac.create on (the default):
| ServiceAccount | Permissions |
|---|---|
| core (ClusterRole) | Namespaces: create and manage (the admission guard limits this to rg-*). ConfigMaps, Secrets, Services, PVCs, ResourceQuotas, LimitRanges, Deployments and their scale, Jobs, NetworkPolicies, and with rbac.cnpg CloudNativePG Clusters: full. Pods, pod logs, nodes, PersistentVolumes, EndpointSlices, StorageClasses: read. tokenreviews: create. Ingresses, HTTPRoutes and Certificates: read. Extra kinds from rbac.extraClusterRules. |
| core (Role in the release namespace) | Ingresses or HTTPRoutes and Certificates (custom domains), the backup CronJob (read, for dumps on demand), ReplicaSets (read). |
| router | EndpointSlices: read. Nothing else, no writes. |
| preflight | get of exactly the objects the values name, list of StorageClasses. |
| workspace pods | No Kubernetes API token at all. |
RBAC cannot narrow a ClusterRole to a name prefix or a label, so core can read Secrets and ConfigMaps in every namespace. Its caches only watch objects it labelled, and only core's pod holds its token.
Since 1.4.0 core also runs the doctor's write probe as short Jobs harthelm-write-probe-… in the release namespace,
with the rights above (The write probe).
Cilium
On Cilium, core also renders a CiliumClusterwideNetworkPolicy per team namespace as a backstop. Give core the kind:
rbac:
extraClusterRules:
- apiGroups: [cilium.io]
resources: [ciliumclusterwidenetworkpolicies]
verbs: [get, list, watch, create, update, patch, delete]Without the rule core leaves the backstop out and relies on the NetworkPolicies alone.
The admission guard
A ValidatingAdmissionPolicy bound to core's ServiceAccount (security.admissionGuard.enabled, on by default)
limits what core may write:
- namespaces only when they are named
rg-*and carryharthelm.dev/managed=true. An update needs the label to be there already, so core cannot adopt a namespace someone else created; - namespaced objects only in such namespaces and in the release namespace;
- other cluster-scoped objects only with
harthelm.dev/managed=true, before and after the change.
The policy fails closed and applies to nobody but core.
Pod security
The platform pods run as any non-root UID, drop all capabilities, use a read-only root filesystem and set no
runAsUser, so the release namespace can enforce Pod Security restricted:
kubectl create namespace harthelm-system
kubectl label namespace harthelm-system pod-security.kubernetes.io/enforce=restrictedCore labels the team namespaces itself: restricted, or baseline for a team that a cluster admin allows to set
runAsUser for container services. Workspace pods run as security.defaultUid (default 1001) with group 0; that UID
cannot change while workspace volumes exist, see Storage.