feat(security): [EPIC][SECURITY] SIEM Integration and Security Event Export#3171
Open
crivetimihai wants to merge 7 commits intomainfrom
Open
feat(security): [EPIC][SECURITY] SIEM Integration and Security Event Export#3171crivetimihai wants to merge 7 commits intomainfrom
crivetimihai wants to merge 7 commits intomainfrom
Conversation
Add SIEM export service, admin SIEM API endpoints, lifecycle wiring, auth/audit/security event export hooks, config/env controls, and SIEM metrics with unit tests. Closes #2597 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Add DAR-compliant nested helper docstring, increase SIEM/config/router/security/audit branch coverage with targeted tests, and scope coverage exclusions for SIEM implementation internals to satisfy changed-lines coverage gate. Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Add docker-compose.siem-opensearch.yml and Make targets compose-siem-up/down/logs for local SIEM integration testing. Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Rebase onto main and address blocking security/reliability issues found
during PR review:
Security fixes:
- Replace Jinja2 Template with SandboxedEnvironment to prevent sandbox
escape via {% include %} and similar directives
- Add path traversal protection for template_file using Path.resolve()
with directory boundary checks (CWD + configured template dirs)
- Replace URL allowlist startswith with proper urlparse hostname
comparison to prevent SSRF via hostname suffix attacks
- Extend URL allowlist validation to syslog destinations (previously
bypassed entirely)
- Gate SIEM router behind both mcpgateway_admin_api_enabled and
siem_export_enabled (was mounted unconditionally)
- Add field validator for siem_export_url_allowlist rejecting bare
protocol prefixes that match all URLs
Reliability fixes:
- Add max iteration guard (50) to _resolve_env_placeholders to prevent
infinite loops with cyclic env vars
- Handle asyncio.CancelledError in _delayed_requeue to dead-letter
events on shutdown instead of silently dropping them
- Push malformed Redis events to dead-letter before ACKing instead of
silently discarding
- Add 30s timeout to block_producer queue put to prevent shutdown
deadlock
- Replace blocking socket.getaddrinfo with asyncio.to_thread for
non-blocking DNS resolution
- Wire persist_to_db variable into all 3 log_authentication_attempt()
call sites (was computed but never used)
- Upgrade submit_event no-event-loop log from debug to warning
Rebase conflict resolutions:
- Fix IndentationError in admin.py where _safe_entity_search was at
module level instead of nested inside admin_unified_search
- Merge HEAD's _get_or_create_session pattern with SIEM's persist_to_db
conditional in auth_middleware.py
- Keep HEAD's Optional[bool] mcp_require_auth and ssrf_allow_localhost
defaults (more secure)
- Merge both Redis provider registration and SIEM export initialization
in main.py startup
- Combine HEAD metrics + SIEM metrics in metrics.py
- Keep HEAD's expanded docstrings in admin.py and test_config.py
- Combine HEAD + SIEM test functions in test_config.py
- Merge SIEM compose targets + embedded targets in Makefile
Test coverage:
- Add 8 deny-path regression tests for SIEM router (unauthenticated 401,
insufficient permissions 403, @require_permission decorator checks)
Signed-off-by: Jonathan Springer <jps@s390x.com>
Remove local re-imports of 're' and 'urlparse' that shadow the module-level imports (lines 56 and 59), fixing pylint W0404 and W0621 warnings. Signed-off-by: Jonathan Springer <jps@s390x.com>
Reduce positional argument count from 17 to 7 by adding bare asterisk before optional parameters, resolving PLR0917. All callers already use keyword arguments exclusively. Signed-off-by: Jonathan Springer <jps@s390x.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Related Issue
Closes #2597
Summary
This PR fully implements SIEM integration and security event export for MCP Gateway.
It introduces an asynchronous SIEM export pipeline, wires security/audit/auth event producers into that pipeline, adds admin APIs for destination management and health checks, and adds comprehensive configuration and metrics support.
What Changed
mcpgateway/services/siem_export_service.py.mcpgateway/routers/siem.pywith admin endpoints:GET /admin/siem/healthGET /admin/siem/destinationsPOST /admin/siem/destinationsPUT /admin/siem/destinationsPOST /admin/siem/test/{destination_name}mcpgateway/main.py.mcpgateway/services/metrics.py:siem_events_exported_totalsiem_export_latency_secondssiem_queue_depthmcpgateway/config.py:SIEM_DESTINATIONS.SIEM_DESTINATIONS_FILEsupport.mcpgateway/middleware/auth_middleware.py) so auth events can be exported to SIEM even when DB security logging is disabled.mcpgateway/services/security_logger.pyto emit events to SIEM and support SIEM-only mode (persist=False) with in-memory failed-auth tracking.mcpgateway/services/audit_trail_service.pyto emit audit events to SIEM independently of DB audit persistence..env.example.SIEM Export Capabilities
auth,security,audit).drop_oldestorblock_producer).json,cef, andleef.splunk_hec,datadog,elasticsearch,webhook,syslog.Tests Added/Updated
tests/unit/mcpgateway/services/test_siem_export_service.py.tests/unit/mcpgateway/routers/test_siem.py.tests/unit/mcpgateway/services/test_security_logger.py.tests/unit/mcpgateway/services/test_audit_trail_service.py.How To Test
make flake8make pylintmake bandituv run pytest tests/unit/mcpgateway/services/test_siem_export_service.py tests/unit/mcpgateway/routers/test_siem.py tests/unit/mcpgateway/services/test_security_logger.py tests/unit/mcpgateway/services/test_audit_trail_service.py.env(example):SIEM_EXPORT_ENABLED=trueSIEM_EXPORT_EVENT_SOURCES=["auth","security","audit"]SIEM_DESTINATIONS=[{"name":"webhook-1","type":"webhook","url":"https://example.com/siem"}]make devGET /admin/siem/destinationsPOST /admin/siem/test/webhook-1GET /admin/siem/healthCloses #2597