50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
"""Tests for the Fernet API-key encryption helper."""
|
|
|
|
import pytest
|
|
|
|
from app import crypto
|
|
from app.config import settings
|
|
|
|
|
|
@pytest.fixture
|
|
def isolated_secret(tmp_path, monkeypatch):
|
|
"""Point the secret at a temp dir so tests don't touch the real one."""
|
|
monkeypatch.setattr(settings, "data_dir", tmp_path)
|
|
crypto.reset_cache()
|
|
yield tmp_path
|
|
crypto.reset_cache()
|
|
|
|
|
|
class TestCrypto:
|
|
def test_round_trip(self, isolated_secret):
|
|
ciphertext = crypto.encrypt("sk-super-secret")
|
|
assert ciphertext # non-empty
|
|
assert ciphertext != "sk-super-secret" # actually encrypted
|
|
assert crypto.decrypt(ciphertext) == "sk-super-secret"
|
|
|
|
def test_secret_file_created_with_600_perms(self, isolated_secret):
|
|
crypto.encrypt("x")
|
|
secret = isolated_secret / ".secret_key"
|
|
assert secret.exists()
|
|
# Owner read/write only (mode bits 0o600). Skip the check on platforms
|
|
# that don't support chmod semantics.
|
|
mode = secret.stat().st_mode & 0o777
|
|
assert mode == 0o600
|
|
|
|
def test_empty_inputs(self, isolated_secret):
|
|
assert crypto.encrypt("") == ""
|
|
assert crypto.decrypt("") == ""
|
|
|
|
def test_undecryptable_returns_empty(self, isolated_secret):
|
|
# Garbage / wrong-secret ciphertext must not raise — treated as empty.
|
|
assert crypto.decrypt("not-a-valid-token") == ""
|
|
|
|
def test_rotated_secret_yields_empty(self, isolated_secret, monkeypatch, tmp_path):
|
|
ciphertext = crypto.encrypt("sk-secret")
|
|
# Simulate a lost/rotated secret: new empty data dir.
|
|
new_dir = tmp_path / "rotated"
|
|
new_dir.mkdir()
|
|
monkeypatch.setattr(settings, "data_dir", new_dir)
|
|
crypto.reset_cache()
|
|
assert crypto.decrypt(ciphertext) == ""
|