mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 10:12:52 +00:00
Refuse a key that is not on a line of its own, name the sharers of an include that gets old_key
This commit is contained in:
+19
-10
@@ -41,14 +41,22 @@ class KeyEdit(LineEdit):
|
||||
def _key_blocks(raw: ConfigType, key: str) -> list[ConfigType]:
|
||||
"""The api and esphome ota ``encryption:`` mappings whose key is ``key``."""
|
||||
blocks = [raw.get(CONF_API) or {}, *esphome_ota_items(raw)]
|
||||
# A bare ota block gets the api key at validation; it has no key line
|
||||
return [
|
||||
block[CONF_ENCRYPTION]
|
||||
for block in blocks
|
||||
if (node := static_encryption_key(block)) is not None
|
||||
and str(node) == key
|
||||
and source_of(block[CONF_ENCRYPTION], CONF_KEY) is not None
|
||||
]
|
||||
found = []
|
||||
for block in blocks:
|
||||
if (node := static_encryption_key(block)) is None or str(node) != key:
|
||||
continue
|
||||
encryption = block[CONF_ENCRYPTION]
|
||||
if source_of(encryption, CONF_KEY) is not None:
|
||||
found.append(encryption)
|
||||
elif hasattr(next(k for k in encryption if k == CONF_KEY), "esp_range"):
|
||||
# Read from a file but not on a line of its own, as with a merge
|
||||
# key; only a key validation added, which has no range at all,
|
||||
# is passed over (a bare ota block takes the api key)
|
||||
raise EsphomeError(
|
||||
f"The '{CONF_KEY}' of an '{CONF_ENCRYPTION}:' block is not on a "
|
||||
"line of its own; edit the key by hand"
|
||||
)
|
||||
return found
|
||||
|
||||
|
||||
_INDENT_RE = re.compile(r"\s*")
|
||||
@@ -165,8 +173,8 @@ def with_sharers(edits: list[KeyEdit]) -> list[str]:
|
||||
f"{path} includes {match['target']} through a substitution"
|
||||
)
|
||||
for edit in edits:
|
||||
if edit.insert_after:
|
||||
continue
|
||||
if edit.insert_after and edit.secret:
|
||||
continue # a new secrets line has no users yet
|
||||
ref = (
|
||||
_secret_use_re(edit.secret) if edit.secret else _file_use_re(edit.path.name)
|
||||
)
|
||||
@@ -223,6 +231,7 @@ def _secret_insert(secrets_path: Path, after: str, name: str, value: str) -> Key
|
||||
m.string,
|
||||
f'{_indent(m.string)}{name}: "{value}"',
|
||||
insert_after=True,
|
||||
secret=name,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1074,10 +1074,27 @@ def test_a_key_merged_from_an_anchor_is_refused(tmp_path: Path) -> None:
|
||||
f'named: &named\n key: "{OLD_KEY}"\n\napi:\n encryption:\n <<: *named\n\n'
|
||||
"ota:\n - platform: esphome\n encryption:\n",
|
||||
)
|
||||
with pytest.raises(EsphomeError, match="was not found on a line of the yaml"):
|
||||
with pytest.raises(EsphomeError, match="not on a line of its own"):
|
||||
locate_key_edits(OLD_KEY, NEW_KEY)
|
||||
|
||||
|
||||
def test_old_key_inserted_into_a_shared_include_names_the_sharers(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""The ota block lives in an include another device loads too, so the
|
||||
inserted old_key reaches that device at its next install."""
|
||||
(tmp_path / "ota.yaml").write_bytes(
|
||||
f'platform: esphome\nencryption:\n key: "{OLD_KEY}"\n'.encode()
|
||||
)
|
||||
(tmp_path / "other.yaml").write_bytes(b"ota:\n - !include ota.yaml\n")
|
||||
_setup(tmp_path, "esphome:\n name: test\n\nota:\n - !include ota.yaml\n")
|
||||
edits = _edits()
|
||||
assert [(e.insert_after, [p.name for p in e.shared_with]) for e in edits] == [
|
||||
(False, ["other.yaml"]),
|
||||
(True, ["other.yaml"]),
|
||||
]
|
||||
|
||||
|
||||
def test_key_overridden_on_top_of_a_package_block(tmp_path: Path) -> None:
|
||||
"""The device yaml's line wins the merge and is the one rewritten."""
|
||||
from esphome.config_helpers import merge_config
|
||||
|
||||
Reference in New Issue
Block a user