Merge pull request #73 from christianlouis/copilot/implement-database-backed-key-storage

Fix CodeQL clear-text logging alerts and improve startup branch coverage
This commit is contained in:
Christian Krakau-Louis
2026-03-30 01:52:12 +02:00
committed by GitHub
6 changed files with 119 additions and 16 deletions
+32
View File
@@ -138,3 +138,35 @@ class TestEnsureSqliteDir:
"""Default DATABASE_URL places the SQLite file inside a data/ subdirectory."""
settings = Settings()
assert settings.DATABASE_URL.endswith("data/dmarq.db")
class TestAdminApiKeySetting:
"""Tests for the ADMIN_API_KEY settings field."""
def test_admin_api_key_defaults_to_none(self):
"""ADMIN_API_KEY is None when not set."""
settings = Settings()
assert settings.ADMIN_API_KEY is None
def test_admin_api_key_reads_from_env(self, monkeypatch):
"""ADMIN_API_KEY is read from the environment variable."""
monkeypatch.setenv("ADMIN_API_KEY", "mytestapikey1234")
settings = Settings()
assert settings.ADMIN_API_KEY == "mytestapikey1234"
def test_admin_api_key_warns_when_short(self, monkeypatch, caplog):
"""A warning is logged when ADMIN_API_KEY is shorter than 32 characters."""
import logging
monkeypatch.setenv("ADMIN_API_KEY", "short")
with caplog.at_level(logging.WARNING, logger="app.core.config"):
settings = Settings()
assert settings.ADMIN_API_KEY == "short"
assert any("too short" in record.message for record in caplog.records)
def test_admin_api_key_accepts_long_key(self, monkeypatch):
"""A 64-char hex key (openssl rand -hex 32 output) is accepted without warnings."""
long_key = "a" * 64
monkeypatch.setenv("ADMIN_API_KEY", long_key)
settings = Settings()
assert settings.ADMIN_API_KEY == long_key
+41
View File
@@ -5,9 +5,11 @@ Covers API key management, domain validation, file upload limits, and XML parsin
"""
import pytest
from fastapi.testclient import TestClient
import app.services.dmarc_parser as parser_module
from app.core.security import add_api_key, generate_api_key, verify_api_key
from app.main import create_app
from app.services.dmarc_parser import DMARCParser
from app.utils.domain_validator import validate_domain, validate_domain_config
@@ -151,3 +153,42 @@ class TestXMLParsingSecurity:
assert "root:" not in org_name and "/bin" not in org_name
except Exception: # pylint: disable=broad-exception-caught
pass # Expected defusedxml blocks DTD processing
class TestAdminApiKeyStartup:
"""Test admin API key loading during the application startup event."""
def test_startup_uses_env_api_key(self, monkeypatch):
"""When ADMIN_API_KEY is configured, startup should register it directly."""
import app.core.security as sec_module
import app.main as main_module
test_key = "a" * 64
monkeypatch.setattr(main_module.settings, "ADMIN_API_KEY", test_key)
saved_keys = set(sec_module._api_keys)
sec_module._api_keys.clear()
try:
application = create_app()
with TestClient(application):
assert sec_module.verify_api_key(test_key)
finally:
sec_module._api_keys.clear()
sec_module._api_keys.update(saved_keys)
def test_startup_generates_key_when_no_env(self, monkeypatch):
"""When ADMIN_API_KEY is not set, startup should generate a random key."""
import app.core.security as sec_module
import app.main as main_module
monkeypatch.setattr(main_module.settings, "ADMIN_API_KEY", None)
saved_keys = set(sec_module._api_keys)
sec_module._api_keys.clear()
try:
application = create_app()
with TestClient(application):
assert len(sec_module._api_keys) == 1
finally:
sec_module._api_keys.clear()
sec_module._api_keys.update(saved_keys)