Repository navigation
Authenticate the node to the broker, with credentials kept out of git (#7) - #24
Merged
Merged
Conversation
…#7) The node sends a username and password in AT+MQTTUSERCFG. They are read from /mqtt_credentials.json on the board, which deploy.sh copies there from the bench's ~/.config/layout-feedback/<node>.json. That file is the only copy, so the password never passes through git or the dev machine. If the file is missing or malformed, the node flashes new LED code 8 instead of connecting anonymously. The modem echoes the command back, so the password is also redacted from the console. docs/broker-auth.md records the identities, the ACL, and the trap: mosquitto acknowledges a publish the ACL denies, so the node cannot see the failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bench broker used to accept anonymous clients on the LAN. Any device on that network could publish a fabricated
clearon an occupied block, and the orchestrator would believe it. Now every client has its own identity, and an ACL limits each identity to the topics it owns. This PR is the firmware and deploy side of that change. The broker side is already live on the bench.The ACL
orchestratorlayout/#io-nodesensor/+/readingandpoint/+/reading; readpoint/+/query. Pinned to this layout's id.monitorlayout/#and$SYS/#, formosquitto_subThe
io-noderules cover topic kinds, not individual sensor ids, and that is deliberate. Mosquitto acknowledges a publish the ACL denies and then drops it. The node'spublish()returns True, and the broker log records nothing at the default level (checked on the bench). If the ACL listed sensor ids, installing a sensor would fail in exactly the silent way rule 3 exists to prevent.How the node gets its password
~/.config/layout-feedback/<node>.json(mode 0600). It is never in git or on the dev machine.scripts/deploy.shcopies it to the board as/mqtt_credentials.jsonon every deploy. It refuses to deploy if the file is missing, and checks that before touching the board. The file is.jsonrather than.py, so the root sweep leaves it alone and nothing can import it.broker_credentials.pyis new, pure code with nomachineimport. It reads and validates the file. A missing or malformed file raisesCredentialsError, which flashes the new LED code 8, and the node never falls back to anonymous. Values are limited to 64 printable ASCII characters with no",\or,, so a bad value fails here and not as "connection refused".MQTTATClientgainsusernameandpasswordand sends them inAT+MQTTUSERCFG. The modem echoes that command back, so the password is redacted from the debug log and from failure dumps.The broker config, the password file, the ACL and the other clients' credentials live on the bench.
docs/broker-auth.mdrecords where each one is and how to rotate it.Verified at cutover
Host suite:
207 passed in 0.12s.On the bench, 2026-09-23:
u'io-node'andu'orchestrator'on every connect. After the broker restart the node reconnected through its own reconnect path.Connection refused: Not authorized.monitorwatcher on an all-zero layoutId received nothing from three probes:io-node→point/…/command,io-node→sensor/…/readingunder the wrong layout id, andmonitor→ anything. The positive control, anorchestratorpublish to the same namespace, arrived.onlinewith no fault reason, and both Goods Shed readings kept re-asserting.Not covered on the host: whether the real ESP-AT firmware reports a rejected password differently from an unreachable broker. It's treated as the same failure (code 5), and the doc says so.
Docs
docs/broker-auth.mdis new.docs/startup-and-status-led.mdgains code 8, and code 5 now covers rejected credentials.CLAUDE.mdgets the doc-index row, the module listing and a trap entry.TLS is out of scope and tracked separately.
Closes #7
🤖 Generated with Claude Code