Repository navigation
trident-acl-agent: verify Node systemUUID matches local hardware - #837
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟡 Changes recommended
Watched Node objects bypass identity verification, allowing reconciliation against recycled Nodes.
2 open findings
What changed in this PR
Adds hardware UUID validation to prevent the ACL agent from accepting a stale Kubernetes Node object.
Changes:
- Compares Node and local DMI system UUIDs.
- Treats mismatches as
NodeGone. - Adds focused identity-verification tests.
| File | Description |
|---|---|
crates/trident-acl-agent/src/annotations/k8s.rs |
Adds Node identity verification and tests. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Added run-node-resilience phase 3 (storm E2E) + fast Go unit tests covering the systemUUID-mismatch case end-to-end: sets a mismatched systemUUID on the fake Node, restarts trident-acl-agent, and confirms it (a) logs the mismatch distinctly from a plain 404 and (b) treats it the same as NodeGone — no crash, same PID, resumes once the systemUUID matches again. See tools/storm/aclagent/tests/node_resilience.go and proxies/apiserver_test.go. |
|
Pushed a follow-up fix after investigating whether AKS nodes guarantee status.nodeInfo.systemUUID matches /sys/class/dmi/id/product_uuid: Confirmed via cadvisor source that kubelet populates systemUUID by reading the exact same file we check against. However, if cadvisor fails to read that file on the kubelet side, it logs an error but still lets node registration proceed with an empty systemUUID rather than failing. An empty value only means kubelet could not determine the UUID - it is not evidence the Node describes a different machine. Updated verify_node_identity to skip verification (warn + Ok) when the Node reports an empty systemUUID, same as when our local file is unreadable, instead of treating it as a mismatch. Without this, a rare kubelet-side DMI read failure could have falsely locked us out of an otherwise-healthy node forever. Updated/added unit tests accordingly (missing_node_system_info_skips_verification, empty_node_system_uuid_skips_verification). |
|
Fixed the storm run-node-resilience failure from build 1220454: readVmProductUUID ran a plain cat /sys/class/dmi/id/product_uuid over SSH as the non-root test user, which hit Permission denied (file is 0400 root-only) and aborted the whole aclagent scenario before any assertions ran. Every other privileged command in this harness already uses sudo; added it here too. |
|
Made the systemUUID verification opt-in: added TRIDENT_ACL_AGENT_VALIDATE_NODE_UUID (presence-only env var, same convention as osutils::container::DOCKER_ENVIRONMENT). Disabled by default - kubelet sourcing systemUUID from the same product_uuid file is well-supported in general but not a confirmed guarantee across every environment this agent runs in, so it is opt-in per deployment rather than unconditional. Enabled it for the storm aclagent E2E scenario via the existing trident-acl-agent.service override.conf drop-in (baked into both base and update VM images), so run-node-resilience Phase 3 and the general NodeGone handling keep exercising this path. Documented the new env var and behavior in docs/Explanation/Trident-ACL-Agent.md. |
1d360a0 to
a4bfc49
Compare
|
Copilot resolve the merge conflicts in this pull request |
…t-node-uuid-verify # Conflicts: # tests/images/trident-vm-testimage/base/files/trident-acl-agent-override.conf Co-authored-by: bfjelds <9874445+bfjelds@users.noreply.github.com>
Resolved the conflict, retaining both branch-specific settings alongside |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6113bec5-d3d1-4cab-9988-bb52fa6b7bb7
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6113bec5-d3d1-4cab-9988-bb52fa6b7bb7
|
Copilot resolve the merge conflicts in this pull request |
…t-node-uuid-verify # Conflicts: # crates/trident-acl-agent/src/core/config.rs # docs/Development/Testing/TridentAclAgent-Tests.md # tools/storm/aclagent/README.md Co-authored-by: bfjelds <9874445+bfjelds@users.noreply.github.com>
Resolved the conflicts against current |
Paco Huelsz (frhuelsz)
left a comment
There was a problem hiding this comment.
LGTM, agent reviewed and brought up these non-blocking concerns:
| Concern | Scenario and impact | Proposed resolution |
|---|---|---|
| Status PATCH race | A Node could be replaced after it was verified but before an in-progress or terminal status PATCH. The old VM could write stale status onto the replacement, but cannot service or reboot it; operation IDs also help the controller reject unrelated results. | Follow-up hardening: atomically test the verified Node UID when PATCHing and treat a failed test as NodeGone. UID is preferable to resourceVersion, which changes during normal Node updates. |
| Pending-commit recovery | If a Node name is reassigned while the old VM reboots—or the old VM later returns as a zombie—it can publish commit status before another verified read. The local commit must remain independent of Kubernetes to avoid firmware fallback. | Commit and persist locally first, then verify the Node before publishing. If identity does not match, retain the result instead of patching the replacement. |
| Empty Node UUID | An empty UUID means kubelet could not determine hardware identity; it does not prove a mismatch. Failing closed could permanently disable updates on an otherwise valid node. | Keep the documented warning-and-skip behavior, or add an explicit strict mode where an empty UUID is treated as NodeGone. |
None of these should block this PR. The main request-processing race is fixed, and the remaining cases require a broader split-brain failure where infrastructure reuses a Node name without fencing the old VM. I recommend tracking conditional PATCH protection as follow-up hardening; the pending-recovery and empty-UUID behaviors are reasonable accepted tradeoffs.
Separate nit: git diff --check reports trailing whitespace in the testing documentation.



Fixes trident-acl-agent so a stale/recycled Node name can't be mistaken for this machine's own Node object. Opt-in, disabled by default.
Change
trueto enable verification. Disabled (false) by default: the assumption that kubelet's systemUUID always traces back to this machine's product_uuid hasn't been confirmed across every environment this agent runs in, so it's opt-in per-deployment rather than unconditional.Testing
storm-trident run aclagentsuite - 7/7 PASS, including run-node-resilience's systemUUID mismatch phases.