fix: register a verifiable discovery host, and match panelbench's TLS port (1.2.1) - #49
Merged
Merged
Conversation
…ostname The integration's Supervisor path rewrites an existing entry's host to whatever the add-on registers, deliberately and without the guard its other discovery routes apply — an add-on legitimately reallocates its own ports, so freezing the entry against its own add-on would be worse. The consequence is that whatever is registered here had better be an address the panel's certificate names. The container hostname is not. Under `host_network: true` it is only a per-add-on alias for the host, so it is absent from the leaf's SAN and differs between the two emulators. An entry a user had configured by IP was silently moved to it within a minute of creation, and the panelbench swap then failed hostname verification — the panel is meant to keep its identity across that swap, which is the whole point of the shared authority. The advertised address is what the leaf names and what stays constant across the swap, so it is what gets registered. The hostname remains the fallback for an install that configures no advertise address, where it is still better than refusing to register at all. Note that panelbench needs the same change for the rehearsal to work end to end: it still registers its container hostname, so the entry is rewritten again after the swap.
The TLS port was allocated from its own base of 8443 while panelbench derives it as the HTTP port plus 1000. A real panel keeps 443 across a firmware upgrade, so two emulators that stand in for the same panel either side of one have to agree on where it serves TLS — a panel whose TLS port moved across the swap is not a panel that was upgraded. Adopted panelbench's rule, down to the `https_port_for` helper, so the two read the same and neither can drift without the other noticing. Deriving also removes the second pool: there is one allocation per panel now, and releasing it releases the pair, so the two pools can no longer fall out of step. Pair-retry semantics are unchanged — either half may be the one in use, and both move together, so the next allocation is a clean pair. The offset is asserted in a test rather than left implicit in a constant, since it is a contract with another repository and changing it on one side alone breaks the rehearsal silently.
1.2.0 is already installed from the previous merge, so these two fixes cannot ship under that version — the add-on store would never offer them. The 1.2.0 entry is left describing only what it shipped. Its TLS port paragraph had been edited in place to describe the derived port, which 1.2.0 does not do: that release allocated from a separate base of 8443, and saying otherwise would misdescribe the build people are running.
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.
Follow-on to #48, which merged while these were being written. Ships as 1.2.1, not 1.2.0: that version is already installed from the #48 merge, so the add-on store would never offer these under it.
Both come from a repeat of the firmware-upgrade rehearsal on 1.2.0 / panelbench 2.5.1. The gateway fix from #48 worked and both emulators advertised the same address, but the swap still failed for two harness reasons.
Supervisor discovery registered a host the certificate does not name
register_panelregistered the container hostname. Underhost_network: truethat is only a per-add-on alias for the host — it is absent from the leaf's SAN and it differs between the two emulators.async_step_hassiorewrites an existing entry's host to whatever the add-on registers. That is deliberate and documented, and it is not guarded the way the integration's other discovery routes are, because an add-on legitimately reallocates its own ports and the guard would freeze an entry against its own add-on. The consequence is that whatever gets registered here had better be an address the certificate names.It was not. An entry a user had configured by IP was silently moved to the hostname within a minute of creation, and the panelbench swap then failed hostname verification — the panel is meant to keep its identity across that swap, which is what the shared authority exists for.
The advertised address is what the leaf names and what stays constant across the swap, so it is what gets registered now. The container hostname stays as the fallback where no advertise address is configured, where it still beats refusing to register.
The TLS port disagreed with panelbench
The port was allocated from its own base of 8443; panelbench derives it as the HTTP port plus 1000. A real panel keeps 443 across a firmware upgrade, so two emulators standing in for the same panel either side of one have to agree on where it serves TLS — a panel whose TLS port moved across the swap is not a panel that was upgraded.
Now derived with the same
https_port_forhelper panelbench uses, so the two read alike and neither can drift without the other noticing. Deriving also removes the second pool: one allocation per panel, and releasing it releases the pair, so the two pools can no longer fall out of step. Pair-retry semantics are unchanged — either half may be the one in use, both move together, so the next allocation is a clean pair.The offset is asserted in a test rather than left implicit in a constant, because it is a contract with another repository that would otherwise break silently.
This is user-visible for anyone who noted the port from 1.2.0: a panel on HTTP 8081 now serves TLS on 9081 rather than 8443. Nothing needs changing by hand, since the port is published in discovery, but the changelog calls it out for firewall rules written against the old number.
Changelog
1.2.0's entry is left describing only what it shipped. Its TLS port paragraph had been edited in place to describe the derived port, which 1.2.0 does not do — that release allocated from a separate base — so it has been restored; saying otherwise would misdescribe the build people are currently running.
Testing
489 passed, up from 486 on #48's head. The same three failures remain (test_graph_builder_topology×2,test_main_logging) and are pre-existing onmain, unrelated: the pin isebus-sdk==0.23.1while the vendored emitter targets the 0.1.xDeviceAPI.Three new tests: the registered host is the advertised address; the hostname fallback still applies with no advertise address configured; and the offset matches panelbench's, pinned by value so a one-sided change fails here rather than in a rehearsal.
run-local.shnow prints the HTTPS port alongside the HTTP one, since it is derived rather than typed and adding a panel by hand needs it.Follow-up, not in this PR
panelbench needs the same host change.
supervisor_discovery.py:121there still doeshost = _container_hostname(), so after the swap the entry is rewritten to panelbench's own hostname and hostname verification fails at the same point. Fixing the simulator half alone does not complete the rehearsal; both halves are needed. That repo is owned by another change in flight.