Bump securetar to 2025.1.3 (#135762)

* Bump securetar to 2025.1.3

* Remove outdated fixture
This commit is contained in:
Erik Montnemery 2025-01-16 13:26:52 +01:00 committed by GitHub
parent 1cff45b8b7
commit 6cbe18ebbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 24 additions and 30 deletions

View File

@ -8,5 +8,5 @@
"integration_type": "system",
"iot_class": "calculated",
"quality_scale": "internal",
"requirements": ["cronsim==2.6", "securetar==2025.1.2"]
"requirements": ["cronsim==2.6", "securetar==2025.1.3"]
}

View File

@ -13,13 +13,7 @@ import tarfile
from typing import IO, Self, cast
import aiohttp
from securetar import (
PLAINTEXT_SIZE_HEADER,
VERSION_HEADER,
SecureTarError,
SecureTarFile,
SecureTarReadError,
)
from securetar import SecureTarError, SecureTarFile, SecureTarReadError
from homeassistant.backup_restore import password_to_key
from homeassistant.core import HomeAssistant
@ -205,8 +199,6 @@ def validate_password_stream(
for obj in input_tar:
if not obj.name.endswith((".tar", ".tgz", ".tar.gz")):
continue
if obj.pax_headers.get(VERSION_HEADER) != "2.0":
raise UnsupportedSecureTarVersion
istf = SecureTarFile(
None, # Not used
gzip=False,
@ -215,6 +207,8 @@ def validate_password_stream(
fileobj=input_tar.extractfile(obj),
)
with istf.decrypt(obj) as decrypted:
if istf.securetar_header.plaintext_size is None:
raise UnsupportedSecureTarVersion
try:
decrypted.read(1) # Read a single byte to trigger the decryption
except SecureTarReadError as err:
@ -270,10 +264,6 @@ def _decrypt_backup(
if not obj.name.endswith((".tar", ".tgz", ".tar.gz")):
output_tar.addfile(obj, input_tar.extractfile(obj))
continue
if obj.pax_headers.get(VERSION_HEADER) != "2.0":
raise UnsupportedSecureTarVersion
decrypted_obj = copy.deepcopy(obj)
decrypted_obj.size = int(obj.pax_headers[PLAINTEXT_SIZE_HEADER])
istf = SecureTarFile(
None, # Not used
gzip=False,
@ -282,6 +272,10 @@ def _decrypt_backup(
fileobj=input_tar.extractfile(obj),
)
with istf.decrypt(obj) as decrypted:
if (plaintext_size := istf.securetar_header.plaintext_size) is None:
raise UnsupportedSecureTarVersion
decrypted_obj = copy.deepcopy(obj)
decrypted_obj.size = plaintext_size
output_tar.addfile(decrypted_obj, decrypted)

View File

@ -60,7 +60,7 @@ PyTurboJPEG==1.7.5
pyudev==0.24.1
PyYAML==6.0.2
requests==2.32.3
securetar==2025.1.2
securetar==2025.1.3
SQLAlchemy==2.0.36
standard-aifc==3.13.0;python_version>='3.13'
standard-telnetlib==3.13.0;python_version>='3.13'

View File

@ -66,7 +66,7 @@ dependencies = [
"python-slugify==8.0.4",
"PyYAML==6.0.2",
"requests==2.32.3",
"securetar==2025.1.2",
"securetar==2025.1.3",
"SQLAlchemy==2.0.36",
"standard-aifc==3.13.0;python_version>='3.13'",
"standard-telnetlib==3.13.0;python_version>='3.13'",

2
requirements.txt generated
View File

@ -38,7 +38,7 @@ psutil-home-assistant==0.0.1
python-slugify==8.0.4
PyYAML==6.0.2
requests==2.32.3
securetar==2025.1.2
securetar==2025.1.3
SQLAlchemy==2.0.36
standard-aifc==3.13.0;python_version>='3.13'
standard-telnetlib==3.13.0;python_version>='3.13'

2
requirements_all.txt generated
View File

@ -2665,7 +2665,7 @@ screenlogicpy==0.10.0
scsgate==0.1.0
# homeassistant.components.backup
securetar==2025.1.2
securetar==2025.1.3
# homeassistant.components.sendgrid
sendgrid==6.8.2

View File

@ -2147,7 +2147,7 @@ sanix==1.0.6
screenlogicpy==0.10.0
# homeassistant.components.backup
securetar==2025.1.2
securetar==2025.1.3
# homeassistant.components.emulated_kasa
# homeassistant.components.sense

View File

@ -186,7 +186,7 @@
'type': 'result',
})
# ---
# name: test_can_decrypt_on_download[backup.local-ed1608a9-hunter2]
# name: test_can_decrypt_on_download[backup.local-c0cb53bd-hunter2]
dict({
'id': 1,
'result': None,
@ -194,7 +194,7 @@
'type': 'result',
})
# ---
# name: test_can_decrypt_on_download[backup.local-ed1608a9-wrong_password]
# name: test_can_decrypt_on_download[backup.local-c0cb53bd-wrong_password]
dict({
'error': dict({
'code': 'password_incorrect',
@ -216,7 +216,7 @@
'type': 'result',
})
# ---
# name: test_can_decrypt_on_download[no_such_agent-ed1608a9-hunter2]
# name: test_can_decrypt_on_download[no_such_agent-c0cb53bd-hunter2]
dict({
'error': dict({
'code': 'home_assistant_error',

View File

@ -106,14 +106,14 @@ async def test_downloading_remote_encrypted_backup(
hass_client: ClientSessionGenerator,
) -> None:
"""Test downloading a local backup file."""
backup_path = get_fixture_path("test_backups/ed1608a9.tar", DOMAIN)
backup_path = get_fixture_path("test_backups/c0cb53bd.tar", DOMAIN)
await setup_backup_integration(hass)
hass.data[DATA_MANAGER].backup_agents["domain.test"] = BackupAgentTest(
"test",
[
AgentBackup(
addons=[AddonInfo(name="Test", slug="test", version="1.0.0")],
backup_id="ed1608a9",
backup_id="c0cb53bd",
database_included=True,
date="1970-01-01T00:00:00Z",
extra_metadata={},
@ -141,7 +141,7 @@ async def _test_downloading_encrypted_backup(
"""Test downloading an encrypted backup file."""
# Try downloading without supplying a password
client = await hass_client()
resp = await client.get(f"/api/backup/download/ed1608a9?agent_id={agent_id}")
resp = await client.get(f"/api/backup/download/c0cb53bd?agent_id={agent_id}")
assert resp.status == 200
backup = await resp.read()
# We expect a valid outer tar file, but the inner tar file is encrypted and
@ -158,7 +158,7 @@ async def _test_downloading_encrypted_backup(
# Download with the wrong password
resp = await client.get(
f"/api/backup/download/ed1608a9?agent_id={agent_id}&password=wrong"
f"/api/backup/download/c0cb53bd?agent_id={agent_id}&password=wrong"
)
assert resp.status == 200
backup = await resp.read()
@ -171,7 +171,7 @@ async def _test_downloading_encrypted_backup(
# Finally download with the correct password
resp = await client.get(
f"/api/backup/download/ed1608a9?agent_id={agent_id}&password=hunter2"
f"/api/backup/download/c0cb53bd?agent_id={agent_id}&password=hunter2"
)
assert resp.status == 200
backup = await resp.read()

View File

@ -2560,13 +2560,13 @@ async def test_subscribe_event(
("agent_id", "backup_id", "password"),
[
# Invalid agent or backup
("no_such_agent", "ed1608a9", "hunter2"),
("no_such_agent", "c0cb53bd", "hunter2"),
("backup.local", "no_such_backup", "hunter2"),
# Legacy backup, which can't be streamed
("backup.local", "2bcb3113", "hunter2"),
# New backup, which can be streamed, try with correct and wrong password
("backup.local", "ed1608a9", "hunter2"),
("backup.local", "ed1608a9", "wrong_password"),
("backup.local", "c0cb53bd", "hunter2"),
("backup.local", "c0cb53bd", "wrong_password"),
],
)
@pytest.mark.usefixtures("mock_backups")