Skip to main content
Glama
test_api_key_generation.py5.08 kB
"""Unit tests for API key generation script (User Story 3). Tests the CLI script for generating test API keys for local development. Following TDD: These tests should FAIL until implementation is complete. """ import hashlib import re from unittest.mock import MagicMock import pytest def test_api_key_format() -> None: """Test that generated API keys follow the correct format. Format: mcp_{32+ characters of base64url-safe string} """ # Simulate key generation import secrets token = secrets.token_urlsafe(32) api_key = f"mcp_{token}" # Verify format assert api_key.startswith("mcp_"), "API key must start with 'mcp_' prefix" assert len(api_key) > 36, f"API key too short: {len(api_key)} chars (expected >36)" # Verify it contains only URL-safe characters pattern = r"^mcp_[A-Za-z0-9_-]+$" assert re.match(pattern, api_key), f"API key contains invalid characters: {api_key}" def test_sha256_hash_computation() -> None: """Test that SHA-256 hash is computed correctly. The hash is what gets stored in the database, not the plain key. """ # Example API key api_key = "mcp_test_key_12345_abcdefghijklmnop" # Compute SHA-256 hash key_hash = hashlib.sha256(api_key.encode()).hexdigest() # Verify hash properties assert len(key_hash) == 64, f"SHA-256 hash should be 64 hex chars, got {len(key_hash)}" assert key_hash.isalnum(), "Hash should only contain alphanumeric characters" assert key_hash.islower(), "Hash should be lowercase hexadecimal" # Verify it's deterministic key_hash2 = hashlib.sha256(api_key.encode()).hexdigest() assert key_hash == key_hash2, "Hash should be deterministic" def test_generate_key_cli() -> None: """Test Click CLI invocation for key generation. Verifies the CLI interface works with required options. """ from click.testing import CliRunner # This test will fail until the script is implemented # For now, we're just testing the test infrastructure try: from src.scripts.generate_api_key import generate_key runner = CliRunner() # Test with missing required options (should fail) result = runner.invoke(generate_key, []) assert result.exit_code != 0, "Should fail without required options" # Test with --help result = runner.invoke(generate_key, ["--help"]) assert result.exit_code == 0, "Should show help successfully" assert "Usage:" in result.output or "usage:" in result.output.lower() except ImportError: # Script doesn't exist yet - expected in TDD pytest.skip("generate_api_key script not yet implemented") def test_database_insertion_mocked() -> None: """Test Supabase database insertion logic with mocked client. Verifies the script correctly inserts API key data into Supabase. """ # Mock Supabase client mock_supabase = MagicMock() mock_table = MagicMock() mock_insert = MagicMock() mock_execute = MagicMock() # Set up mock chain mock_supabase.table.return_value = mock_table mock_table.insert.return_value = mock_insert mock_insert.execute.return_value = MagicMock( data=[{"id": "test-key-id", "key_hash": "test-hash"}] ) # Simulate insertion api_key = "mcp_test_key_12345" key_hash = hashlib.sha256(api_key.encode()).hexdigest() # Call mocked Supabase result = ( mock_supabase.table("api_keys") .insert( { "organization_id": 123, "key_hash": key_hash, "created_by_user_id": "user-uuid", "is_active": True, } ) .execute() ) # Verify insertion was called mock_supabase.table.assert_called_once_with("api_keys") assert result.data is not None, "Insert should return data" def test_api_key_uniqueness() -> None: """Test that generated API keys are unique across invocations. Uses secrets module which provides cryptographic randomness. """ import secrets # Generate multiple keys keys = set() for _ in range(100): token = secrets.token_urlsafe(32) api_key = f"mcp_{token}" keys.add(api_key) # All keys should be unique assert len(keys) == 100, "Generated keys should be unique" def test_key_entropy() -> None: """Test that generated keys have sufficient entropy. 32 bytes (256 bits) exceeds NIST recommendations for API keys. """ import secrets # Generate a key token_bytes = secrets.token_bytes(32) # Verify byte length assert len(token_bytes) == 32, f"Token should be 32 bytes, got {len(token_bytes)}" # Verify it's not all zeros (extremely unlikely with secrets module) assert token_bytes != b"\x00" * 32, "Token should not be all zeros" # Convert to URL-safe base64 import base64 token_str = base64.urlsafe_b64encode(token_bytes).decode().rstrip("=") assert len(token_str) >= 43, f"Base64 token should be ~43 chars, got {len(token_str)}"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/darrentmorgan/hostaway-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server