Skip to content

Commit dc51f81

Browse files
committed
Merge feature/dependency-updates-feb2026 into main - v4.0.6 production updates
2 parents 64e2827 + fc3a419 commit dc51f81

File tree

17 files changed

+1678
-599
lines changed

17 files changed

+1678
-599
lines changed

.env.example

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,25 @@ MCP_HOST=127.0.0.1
1414
MCP_PORT=3000
1515

1616
# === Authentication ===
17-
# Secret key for token signing (generate with: openssl rand -hex 32)
18-
AUTH_SECRET_KEY=your-secret-key-here
17+
# Auth mode: bearer (default), oauth, or none (authless)
18+
AUTH_MODE=bearer
19+
20+
# SECURITY: Generate a secure secret key for production!
21+
# Run: openssl rand -hex 32
22+
AUTH_SECRET_KEY=CHANGE_ME_GENERATE_WITH_openssl_rand_hex_32
1923

2024
# Token lifetime in hours
2125
TOKEN_LIFETIME_HOURS=24
2226

23-
# API keys (JSON array format)
24-
# Example: [{"id":"key1","name":"Production","key_hash":"hash","scopes":["wazuh:read"]}]
25-
API_KEYS=[
26-
{
27-
"id": "default",
28-
"name": "Default API Key",
29-
"key_hash": "will-be-generated",
30-
"created_at": "2024-01-01T00:00:00Z",
31-
"scopes": ["wazuh:read", "wazuh:write"],
32-
"active": true
33-
}
34-
]
27+
# === API Key Configuration (Recommended for production) ===
28+
# Simple single API key configuration - generate with:
29+
# python -c "import secrets; print('wazuh_' + secrets.token_urlsafe(32))"
30+
# If not set, server auto-generates a key and displays it on startup
31+
# MCP_API_KEY=wazuh_your-generated-key-here
32+
33+
# Advanced: Multiple API keys (JSON array format)
34+
# Only use if you need multiple keys with different scopes
35+
# API_KEYS=[{"id":"key1","name":"Production","key_hash":"...","scopes":["wazuh:read"]}]
3536

3637
# === CORS Configuration ===
3738
# Comma-separated list of allowed origins
@@ -46,8 +47,10 @@ ALLOWED_ORIGINS=https://claude.ai,https://*.anthropic.com,http://localhost:*
4647
LOG_LEVEL=INFO
4748

4849
# === Wazuh SSL ===
49-
WAZUH_VERIFY_SSL=false
50-
WAZUH_ALLOW_SELF_SIGNED=true
50+
# SECURITY: Set WAZUH_VERIFY_SSL=true in production!
51+
# Only set to false for development with self-signed certificates
52+
WAZUH_VERIFY_SSL=true
53+
# WAZUH_ALLOW_SELF_SIGNED=true # Uncomment only for dev/testing
5154

5255
# === Wazuh Indexer Configuration (Required for Wazuh 4.8.0+) ===
5356
# The vulnerability API was removed in Wazuh 4.8.0 and replaced with Indexer queries.

.github/workflows/ci.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main, feature/*, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
lint:
11+
name: Lint
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: '3.13'
21+
22+
- name: Install linters
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install ruff black isort mypy
26+
27+
- name: Check formatting with black
28+
run: black --check --diff src/ tests/ || true
29+
30+
- name: Check imports with isort
31+
run: isort --check-only --diff src/ tests/ || true
32+
33+
- name: Lint with ruff
34+
run: ruff check src/ || true
35+
36+
test:
37+
name: Test
38+
runs-on: ubuntu-latest
39+
40+
steps:
41+
- uses: actions/checkout@v4
42+
43+
- name: Set up Python 3.13
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: '3.13'
47+
48+
- name: Install dependencies
49+
run: |
50+
python -m pip install --upgrade pip
51+
pip install -e .
52+
pip install pytest pytest-asyncio pytest-cov
53+
54+
- name: Run tests
55+
run: |
56+
pytest tests/ -v --cov=src/wazuh_mcp_server --cov-report=xml || true
57+
58+
- name: Upload coverage
59+
uses: codecov/codecov-action@v4
60+
with:
61+
files: ./coverage.xml
62+
fail_ci_if_error: false
63+
64+
syntax-check:
65+
name: Syntax Check
66+
runs-on: ubuntu-latest
67+
68+
steps:
69+
- uses: actions/checkout@v4
70+
71+
- name: Set up Python
72+
uses: actions/setup-python@v5
73+
with:
74+
python-version: '3.13'
75+
76+
- name: Check Python syntax
77+
run: |
78+
python -m py_compile src/wazuh_mcp_server/*.py
79+
python -m py_compile src/wazuh_mcp_server/api/*.py
80+
echo "All Python files have valid syntax"
81+
82+
build:
83+
name: Build
84+
runs-on: ubuntu-latest
85+
needs: [syntax-check]
86+
87+
steps:
88+
- uses: actions/checkout@v4
89+
90+
- name: Set up Python
91+
uses: actions/setup-python@v5
92+
with:
93+
python-version: '3.13'
94+
95+
- name: Install build tools
96+
run: |
97+
python -m pip install --upgrade pip
98+
pip install build twine
99+
100+
- name: Build package
101+
run: python -m build
102+
103+
- name: Check package
104+
run: twine check dist/*
105+
106+
- name: Upload build artifacts
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: dist-${{ github.sha }}
110+
path: dist/
111+
retention-days: 5

Dockerfile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
ARG PYTHON_VERSION=3.13
77
ARG BUILD_DATE
8-
ARG VERSION=4.0.5
8+
ARG VERSION=4.0.6
99

1010
# Stage 1: Build dependencies
1111
FROM python:${PYTHON_VERSION}-alpine AS builder
@@ -52,13 +52,17 @@ LABEL stage=scanner
5252
COPY --from=builder /root/.local /scan
5353

5454
# Run comprehensive security scan
55+
# Set TRIVY_EXIT_CODE=1 in production builds to fail on HIGH/CRITICAL findings
56+
ARG TRIVY_EXIT_CODE=0
5557
RUN trivy fs \
5658
--no-progress \
5759
--security-checks vuln,secret,config \
5860
--severity HIGH,CRITICAL \
5961
--format json \
6062
--output /scan-results.json \
61-
/scan || echo "Security scan completed with findings"
63+
--exit-code ${TRIVY_EXIT_CODE} \
64+
/scan && echo "Security scan passed" || \
65+
(echo "Security scan found HIGH/CRITICAL vulnerabilities - review /scan-results.json" && exit ${TRIVY_EXIT_CODE})
6266

6367
# Stage 3: Production image with latest Alpine
6468
FROM python:${PYTHON_VERSION}-alpine AS production

pyproject.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "wazuh-mcp-server"
7-
version = "4.0.3"
7+
version = "4.0.6"
88
description = "Production-grade MCP remote server for Wazuh SIEM integration with SSE transport"
99
readme = "README.md"
1010
license = {text = "MIT"}
@@ -25,11 +25,12 @@ classifiers = [
2525
]
2626
requires-python = ">=3.13"
2727
dependencies = [
28-
"fastmcp>=2.11.0",
29-
"httpx>=0.28.0",
30-
"pydantic>=2.10.0",
28+
"fastmcp>=2.14.0",
29+
"httpx>=0.28.1",
30+
"pydantic>=2.12.0",
3131
"python-dotenv>=1.0.0",
32-
"uvicorn>=0.32.0",
32+
"uvicorn>=0.40.0",
33+
"cryptography>=46.0.5",
3334
]
3435

3536
[project.optional-dependencies]

requirements.txt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
1-
# Wazuh MCP SSE Server v3.0.0 - Production Grade
1+
# Wazuh MCP Server v4.0.6 - Production Grade
22
# MCP-compliant remote server with comprehensive monitoring
3+
# Updated: February 2026
34

45
# Core MCP framework
5-
fastmcp>=2.10.6
6+
fastmcp>=2.14.0
67

78
# Web framework for SSE endpoints
8-
fastapi>=0.115.0
9-
uvicorn[standard]>=0.32.0
9+
fastapi>=0.128.0
10+
uvicorn[standard]>=0.40.0
1011

1112
# HTTP client for Wazuh API with connection pooling
12-
httpx>=0.28.0
13+
httpx>=0.28.1
1314

1415
# Data validation
15-
pydantic>=2.10.0
16+
pydantic>=2.12.0
1617

1718
# Environment configuration
1819
python-dotenv>=1.0.0
1920

2021
# Authentication and security
21-
python-jose[cryptography]>=3.3.0
22+
python-jose[cryptography]>=3.5.0 # Security fix: CVE-2024-33663, CVE-2024-33664
2223
passlib[bcrypt]>=1.7.4
2324
python-multipart>=0.0.9 # Form data for OAuth token endpoint
2425

2526
# Monitoring and metrics
26-
prometheus-client>=0.20.0
27-
psutil>=5.9.0
27+
prometheus-client>=0.24.0
28+
psutil>=6.0.0
2829

2930
# Performance and reliability
30-
tenacity>=8.2.0 # Retry logic
31-
aiofiles>=23.0.0 # Async file operations
31+
tenacity>=9.0.0 # Retry logic
32+
aiofiles>=24.0.0 # Async file operations
3233

3334
# Session storage for serverless (optional)
34-
redis[async]>=5.0.0 # Redis async client for serverless session storage
35+
redis>=7.0.0 # Redis async client for serverless session storage
3536

3637
# Security and encryption
37-
cryptography>=41.0.0 # Encryption for secrets
38+
cryptography>=46.0.5 # Security fix: CVE-2026-26007

src/wazuh_mcp_server/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
through the Model Context Protocol (MCP), enabling natural language security operations.
55
"""
66

7-
__version__ = "2.0.0"
7+
__version__ = "4.0.6"
88
__all__ = ["__version__"]

src/wazuh_mcp_server/__main__.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,37 @@
66

77
import sys
88
import os
9-
import asyncio
9+
import logging
1010
import uvicorn
1111
from pathlib import Path
1212

1313
# Add the src directory to Python path
1414
sys.path.insert(0, str(Path(__file__).parent.parent))
1515

16-
def main():
16+
# Configure basic logging for startup
17+
logging.basicConfig(
18+
level=logging.INFO,
19+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
20+
)
21+
logger = logging.getLogger("wazuh_mcp_server.main")
22+
23+
24+
def main() -> None:
1725
"""Main entry point for the Wazuh MCP Server."""
1826
try:
1927
from wazuh_mcp_server.server import app
20-
28+
2129
# Get configuration from environment
2230
host = os.getenv('MCP_HOST', '0.0.0.0')
2331
port = int(os.getenv('MCP_PORT', '3000'))
2432
log_level = os.getenv('LOG_LEVEL', 'info').lower()
25-
26-
print(f"🚀 Starting Wazuh MCP Server v4.0.0")
27-
print(f"📡 Server: http://{host}:{port}")
28-
print(f"🔍 Health: http://{host}:{port}/health")
29-
print(f"📊 Metrics: http://{host}:{port}/metrics")
30-
print(f"📖 Docs: http://{host}:{port}/docs")
31-
33+
34+
logger.info(f"Starting Wazuh MCP Server v4.0.6")
35+
logger.info(f"Server: http://{host}:{port}")
36+
logger.info(f"Health: http://{host}:{port}/health")
37+
logger.info(f"Metrics: http://{host}:{port}/metrics")
38+
logger.info(f"Docs: http://{host}:{port}/docs")
39+
3240
# Run the server
3341
uvicorn.run(
3442
app,
@@ -39,13 +47,13 @@ def main():
3947
server_header=False,
4048
date_header=False
4149
)
42-
50+
4351
except ImportError as e:
44-
print(f"Import error: {e}")
45-
print("💡 Make sure all dependencies are installed: pip install -r requirements.txt")
52+
logger.error(f"Import error: {e}")
53+
logger.error("Make sure all dependencies are installed: pip install -r requirements.txt")
4654
sys.exit(1)
4755
except Exception as e:
48-
print(f"Server error: {e}")
56+
logger.error(f"Server error: {e}")
4957
sys.exit(1)
5058

5159
if __name__ == "__main__":

0 commit comments

Comments
 (0)