enroll/tests/test_sopsutil.py
Miguel Jacq bf735c8328
Some checks failed
CI / test (push) Failing after 1s
Lint / test (push) Failing after 1s
More coverage
2026-05-31 17:15:22 +10:00

234 lines
6.4 KiB
Python

from __future__ import annotations
import pytest
from pathlib import Path
from enroll.sopsutil import SopsError, _pgp_arg, find_sops_cmd, require_sops_cmd
def test_find_sops_cmd():
result = find_sops_cmd()
if result is None:
pytest.skip("sops not installed")
assert result.endswith("sops")
def test_require_sops_cmd():
exe = require_sops_cmd()
assert exe is not None
assert "sops" in exe
def test_require_sops_cmd_raises_when_not_found(monkeypatch):
import enroll.sopsutil as s
def fake_find():
return None
monkeypatch.setattr(s, "find_sops_cmd", fake_find)
with pytest.raises(SopsError) as exc_info:
require_sops_cmd()
assert "sops" in str(exc_info.value).lower()
assert "not found" in str(exc_info.value).lower()
def test_pgp_arg_with_empty_fingerprints():
with pytest.raises(SopsError) as exc_info:
_pgp_arg([])
assert "No GPG fingerprints" in str(exc_info.value)
def test_pgp_arg_with_whitespace_fingerprints():
result = _pgp_arg([" ", "ABC123", " DEF456 "])
assert result == "ABC123,DEF456"
def test_pgp_arg_with_single_fingerprint():
result = _pgp_arg(["ABC123DEF456"])
assert result == "ABC123DEF456"
def test_pgp_arg_with_multiple_fingerprints():
result = _pgp_arg(["ABC123", "DEF456", "GHI789"])
assert result == "ABC123,DEF456,GHI789"
def test_encrypt_file_binary_success(monkeypatch, tmp_path: Path):
"""Test successful encryption path."""
# Create source file
src = tmp_path / "secret.txt"
src.write_text("secret data", encoding="utf-8")
dst = tmp_path / "encrypted.sops"
# Mock subprocess.run to succeed
class Result:
returncode = 0
stdout = b"encrypted data"
stderr = b""
def fake_run(cmd, capture_output, check):
return Result()
# Mock require_sops_cmd to return a fake path
def fake_require():
return "/fake/sops"
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
from enroll.sopsutil import encrypt_file_binary
encrypt_file_binary(src, dst, pgp_fingerprints=["ABC123"])
assert dst.exists()
assert dst.read_bytes() == b"encrypted data"
def test_encrypt_file_binary_fails(monkeypatch, tmp_path: Path):
"""Test encryption failure path."""
src = tmp_path / "secret.txt"
src.write_text("secret data", encoding="utf-8")
dst = tmp_path / "encrypted.sops"
class Result:
returncode = 1
stdout = b""
stderr = b"sops: gpg error"
def fake_run(cmd, capture_output, check):
return Result()
def fake_require():
return "/fake/sops"
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
from enroll.sopsutil import encrypt_file_binary, SopsError
with pytest.raises(SopsError) as exc_info:
encrypt_file_binary(src, dst, pgp_fingerprints=["ABC123"])
assert "encryption failed" in str(exc_info.value).lower()
def test_encrypt_file_binary_chmod_fails(monkeypatch, tmp_path: Path):
"""Test when chmod fails but file is still written."""
src = tmp_path / "secret.txt"
src.write_text("secret data", encoding="utf-8")
dst = tmp_path / "encrypted.sops"
class Result:
returncode = 0
stdout = b"encrypted data"
stderr = b""
def fake_run(cmd, capture_output, check):
return Result()
def fake_require():
return "/fake/sops"
def fake_chmod(path, mode):
raise OSError("Permission denied")
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
monkeypatch.setattr("enroll.sopsutil.os.chmod", fake_chmod)
from enroll.sopsutil import encrypt_file_binary
# Should not raise even though chmod fails
encrypt_file_binary(src, dst, pgp_fingerprints=["ABC123"])
assert dst.exists()
def test_decrypt_file_binary_to_success(monkeypatch, tmp_path: Path):
"""Test successful decryption path."""
src = tmp_path / "encrypted.sops"
src.write_bytes(b"encrypted data")
dst = tmp_path / "decrypted.txt"
class Result:
returncode = 0
stdout = b"decrypted data"
stderr = b""
def fake_run(cmd, capture_output, check):
return Result()
def fake_require():
return "/fake/sops"
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
from enroll.sopsutil import decrypt_file_binary_to
decrypt_file_binary_to(src, dst)
assert dst.exists()
assert dst.read_bytes() == b"decrypted data"
def test_decrypt_file_binary_to_fails(monkeypatch, tmp_path: Path):
"""Test decryption failure path."""
src = tmp_path / "encrypted.sops"
src.write_bytes(b"encrypted data")
dst = tmp_path / "decrypted.txt"
class Result:
returncode = 1
stdout = b""
stderr = b"sops: decryption failed"
def fake_run(cmd, capture_output, check):
return Result()
def fake_require():
return "/fake/sops"
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
from enroll.sopsutil import decrypt_file_binary_to, SopsError
with pytest.raises(SopsError) as exc_info:
decrypt_file_binary_to(src, dst)
assert "decryption failed" in str(exc_info.value).lower()
def test_decrypt_file_binary_to_chmod_fails(monkeypatch, tmp_path: Path):
"""Test when chmod fails during decryption but file is still written."""
src = tmp_path / "encrypted.sops"
src.write_bytes(b"encrypted data")
dst = tmp_path / "decrypted.txt"
class Result:
returncode = 0
stdout = b"decrypted data"
stderr = b""
def fake_run(cmd, capture_output, check):
return Result()
def fake_require():
return "/fake/sops"
def fake_chmod(path, mode):
raise OSError("Permission denied")
monkeypatch.setattr("enroll.sopsutil.subprocess.run", fake_run)
monkeypatch.setattr("enroll.sopsutil.require_sops_cmd", fake_require)
monkeypatch.setattr("enroll.sopsutil.os.chmod", fake_chmod)
from enroll.sopsutil import decrypt_file_binary_to
# Should not raise even though chmod fails
decrypt_file_binary_to(src, dst)
assert dst.exists()