Warn that an api key supersedes the OTA password

This commit is contained in:
J. Nick Koston
2026-09-05 12:09:53 +02:00
parent 3601a1aad8
commit b4c6a40593
2 changed files with 52 additions and 0 deletions
@@ -129,6 +129,20 @@ def ota_esphome_final_validate(config: ConfigType) -> None:
_validate_no_password_with_encryption(ota_conf)
if (encryption_conf := ota_conf.get(CONF_ENCRYPTION)) is not None:
_resolve_encryption_key(encryption_conf, api_conf)
elif CONF_PASSWORD in ota_conf and _api_static_key(api_conf) is not None:
_LOGGER.warning(
"The '%s' %s %s also authenticates OTA uploads and encrypts them, "
"so '%s' %s only guards plaintext uploads; remove '%s' and add "
"'%s' under '%s' to require encryption",
CONF_API,
CONF_ENCRYPTION,
CONF_KEY,
CONF_OTA,
CONF_PASSWORD,
CONF_PASSWORD,
CONF_ENCRYPTION,
CONF_OTA,
)
if any(
conf.get(CONF_PLATFORM) == CONF_WEB_SERVER for conf in full_ota_conf
) and any(
@@ -346,6 +346,44 @@ def test_encryption_with_captive_portal_web_server_ota_warns(
fv.full_config.reset(token)
def test_password_with_api_key_warns(caplog: pytest.LogCaptureFixture) -> None:
"""An api key makes the device offer encryption, which authenticates an
uploader without the password; the config validates with a warning."""
full_conf = {
CONF_API: {CONF_ENCRYPTION: {CONF_KEY: API_KEY}},
CONF_OTA: [_make_ota_config(port=3232, **{CONF_PASSWORD: "pw"})],
}
token = fv.full_config.set(full_conf)
try:
with caplog.at_level(logging.WARNING):
ota_esphome_final_validate({})
assert any("only guards plaintext" in r.message for r in caplog.records)
finally:
fv.full_config.reset(token)
@pytest.mark.parametrize(
"api_conf",
[{}, {CONF_ENCRYPTION: {}}, {CONF_ENCRYPTION: {CONF_KEY: ZEROS_KEY}}],
ids=["no_api", "runtime_key", "zeros_key"],
)
def test_password_without_static_api_key_no_warning(
caplog: pytest.LogCaptureFixture, api_conf: dict[str, Any]
) -> None:
"""Without a build-time api key there is no offer, so nothing to warn about."""
full_conf = {
CONF_API: api_conf,
CONF_OTA: [_make_ota_config(port=3232, **{CONF_PASSWORD: "pw"})],
}
token = fv.full_config.set(full_conf)
try:
with caplog.at_level(logging.WARNING):
ota_esphome_final_validate({})
assert not any("only guards plaintext" in r.message for r in caplog.records)
finally:
fv.full_config.reset(token)
def test_web_server_ota_without_encryption_unaffected() -> None:
"""web_server ota stays valid alongside an unencrypted esphome entry."""
full_conf = {