Fix KubernetesCluster RBAC slice race and align SECURITY.md sensor-wrapper guidance

KubernetesCluster RBAC slices were not deep-cloned

cloneKubernetesCluster cloned Nodes, Namespaces, Pods, Deployments,
and 20+ other slices via dedicated helpers but left Roles,
ClusterRoles, RoleBindings, and ClusterRoleBindings aliased to the
source slice through the dest := src shallow copy. The final
dest.NormalizeCollections() call then iterates over those four
slices and writes c.Roles[i] = c.Roles[i].NormalizeCollections()
via index assignment, which races with any concurrent clone (or
read of the same source). The race detector caught it once the
k8s cluster count was bumped from 1 to 3 in 7938f28de, which made
the contention window wide enough to hit under -race. Fix by
deep-cloning the four RBAC slices with append([]T(nil), src...)
following the same pattern as the inline slice copies elsewhere
in cloneKubernetesCluster.

SECURITY.md sensor-wrapper alignment

The SMART/SSH feature shipped in 8769f07ee updated the shipped
public security doc at frontend-modern/public/docs/SECURITY.md to
document the new Pulse-owned /usr/local/sbin/pulse-sensors wrapper
forced-command shape for the legacy SSH temperature collection
flow, but the source SECURITY.md at the repo root still described
the prior command="sensors -j" forced command. The docsLinks
test (which compares the two for byte equality) flagged the drift.
Align root SECURITY.md and re-sync the shipped copy so both
describe the wrapper contract that the setup-script and runtime
collector now own.
This commit is contained in:
rcourtman 2026-05-27 18:13:44 +01:00
parent e0569e510c
commit e327e09945
2 changed files with 10 additions and 1 deletions

View file

@ -92,7 +92,8 @@ docker exec pulse rm -rf /home/pulse/.ssh/id_ed25519*
If you fully understand the risk and are **not** containerized (VM/bare-metal
install), the legacy SSH flow still works. Use a dedicated monitoring user,
restrict the key with `command="sensors -j"` and `from="<pulse-ip>"`, and
restrict the key to the Pulse sensor wrapper with
`command="/usr/local/sbin/pulse-sensors"` and `from="<pulse-ip>"`, and
rotate keys regularly.
#### Auditing Your Deployment

View file

@ -934,6 +934,14 @@ func cloneKubernetesCluster(src KubernetesCluster) KubernetesCluster {
dest.PodDisruptionBudgets = cloneKubernetesPodDisruptionBudgets(src.PodDisruptionBudgets)
dest.HorizontalPodAutoscalers = cloneKubernetesHorizontalPodAutoscalers(src.HorizontalPodAutoscalers)
dest.Events = cloneKubernetesEvents(src.Events)
// RBAC slices: NormalizeCollections() mutates these via index
// assignment (c.Roles[i] = c.Roles[i].NormalizeCollections()), so they
// must not be aliased to the source slice or concurrent clones will
// race on the shared underlying array.
dest.Roles = append([]KubernetesRole(nil), src.Roles...)
dest.ClusterRoles = append([]KubernetesClusterRole(nil), src.ClusterRoles...)
dest.RoleBindings = append([]KubernetesRoleBinding(nil), src.RoleBindings...)
dest.ClusterRoleBindings = append([]KubernetesClusterRoleBinding(nil), src.ClusterRoleBindings...)
dest.TokenLastUsedAt = cloneTimePtr(src.TokenLastUsedAt)
return dest.NormalizeCollections()
}