This commit is contained in:
2026-02-11 18:16:00 +01:00
parent dd7bbd1f9a
commit d82fe87113
25 changed files with 120 additions and 4230 deletions

View File

@@ -5,8 +5,8 @@ import pytest
from aegis_gitea_mcp.auth import (
APIKeyValidator,
generate_api_key,
hash_api_key,
get_validator,
hash_api_key,
reset_validator,
)
from aegis_gitea_mcp.config import reset_settings
@@ -40,7 +40,7 @@ def validator(mock_env_with_key):
def test_generate_api_key():
"""Test API key generation."""
key = generate_api_key(length=64)
assert len(key) == 64
assert all(c in "0123456789abcdef" for c in key)
@@ -48,7 +48,7 @@ def test_generate_api_key():
def test_generate_api_key_custom_length():
"""Test API key generation with custom length."""
key = generate_api_key(length=128)
assert len(key) == 128
@@ -56,7 +56,7 @@ def test_hash_api_key():
"""Test API key hashing."""
key = "test-key-12345"
hashed = hash_api_key(key)
assert len(hashed) == 64 # SHA256 produces 64-char hex string
assert hashed == hash_api_key(key) # Deterministic
@@ -65,7 +65,7 @@ def test_validator_singleton():
"""Test that get_validator returns same instance."""
validator1 = get_validator()
validator2 = get_validator()
assert validator1 is validator2
@@ -73,10 +73,10 @@ def test_constant_time_compare(validator):
"""Test constant-time string comparison."""
# Same strings
assert validator._constant_time_compare("test", "test")
# Different strings
assert not validator._constant_time_compare("test", "fail")
# Different lengths
assert not validator._constant_time_compare("test", "testing")
@@ -86,19 +86,19 @@ def test_extract_bearer_token(validator):
# Valid bearer token
token = validator.extract_bearer_token("Bearer abc123")
assert token == "abc123"
# No header
token = validator.extract_bearer_token(None)
assert token is None
# Wrong format
token = validator.extract_bearer_token("abc123")
assert token is None
# Wrong scheme
token = validator.extract_bearer_token("Basic abc123")
assert token is None
# Too many parts
token = validator.extract_bearer_token("Bearer abc 123")
assert token is None
@@ -107,7 +107,7 @@ def test_extract_bearer_token(validator):
def test_validate_api_key_missing(validator):
"""Test validation with missing API key."""
is_valid, error = validator.validate_api_key(None, "127.0.0.1", "test-agent")
assert not is_valid
assert "Authorization header missing" in error
@@ -115,7 +115,7 @@ def test_validate_api_key_missing(validator):
def test_validate_api_key_too_short(validator):
"""Test validation with too-short API key."""
is_valid, error = validator.validate_api_key("short", "127.0.0.1", "test-agent")
assert not is_valid
assert "Invalid API key format" in error
@@ -123,7 +123,7 @@ def test_validate_api_key_too_short(validator):
def test_validate_api_key_invalid(validator, mock_env_with_key):
"""Test validation with invalid API key."""
is_valid, error = validator.validate_api_key("b" * 64, "127.0.0.1", "test-agent")
assert not is_valid
assert "Invalid API key" in error
@@ -131,7 +131,7 @@ def test_validate_api_key_invalid(validator, mock_env_with_key):
def test_validate_api_key_valid(validator, mock_env_with_key):
"""Test validation with valid API key."""
is_valid, error = validator.validate_api_key("a" * 64, "127.0.0.1", "test-agent")
assert is_valid
assert error is None
@@ -139,12 +139,12 @@ def test_validate_api_key_valid(validator, mock_env_with_key):
def test_rate_limiting(validator):
"""Test rate limiting after multiple failures."""
client_ip = "192.168.1.1"
# First 5 attempts should be allowed
for i in range(5):
for _ in range(5):
is_valid, error = validator.validate_api_key("b" * 64, client_ip, "test-agent")
assert not is_valid
# 6th attempt should be rate limited
is_valid, error = validator.validate_api_key("b" * 64, client_ip, "test-agent")
assert not is_valid
@@ -155,15 +155,15 @@ def test_rate_limiting_per_ip(validator):
"""Test that rate limiting is per IP address."""
ip1 = "192.168.1.1"
ip2 = "192.168.1.2"
# Fail 5 times from IP1
for i in range(5):
for _ in range(5):
validator.validate_api_key("b" * 64, ip1, "test-agent")
# IP1 should be rate limited
is_valid, error = validator.validate_api_key("b" * 64, ip1, "test-agent")
assert "Too many failed" in error
# IP2 should still work
is_valid, error = validator.validate_api_key("b" * 64, ip2, "test-agent")
assert "Invalid API key" in error # Wrong key, but not rate limited
@@ -175,9 +175,9 @@ def test_auth_disabled(monkeypatch):
monkeypatch.setenv("GITEA_TOKEN", "test-token-12345")
monkeypatch.setenv("AUTH_ENABLED", "false")
monkeypatch.setenv("MCP_API_KEYS", "") # No keys needed when disabled
validator = APIKeyValidator()
# Should allow access without key
is_valid, error = validator.validate_api_key(None, "127.0.0.1", "test-agent")
assert is_valid
@@ -190,19 +190,19 @@ def test_multiple_keys(monkeypatch):
monkeypatch.setenv("GITEA_TOKEN", "test-token-12345")
monkeypatch.setenv("AUTH_ENABLED", "true")
monkeypatch.setenv("MCP_API_KEYS", f"{'a' * 64},{'b' * 64},{'c' * 64}")
validator = APIKeyValidator()
# All three keys should work
is_valid, _ = validator.validate_api_key("a" * 64, "127.0.0.1", "test-agent")
assert is_valid
is_valid, _ = validator.validate_api_key("b" * 64, "127.0.0.1", "test-agent")
assert is_valid
is_valid, _ = validator.validate_api_key("c" * 64, "127.0.0.1", "test-agent")
assert is_valid
# Invalid key should fail
is_valid, _ = validator.validate_api_key("d" * 64, "127.0.0.1", "test-agent")
assert not is_valid