ISSUE_28_IMPLEMENTATION_SUMMARY.md 8.7 KB

Issue #28 Implementation Summary: "When authentication is enabled, login should be forced"

Overview

This document summarizes the implementation of Issue #28, which addresses the security gap where authentication was not properly enforced when enabled. The changes ensure that when authentication is enabled, only explicitly public endpoints are accessible without authentication.

Changes Made

1. Tightened Default Public Paths

File: src/auth_middleware.cpp

Changes:

  • Modified initializeDefaultPaths() to only include truly essential endpoints as public by default
  • Reduced default public paths from 7 endpoints to just 2:
    • /api/health - Health check endpoint
    • /api/status - Basic server status
  • Moved model discovery endpoints from public paths to user paths:
    • /api/models, /api/models/types, /api/models/directories
    • /api/samplers, /api/schedulers, /api/parameters

Security Impact: Prevents unauthorized access to model information and system capabilities when authentication is enabled.

2. Enhanced Authentication Logic

File: src/auth_middleware.cpp

Changes:

  • Modified requiresAuthentication() to follow an "authentication-first" approach
  • Added explicit check for authentication disabled status first
  • When authentication is enabled, only paths explicitly in publicPaths are accessible without authentication
  • All other paths require authentication when auth is enabled

Before:

bool AuthMiddleware::requiresAuthentication(const std::string& path) const {
    // Check if path is public
    if (pathMatchesPattern(path, m_config.publicPaths)) {
        return false;
    }
    // If authentication is enabled (not NONE), then all paths except public ones require authentication
    return !isAuthenticationDisabled();
}

After:

bool AuthMiddleware::requiresAuthentication(const std::string& path) const {
    // First check if authentication is completely disabled
    if (isAuthenticationDisabled()) {
        return false;
    }
    // Authentication is enabled, check if path is explicitly public
    if (pathMatchesPattern(path, m_config.publicPaths)) {
        return false;
    }
    // All other paths require authentication when auth is enabled
    return true;
}

3. Configurable Public Paths

Files:

  • include/server_config.h
  • src/auth_middleware.cpp
  • src/main.cpp

Changes:

  • Added customPublicPaths field to AuthConfig structure
  • Added --public-paths command line option
  • Implemented parsing of comma-separated public paths with automatic trimming and prefix handling
  • Added help documentation for the new option

Usage Examples:

# Default behavior (only health and status are public)
./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt

# Custom public paths
./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt --public-paths "/api/health,/api/status,/api/models"

# Make all endpoints public (not recommended for production)
./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt --public-paths "/"

4. Protected Endpoint Updates

File: src/server.cpp

Changes:

  • Updated all model discovery endpoints to use authentication middleware:
    • /api/samplers, /api/schedulers, /api/parameters
    • /api/models, /api/models/types, /api/models/directories
    • /api/models/stats
  • Updated queue endpoints to require authentication:
    • /api/queue/status, /api/queue/job/{id}

Security Impact: Ensures all potentially sensitive endpoints require authentication when auth is enabled.

5. Documentation

File: AUTHENTICATION_SECURITY_GUIDE.md

Changes:

  • Created comprehensive security guide explaining the authentication changes
  • Documented default secure configuration
  • Provided migration guide for existing deployments
  • Included best practices and troubleshooting information
  • Added examples for different deployment scenarios

6. Unit Tests

Files:

  • test_auth_security_simple.cpp
  • src/CMakeLists.txt

Changes:

  • Created comprehensive test suite covering all authentication scenarios
  • Added build configuration for the new test executable
  • Tests cover:
    • Default public paths behavior
    • Custom public paths configuration
    • Authentication method consistency
    • Protected endpoint verification
    • Edge cases and error conditions

Security Improvements

Before Implementation

  • When authentication was enabled, many endpoints remained publicly accessible
  • Model discovery, system information, and utility endpoints were exposed without authentication
  • No way to customize which endpoints should be public
  • Inconsistent authentication enforcement across different auth methods

After Implementation

  • Secure by Default: Only essential health/status endpoints are public when auth is enabled
  • Explicit Control: Administrators can customize public paths via command line
  • Consistent Enforcement: All auth methods properly enforce authentication requirements
  • Comprehensive Protection: All sensitive endpoints require authentication when enabled

Migration Guide

For Existing Deployments

  1. Review Client Applications: Check if any applications rely on previously public endpoints
  2. Update Authentication: Ensure client applications handle authentication properly
  3. Configure Public Paths: Use --public-paths if needed to maintain compatibility
  4. Test Thoroughly: Verify all endpoints behave as expected

Example Migration Scenarios

Scenario 1: Public API Documentation

./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt --public-paths "/api/health,/api/status,/api/docs,/api/openapi.json"

Scenario 2: Internal Monitoring

./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt --public-paths "/api/health,/api/status,/api/queue/status"

Scenario 3: Development Environment

./stable-diffusion-rest --models-dir /data/SD_MODELS --auth jwt --public-paths "/api/health,/api/status,/api/models,/api/samplers"

Testing

Building and Running Tests

# Configure build with tests enabled
cmake -DBUILD_AUTH_SECURITY_TEST=ON ..

# Build the test
cmake --build . --target test_auth_security_simple

# Run the tests
./build/bin/test_auth_security_simple

Test Coverage

The test suite covers:

  • ✅ Default public paths when auth is disabled
  • ✅ Default public paths when auth is enabled
  • ✅ Custom public paths configuration
  • ✅ Path parsing with spaces and auto-prefixing
  • ✅ Model discovery endpoint protection
  • ✅ Generation endpoint protection
  • ✅ Queue endpoint protection
  • ✅ Authentication method consistency
  • ✅ Optional authentication scenarios

Command Line Options

New Option

  • --public-paths <paths>: Comma-separated list of public paths that don't require authentication
    • Default: /api/health,/api/status when auth is enabled
    • Example: --public-paths "/api/health,/api/status,/api/models"

Updated Help Text

Authentication Options:
  --auth <method>                 Authentication method (none, jwt, api-key, unix, pam, optional)
  --auth-method <method>          Authentication method (alias for --auth)
  --jwt-secret <secret>           JWT secret key (auto-generated if not provided)
  --jwt-expiration <minutes>      JWT token expiration time (default: 60)
  --enable-guest-access          Allow unauthenticated guest access
  --pam-service-name <name>      PAM service name (default: stable-diffusion-rest)
  --auth-data-dir <dir>          Directory for authentication data (default: ./auth)
  --public-paths <paths>         Comma-separated list of public paths (default: /api/health,/api/status)

Best Practices

  1. Principle of Least Privilege: Only make endpoints public that are absolutely necessary
  2. Regular Security Reviews: Periodically review your authentication configuration
  3. Monitor Access: Log and monitor authentication attempts
  4. Use Strong Authentication: Prefer JWT or PAM over simpler methods
  5. Secure Communication: Always use HTTPS in production
  6. Token Management: Implement proper token expiration and refresh mechanisms

Conclusion

The implementation of Issue #28 significantly improves the security posture of the stable-diffusion.cpp-rest server by ensuring that when authentication is enabled, login is truly forced and only explicitly configured endpoints remain publicly accessible. The changes provide administrators with fine-grained control over public endpoints while maintaining a secure default configuration.

The implementation is backward compatible through the --public-paths configuration option, allowing existing deployments to migrate at their own pace while immediately benefiting from the improved security defaults.