Skip to content

Commit 77aeb8a

Browse files
PabloAlexis611neersighted
authored andcommitted
Improve error handling on FIPS systems (python-poetry#9152)
(cherry picked from commit 52b113d)
1 parent 392adbf commit 77aeb8a

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

src/poetry/repositories/http_repository.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import hashlib
55

66
from contextlib import contextmanager
7+
from contextlib import suppress
78
from pathlib import Path
89
from typing import TYPE_CHECKING
910
from typing import Any
@@ -374,7 +375,11 @@ def calculate_sha256(self, link: Link) -> str | None:
374375
hash_name = get_highest_priority_hash_type(
375376
set(link.hashes.keys()), link.filename
376377
)
377-
known_hash = getattr(hashlib, hash_name)() if hash_name else None
378+
known_hash = None
379+
with suppress(ValueError, AttributeError):
380+
# Handle ValueError here as well since under FIPS environments
381+
# this is what is raised (e.g., for MD5)
382+
known_hash = getattr(hashlib, hash_name)() if hash_name else None
378383
required_hash = hashlib.sha256()
379384

380385
chunksize = 4096

tests/repositories/test_http_repository.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,71 @@ def test_get_info_from_wheel_state_sequence(mocker: MockerFixture) -> None:
153153
repo._get_info_from_wheel(link)
154154
assert mock_metadata_from_wheel_url.call_count == 5
155155
assert mock_download.call_count == 4
156+
157+
158+
@pytest.mark.parametrize(
159+
"mock_hashes",
160+
[
161+
None,
162+
{"sha256": "e216b70f013c47b82a72540d34347632c5bfe59fd54f5fe5d51f6a68b19aaf84"},
163+
{"md5": "be7589b4902793e66d7d979bd8581591"},
164+
],
165+
)
166+
def test_calculate_sha256(
167+
mocker: MockerFixture, mock_hashes: dict[str, Any] | None
168+
) -> None:
169+
filename = "poetry_core-1.5.0-py3-none-any.whl"
170+
filepath = MockRepository.DIST_FIXTURES / filename
171+
mock_download = mocker.patch(
172+
"poetry.repositories.http_repository.download_file",
173+
side_effect=lambda _, dest, *args, **kwargs: shutil.copy(filepath, dest),
174+
)
175+
domain = "foo.com"
176+
link = Link(f"https://{domain}/{filename}", hashes=mock_hashes)
177+
repo = MockRepository()
178+
179+
calculated_hash = repo.calculate_sha256(link)
180+
181+
assert mock_download.call_count == 1
182+
assert (
183+
calculated_hash
184+
== "sha256:e216b70f013c47b82a72540d34347632c5bfe59fd54f5fe5d51f6a68b19aaf84"
185+
)
186+
187+
188+
def test_calculate_sha256_defaults_to_sha256_on_md5_errors(
189+
mocker: MockerFixture,
190+
) -> None:
191+
raised_value_error = False
192+
193+
def mock_hashlib_md5_error() -> None:
194+
nonlocal raised_value_error
195+
raised_value_error = True
196+
raise ValueError(
197+
"[digital envelope routines: EVP_DigestInit_ex] disabled for FIPS"
198+
)
199+
200+
filename = "poetry_core-1.5.0-py3-none-any.whl"
201+
filepath = MockRepository.DIST_FIXTURES / filename
202+
mock_download = mocker.patch(
203+
"poetry.repositories.http_repository.download_file",
204+
side_effect=lambda _, dest, *args, **kwargs: shutil.copy(filepath, dest),
205+
)
206+
mock_hashlib_md5 = mocker.patch("hashlib.md5", side_effect=mock_hashlib_md5_error)
207+
208+
domain = "foo.com"
209+
link = Link(
210+
f"https://{domain}/{filename}",
211+
hashes={"md5": "be7589b4902793e66d7d979bd8581591"},
212+
)
213+
repo = MockRepository()
214+
215+
calculated_hash = repo.calculate_sha256(link)
216+
217+
assert raised_value_error
218+
assert mock_download.call_count == 1
219+
assert mock_hashlib_md5.call_count == 1
220+
assert (
221+
calculated_hash
222+
== "sha256:e216b70f013c47b82a72540d34347632c5bfe59fd54f5fe5d51f6a68b19aaf84"
223+
)

0 commit comments

Comments
 (0)