mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-07 07:58:09 +00:00
* fix(proxy): probe scrypt instead of MD5 in the fips_mode OpenSSL check * test(proxy): fake a working scrypt so the fips_mode check tests pass on FIPS hosts
121 lines
4.8 KiB
Python
121 lines
4.8 KiB
Python
import _hashlib
|
|
from collections.abc import Mapping
|
|
from contextlib import nullcontext
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
from cryptography.exceptions import InternalError
|
|
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
|
from cryptography.hazmat.primitives import hashes
|
|
|
|
from litellm.proxy.common_utils.fips import (
|
|
FipsModeError,
|
|
cryptography_enforces_fips,
|
|
enforce_fips_mode,
|
|
openssl_enforces_fips,
|
|
)
|
|
|
|
|
|
def _fake_openssl(monkeypatch: pytest.MonkeyPatch, *, fips_flag: int, scrypt_refused: bool) -> None:
|
|
monkeypatch.setattr(_hashlib, "get_fips_mode", lambda: fips_flag)
|
|
if scrypt_refused:
|
|
monkeypatch.setattr(_hashlib, "scrypt", Mock(side_effect=ValueError("[digital envelope routines] unsupported")))
|
|
else:
|
|
monkeypatch.setattr(_hashlib, "scrypt", Mock(return_value=b"\0" * 16))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"fips_flag, scrypt_refused, enforces",
|
|
[(1, True, True), (0, True, False), (1, False, False)],
|
|
ids=["fips", "fips-flag-off", "scrypt-allowed"],
|
|
)
|
|
def test_openssl_enforces_fips_needs_the_fips_flag_and_a_refused_scrypt(
|
|
monkeypatch: pytest.MonkeyPatch, fips_flag: int, scrypt_refused: bool, enforces: bool
|
|
) -> None:
|
|
_fake_openssl(monkeypatch, fips_flag=fips_flag, scrypt_refused=scrypt_refused)
|
|
assert openssl_enforces_fips() is enforces
|
|
|
|
|
|
def test_openssl_enforces_fips_while_md5_is_still_served_for_non_security_use(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
_fake_openssl(monkeypatch, fips_flag=1, scrypt_refused=True)
|
|
monkeypatch.setattr(_hashlib, "new", Mock(return_value=Mock()))
|
|
assert openssl_enforces_fips() is True
|
|
|
|
|
|
def test_openssl_without_get_fips_mode_does_not_enforce_fips(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.delattr(_hashlib, "get_fips_mode")
|
|
assert openssl_enforces_fips() is False
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"fips_enabled, sha256_broken, enforces",
|
|
[(True, False, True), (False, False, False), (True, True, False)],
|
|
ids=["fips", "fips-flag-off", "sha256-broken"],
|
|
)
|
|
def test_cryptography_enforces_fips_needs_the_fips_flag_and_a_working_sha256(
|
|
monkeypatch: pytest.MonkeyPatch, fips_enabled: bool, sha256_broken: bool, enforces: bool
|
|
) -> None:
|
|
monkeypatch.setattr(rust_openssl, "is_fips_enabled", lambda: fips_enabled)
|
|
if sha256_broken:
|
|
monkeypatch.setattr(hashes, "Hash", Mock(side_effect=InternalError("Unknown OpenSSL error", [])))
|
|
assert cryptography_enforces_fips() is enforces
|
|
|
|
|
|
def test_cryptography_without_is_fips_enabled_does_not_enforce_fips(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.delattr(rust_openssl, "is_fips_enabled")
|
|
assert cryptography_enforces_fips() is False
|
|
|
|
|
|
def test_this_runners_python_openssl_does_not_enforce_fips() -> None:
|
|
if _hashlib.get_fips_mode() == 1:
|
|
pytest.skip("this runner's Python OpenSSL is in FIPS mode")
|
|
assert openssl_enforces_fips() is False
|
|
|
|
|
|
def test_this_runners_cryptography_openssl_does_not_enforce_fips() -> None:
|
|
if rust_openssl.is_fips_enabled():
|
|
pytest.skip("this runner's cryptography OpenSSL is in FIPS mode")
|
|
assert cryptography_enforces_fips() is False
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"general_settings, openssl_fips, cryptography_fips, refusal",
|
|
[
|
|
({}, False, False, None),
|
|
({"fips_mode": False}, False, False, None),
|
|
({"fips_mode": "false"}, False, False, None),
|
|
({"fips_mode": True}, True, True, None),
|
|
({"fips_mode": "true"}, True, True, None),
|
|
({"fips_mode": True}, False, True, "general_settings.fips_mode is on but OpenSSL does not enforce FIPS"),
|
|
({"fips_mode": " TRUE "}, False, True, "general_settings.fips_mode is on but OpenSSL does not enforce FIPS"),
|
|
({"fips_mode": True}, True, False, "cryptography library's OpenSSL has no working FIPS provider"),
|
|
({"fips_mode": "enforced"}, True, True, "general_settings.fips_mode='enforced' is not a boolean"),
|
|
({"fips_mode": 1}, True, True, "general_settings.fips_mode=1 is not a boolean"),
|
|
({"fips_mode": None}, True, True, "general_settings.fips_mode has no value"),
|
|
],
|
|
ids=[
|
|
"unset",
|
|
"false",
|
|
"false-from-a-string",
|
|
"fips",
|
|
"fips-from-a-string",
|
|
"openssl-not-fips",
|
|
"openssl-not-fips-from-a-padded-string",
|
|
"cryptography-not-fips",
|
|
"not-a-boolean",
|
|
"a-number",
|
|
"no-value",
|
|
],
|
|
)
|
|
def test_enforce_fips_mode(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
general_settings: Mapping[str, object],
|
|
openssl_fips: bool,
|
|
cryptography_fips: bool,
|
|
refusal: str | None,
|
|
) -> None:
|
|
_fake_openssl(monkeypatch, fips_flag=int(openssl_fips), scrypt_refused=openssl_fips)
|
|
monkeypatch.setattr(rust_openssl, "is_fips_enabled", lambda: cryptography_fips)
|
|
|
|
with pytest.raises(FipsModeError, match=refusal) if refusal else nullcontext():
|
|
enforce_fips_mode(general_settings)
|