import os import stat from pathlib import Path import pytest from backend.app.services.credential_crypto import ( CredentialCrypto, InvalidCredentialBlob, ) pytestmark = pytest.mark.integration def test_load_or_create_writes_key_with_mode_0600(tmp_path): key_path = tmp_path / "secrets" / "credential_key.b64" CredentialCrypto(key_path) assert key_path.exists() mode = stat.S_IMODE(os.stat(key_path).st_mode) assert mode == 0o600 # parent dir is 0o700 parent_mode = stat.S_IMODE(os.stat(key_path.parent).st_mode) assert parent_mode == 0o700 def test_load_existing_key_is_idempotent(tmp_path): key_path = tmp_path / "credential_key.b64" crypto1 = CredentialCrypto(key_path) contents_after_first = key_path.read_bytes() crypto2 = CredentialCrypto(key_path) contents_after_second = key_path.read_bytes() assert contents_after_first == contents_after_second # And both crypto instances decrypt each other's ciphertext ct = crypto1.encrypt("hello") assert crypto2.decrypt(ct) == "hello" def test_encrypt_decrypt_round_trip(tmp_path): crypto = CredentialCrypto(tmp_path / "k") plaintext = "domain.com\tTRUE\t/\tTRUE\t1700000000\tname\tvalue" ct = crypto.encrypt(plaintext) assert isinstance(ct, bytes) assert ct != plaintext.encode() assert crypto.decrypt(ct) == plaintext def test_decrypt_with_wrong_key_raises(tmp_path): crypto_a = CredentialCrypto(tmp_path / "a") crypto_b = CredentialCrypto(tmp_path / "b") ct = crypto_a.encrypt("secret") with pytest.raises(InvalidCredentialBlob): crypto_b.decrypt(ct)