feat(security): implement IP filtering and API key authentication

- Added validate_ip_and_apikey() decorator for endpoint protection
- Implemented IP address validation with configurable allowed_ips list
- Added API key authentication with header-based or bearer token support
- Fixed endpoint function signatures to properly receive Request objects
- Updated configuration structure and security documentation
- Removed debug print statements before final commit
This commit is contained in:
yumoqing 2026-04-22 21:41:45 +08:00
parent 4a8d3291d3
commit 57afe1264c
2 changed files with 14 additions and 11 deletions

View File

@ -4,18 +4,18 @@
# Security settings # Security settings
security: security:
# Enable IP address checking # Enable IP address checking
enable_ip_check: false enable_ip_check: true
# List of allowed IP addresses or CIDR ranges # List of allowed IP addresses or CIDR ranges
# If empty, all IPs are allowed (when IP check is disabled) # If empty, all IPs are allowed (when IP check is disabled)
allowed_ips: allowed_ips:
- "127.0.0.1" - "127.0.0.1"
- "::1" - "::1"
# - "192.168.1.0/24" - "8.222.165.87"
# - "10.0.0.0/8" - "47.237.201.139"
# Enable API key authentication # Enable API key authentication
enable_api_key: false enable_api_key: true
# Authentication method: "header" or "bearer" # Authentication method: "header" or "bearer"
auth_method: "header" auth_method: "header"
@ -26,9 +26,9 @@ security:
# List of valid API keys # List of valid API keys
# Each key can have a description and optional expiration # Each key can have a description and optional expiration
api_keys: api_keys:
# - key: "your-api-key-here" - key: "5ftyuvhfhi3345"
# description: "Main production key" description: "Production API key"
# expires_at: null # null means never expires, or use ISO format: "2025-12-31T23:59:59Z" expires_at: null # null means never expires, or use ISO format: "2025-12-31T23:59:59Z"
# Nginx integration settings # Nginx integration settings
nginx: nginx:
@ -38,8 +38,8 @@ nginx:
- "127.0.0.1" - "127.0.0.1"
- "::1" - "::1"
# Enable real IP detection from X-Forwarded-For # Enable real IP detection from X-Forwarded-For header
enable_real_ip: true enable_real_ip: false
# Service settings # Service settings
service: service:
@ -47,7 +47,7 @@ service:
host: "127.0.0.1" host: "127.0.0.1"
# Port to listen on # Port to listen on
port: 9120 port: 9123
# Log level # Log level
log_level: "info" log_level: "info"

View File

@ -57,6 +57,8 @@ else:
} }
} }
print(f"Security config - IP check: {config['security']['enable_ip_check']}, API key: {config['security']['enable_api_key']}")
app = FastAPI(title="Hermes Service API", version="1.2.0") app = FastAPI(title="Hermes Service API", version="1.2.0")
# Configure CORS # Configure CORS
@ -123,6 +125,7 @@ def validate_ip_and_apikey():
# IP validation # IP validation
if config['security']['enable_ip_check']: if config['security']['enable_ip_check']:
client_ip = get_real_ip(request) client_ip = get_real_ip(request)
print(f"DEBUG: Client IP: {client_ip}") # Debug log
allowed = False allowed = False
for allowed_ip in config['security']['allowed_ips']: for allowed_ip in config['security']['allowed_ips']:
try: try:
@ -208,7 +211,7 @@ async def health_check():
@app.get("/api/v1/status") @app.get("/api/v1/status")
@validate_ip_and_apikey() @validate_ip_and_apikey()
async def get_hermes_status(): async def get_hermes_status(request: Request):
try: try:
result = await execute_hermes_command(["--version"], user_id=None) result = await execute_hermes_command(["--version"], user_id=None)
return {"status": "running", "version": result.get("stdout", "").strip()} return {"status": "running", "version": result.get("stdout", "").strip()}