62 lines
2.8 KiB
Python
62 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
from sqlmodel import Session, SQLModel, create_engine
|
|
|
|
from backend.app.db.models import Secret
|
|
from backend.app.services import repopulse_secret_import as importer
|
|
from backend.app.services.secret_store import get_secret
|
|
|
|
|
|
@pytest.fixture
|
|
def session(tmp_path, monkeypatch):
|
|
engine = create_engine(f"sqlite:///{tmp_path / 'secrets.db'}")
|
|
SQLModel.metadata.create_all(engine)
|
|
monkeypatch.setattr(importer, "secret_storage_status", lambda: {"productionReady": True})
|
|
with Session(engine) as value:
|
|
yield value
|
|
|
|
|
|
def test_import_is_write_only_and_idempotent(session):
|
|
assert importer.import_repopulse_gitea_token(session, "test-token") == "imported"
|
|
assert importer.import_repopulse_gitea_token(session, "test-token") == "already_present"
|
|
assert get_secret(session, importer.SECRET_REF, touch=False) == "test-token"
|
|
|
|
|
|
def test_import_rejects_replacement_and_malformed_input(session):
|
|
importer.import_repopulse_gitea_token(session, "first")
|
|
with pytest.raises(ValueError, match="different value"):
|
|
importer.import_repopulse_gitea_token(session, "second")
|
|
for value in ("", " leading", "trailing ", "line\nbreak", "x" * 8193):
|
|
with pytest.raises(ValueError):
|
|
importer.import_repopulse_gitea_token(session, value)
|
|
assert get_secret(session, importer.SECRET_REF, touch=False) == "first"
|
|
|
|
|
|
def test_import_requires_production_secret_storage(session, monkeypatch):
|
|
monkeypatch.setattr(importer, "secret_storage_status", lambda: {"productionReady": False})
|
|
with pytest.raises(ValueError, match="not ready"):
|
|
importer.import_repopulse_gitea_token(session, "test-token")
|
|
assert get_secret(session, importer.SECRET_REF, touch=False) is None
|
|
|
|
|
|
def test_import_does_not_overwrite_an_undecryptable_secret(session):
|
|
importer.import_repopulse_gitea_token(session, "original")
|
|
row = session.get(Secret, importer.SECRET_REF)
|
|
assert row is not None
|
|
row.encrypted_value = "corrupted-ciphertext"
|
|
session.add(row)
|
|
session.commit()
|
|
with pytest.raises(ValueError, match="cannot be decrypted"):
|
|
importer.import_repopulse_gitea_token(session, "replacement")
|
|
assert session.get(Secret, importer.SECRET_REF).encrypted_value == "corrupted-ciphertext"
|
|
|
|
|
|
def test_controller_bootstrap_import_uses_fixed_distinct_reference(session):
|
|
assert importer.import_controller_bootstrap(session, "bootstrap-test-token") == "imported"
|
|
assert importer.import_controller_bootstrap(session, "bootstrap-test-token") == "already_present"
|
|
assert get_secret(session, importer.BOOTSTRAP_SECRET_REF, touch=False) == "bootstrap-test-token"
|
|
assert get_secret(session, importer.SECRET_REF, touch=False) is None
|
|
with pytest.raises(ValueError, match="different value"):
|
|
importer.import_controller_bootstrap(session, "other-token")
|