- executors: 13 tests, 100% coverage (init/shutdown/run_blocking/run_cpu_blocking) - fileio_utils: 33 tests, 45% coverage (sanitize_filename, get_filename_from_headers, calculate_crc32, create_temp_file, remove_empty_directories, create_dashboard_export, consolidate_archive_folders) - client_registry: 14 tests, 92% coverage (get_client, get_superset_client, get_semaphore, get_auth_lock, shutdown) - cot_logger: 24 tests, 100% coverage (seed/set/get trace_id, push/pop span, structured log with markers, MarkerLogger proxy) - encryption: 12 tests, 100% coverage (key validation, encrypt/decrypt cycle) - rate_limiter: 9 tests, 100% coverage (ban logic, window pruning, per-IP isolation) - auth/logger: 10 tests, 100% coverage (_mask_details, log_security_event)
89 lines
3.4 KiB
Python
89 lines
3.4 KiB
Python
# #region Test.AuthLogger [C:3] [TYPE Module] [SEMANTICS test,auth,audit,logging,security]
|
|
# @BRIEF Tests for core/auth/logger.py — _mask_details, log_security_event.
|
|
# @RELATION BINDS_TO -> [AuthLoggerModule]
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
|
|
|
from unittest.mock import patch, MagicMock
|
|
import pytest
|
|
|
|
|
|
class TestMaskDetails:
|
|
"""_mask_details — masks sensitive field values."""
|
|
|
|
def test_none_returns_none(self):
|
|
from src.core.auth.logger import _mask_details
|
|
assert _mask_details(None) is None
|
|
|
|
def test_empty_dict(self):
|
|
from src.core.auth.logger import _mask_details
|
|
assert _mask_details({}) == {}
|
|
|
|
def test_password_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"password": "supersecret", "username": "admin"})
|
|
assert result["password"] == "***"
|
|
assert result["username"] == "admin"
|
|
|
|
def test_token_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"token": "abc123", "action": "login"})
|
|
assert result["token"] == "***"
|
|
|
|
def test_api_key_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"api_key": "sk-12345"})
|
|
assert result["api_key"] == "***"
|
|
|
|
def test_secret_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"secret": "my-secret"})
|
|
assert result["secret"] == "***"
|
|
|
|
def test_authorization_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"authorization": "Bearer xxx"})
|
|
assert result["authorization"] == "***"
|
|
|
|
def test_nested_dict_masked(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"user": {"password": "secret", "name": "John"}})
|
|
assert result["user"]["password"] == "***"
|
|
assert result["user"]["name"] == "John"
|
|
|
|
def test_case_insensitive_masking(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"Password": "secret", "TOKEN": "abc"})
|
|
assert result["Password"] == "***"
|
|
assert result["TOKEN"] == "***"
|
|
|
|
def test_non_sensitive_keys_preserved(self):
|
|
from src.core.auth.logger import _mask_details
|
|
result = _mask_details({"email": "user@example.com", "role": "admin"})
|
|
assert result["email"] == "user@example.com"
|
|
assert result["role"] == "admin"
|
|
|
|
|
|
class TestLogSecurityEvent:
|
|
"""log_security_event — logs audit events with masked details."""
|
|
|
|
def test_logs_without_details(self):
|
|
from src.core.auth.logger import log_security_event
|
|
with patch("src.core.auth.logger.logger.info") as mock_info:
|
|
log_security_event("LOGIN_SUCCESS", "admin")
|
|
assert mock_info.call_count >= 1
|
|
|
|
def test_logs_with_masked_details(self):
|
|
from src.core.auth.logger import log_security_event
|
|
with patch("src.core.auth.logger.logger.info") as mock_info:
|
|
log_security_event("LOGIN_FAILED", "admin", {"password": "wrong", "ip": "10.0.0.1"})
|
|
assert mock_info.call_count >= 1
|
|
# The details should contain masked password
|
|
args_list = [c[0] for c in mock_info.call_args_list]
|
|
details_call = [a for a in args_list if "Details" in a[0]]
|
|
assert len(details_call) >= 1
|
|
# #endregion Test.AuthLogger
|