FastAPI Guard

repository·master·Indexed 21 days ago

https://github.com/rennf93/fastapi-guard

Production-ready security middleware for FastAPI version 7.4.0 providing IP filtering, rate limiting, signature-based attack detection, and over 20 per-route security decorators. It features a Behavior Manager for suspicious pattern detection and optional integration with a centralized cloud dashboard via guard-agent for real-time monitoring and dynamic rule updates.

Tokens
68.5K
Snippets
219
Records
279
Agent score
73%

What's inside fastapi-guard

  1. Overview of Detection Engine Components

    master

    The FastAPI Guard Detection Engine is composed of four primary components that work together to identify security threats. These components are initialized based on your SecurityConfig:

    1. ContentPreprocessor: Truncates content to manage memory while preserving potential attack patterns.
    2. PatternCompiler: Executes regex pattern matching with built-in timeout protection to prevent Regular Expression Denial of Service (ReDoS).
    3. SemanticAnalyzer: Uses heuristics to detect obfuscated attacks (like SQLi or XSS) that might bypass standard regex.
    4. PerformanceMonitor: Tracks execution metrics, identifies slow patterns, and detects performance anomalies.
  2. How the Behavior Manager works

    master

    The Behavior Manager provides advanced detection for suspicious usage patterns and automated responses. It is composed of three main parts:

    1. BehaviorTracker: The central engine that tracks and analyzes patterns (endpoint usage, return patterns, and request frequency).
    2. BehaviorRule: The configuration object that defines what constitutes suspicious behavior (thresholds, time windows, and patterns) and what action to take.
    3. Integration: The system can be used manually via the tracker or automatically via FastAPI decorators.

    This system allows you to detect when an IP address is accessing endpoints too frequently or receiving specific response patterns (like 'win' or 'rare_item') too often, and then automatically apply actions like banning or throttling.

    from guard import BehaviorTracker, BehaviorRule
    
    tracker = BehaviorTracker(config)
    
    # Define a rule
    usage_rule = BehaviorRule(
        rule_type="usage",
        threshold=10,
        window=3600,
        action="ban"
    )
    
    # Track usage
    await tracker.track_endpoint_usage(endpoint_id, client_ip, usage_rule)
  3. Use Distributed Banning with Redis

    master

    If Redis is enabled in your environment, IPBanManager transitions from local in-memory tracking to distributed banning. In this mode:

    • Bans are shared across all application instances in the cluster.
    • Ban expiration is handled automatically.
    • The manager supports atomic ban operations.
    # Cluster-wide ban
    await ip_ban_manager.ban_ip("192.168.1.1", 3600)
    
    # Check ban status across cluster
    is_banned = await ip_ban_manager.is_ip_banned("192.168.1.1")
  4. Tune semantic analysis and caching

    master

    Semantic Analysis

    Control the performance/security trade-off using detection_semantic_threshold.

    • Higher threshold (e.g., 0.8): Faster, triggers fewer semantic checks (high confidence only).
    • Lower threshold (e.g., 0.6): More thorough, higher security overhead.

    You can also selectively disable semantic analysis for specific low-risk endpoints (like /health).

    Caching

    Optimize Redis for high traffic by increasing redis_pool_size. Monitor the pattern compilation cache hit rate via sus_patterns_handler._compiler.get_cache_stats(). If the hit rate is below 0.8, increase compiler.max_cache_size.

    # Adjust Semantic Threshold
    config = SecurityConfig(
        detection_semantic_threshold=0.8
    )
    
    # Optimize Redis
    config = SecurityConfig(
        use_redis=True,
        redis_pool_size=20,
        redis_ttl=3600,
    )
  5. Understand Detection Engine Results Format

    master

    When a threat is detected, the engine returns a detailed dictionary containing the threat type, score, context, and performance metrics. This allows for granular response logic in your application.

    {
        "is_threat": true,
        "threat_score": 0.85,
        "threats": [
            {
                "type": "regex",
                "pattern": "union.*select",
                "execution_time": 0.002
            }
        ],
        "context": "body:json",
        "original_length": 500,
        "processed_length": 500,
        "execution_time": 0.015,
        "detection_method": "enhanced",
        "timeouts": [],
        "correlation_id": "request-123"
    }
  6. Understand Security Decorator configuration priority

    master

    When applying security settings, FastAPI Guard follows a specific hierarchy of precedence. This allows you to set global defaults while overriding them for specific sensitive endpoints:

    1. Decorator Settings: Route-specific configurations (Highest priority)
    2. Global Middleware Settings: Application-wide defaults defined in SecurityConfig
    3. Built-in Defaults: Library-level defaults (Lowest priority)
    # Global: 100 requests/hour
    config = SecurityConfig(rate_limit=100, rate_limit_window=3600)
    
    @app.get("/api/public")
    def public_endpoint():
        # Uses global: 100 requests/hour
        return {"data": "public"}
    
    @app.get("/api/limited")
    @guard_deco.rate_limit(requests=10, window=300)  # Override: 10 requests/5min
    def limited_endpoint():
        # Uses decorator: 10 requests/5min
        return {"data": "limited"}
  7. How CloudManager handles Redis integration

    master

    When Redis is enabled, CloudManager changes its behavior to support distributed environments:

    • Caching: Cloud IP ranges are cached in Redis with a configurable TTL (controlled by cloud_ip_refresh_interval or the ttl parameter in refresh_async).
    • Synchronization: Using Redis ensures that IP ranges are synchronized across all application instances.
    • Fallback: The manager uses cached ranges from Redis if they are available.

    Note that when Redis is enabled, the standard refresh() method is disabled and will raise a RuntimeError to prevent inconsistent state; you must use refresh_async() instead.

  8. Limitations of the Detection Engine

    master

    Users should be aware of the following constraints:

    • Pattern-Based: The engine relies on known attack patterns and cannot detect unknown (zero-day) threats outside those patterns.
    • Context-Unaware: It does not understand your specific application logic.
    • Performance Trade-offs: Increasing the number of detection rules will increase latency.
    • False Positives: Legitimate content may occasionally match defined patterns.
  9. Use the provided Redis handler for caching in custom handlers

    master

    When implementing initialize_redis(self, redis_handler: RedisHandlerProtocol), you receive an instance of FastAPI Guard's RedisManager. You can use this to cache lookup results, store database files, or share state across instances without managing your own connection pools.

    Available methods on the redis_handler:

    • await redis_handler.set_key(namespace: str, key: str, value: Any, ttl: int | None = None): Store a value with an optional TTL.
    • await redis_handler.get_key(namespace: str, key: str): Retrieve a value.
    • async with redis_handler.get_connection() as conn: Access the underlying connection for direct Redis operations.
    async def initialize_redis(self, redis_handler: RedisHandlerProtocol) -> None:
        self.redis = redis_handler
        # Example: Check for cached database in Redis
        cached_db = await self.redis.get_key("custom", "database")
        if cached_db:
            # ... use cached data
            pass
  10. Choose between In-Memory and Redis Rate Limiting

    master

    FastAPI Guard supports two storage backends for rate limiting:

    In-Memory Rate Limiting

    Uses an in-memory deque for tracking timestamps. This is the default behavior.

    • Pros: No external dependencies, fast performance, automatic cleanup.
    • Cons: Data is lost on restart and is not shared across multiple application instances.

    Redis-Based Rate Limiting

    Ideal for distributed environments and production use.

    • Pros: Works across multiple instances, persists through restarts, uses atomic Lua scripts for concurrency safety.
    • Cons: Requires a Redis server and introduces slight network latency.

    To use Redis, provide a redis_url and an optional redis_prefix in your SecurityConfig.

    # Redis-Based Configuration
    config = SecurityConfig(
        rate_limit=100,
        rate_limit_window=60,
        redis_url="redis://localhost:6379/0",
        redis_prefix="myapp:"  # Optional prefix for Redis keys
    )
  11. How RateLimitManager works

    master

    The RateLimitManager implements a true sliding window algorithm to protect APIs from abuse. Unlike simple counter-based limiters, it tracks individual request timestamps to prevent traffic spikes at window boundaries.

    Key Features

    • In-memory tracking: Uses deques for efficient, chronological storage of timestamps. Best for single-instance applications where low latency is critical.
    • Redis-based distributed limiting: Uses Redis sorted sets to maintain state across multiple API instances. This ensures consistent rate limiting in distributed environments.
    • Atomic Operations: Uses Redis Lua scripts to ensure that adding timestamps, removing expired ones, and counting requests happen atomically, preventing race conditions in high-concurrency scenarios.
    • Automatic Cleanup: Expired timestamps are automatically removed to prevent memory leaks.
  12. Understand the relationship between fastapi-guard and guard-core

    master

    When contributing or extending the security logic, it is important to distinguish between the two repositories:

    • fastapi-guard: This repository serves as the FastAPI/Starlette adapter layer. It provides the decorators, middleware, and integration logic specifically for the FastAPI ecosystem.
    • guard-core: This is where the actual security logic resides. New security features such as checks, detection patterns, and handlers should be contributed to the guard-core repository.