A Security-First Middleware for Django to ensure NIS2 compliance with forensic logging, active defense, and SIEM integration.
Project description
Django NIS2 Shield
The "Security-First" Middleware for NIS2 Compliance.
Why this package?
Companies subject to NIS2 Directive need demonstrable compliance with strict logging and monitoring requirements. This middleware provides:
- Forensic logging with HMAC-SHA256 integrity and PII encryption (Art. 21.2.h)
- Rate limiting to prevent DoS/Brute Force attacks (Art. 21.2.e)
- Session Guard to detect hijacking attempts (Art. 21.2.a)
- MFA Gatekeeper for sensitive routes (Art. 21.2.j)
- SIEM integration with presets for Elasticsearch, Splunk, QRadar, Datadog
django-nis2-shield is a plug-and-play library designed to help Django applications meet the technical requirements of the NIS2 Directive.
Part of the NIS2 Shield Ecosystem: Use with infrastructure for Demonstrable Compliance (audited via
tfsec) and @nis2shield/react-guard for client-side protection.
✨ Key Features
🔒 Forensic Logger
- Structured logs (JSON or CEF) signed with HMAC-SHA256
- Automatic PII field encryption (GDPR compliant)
- Configurable IP anonymization
🛡️ Active Defense
- Rate Limiting: Protection against application-level DoS attacks (sliding window algorithm)
- Session Guard: Session hijacking prevention with mobile network tolerance
- Tor Blocker: Automatic blocking of Tor exit nodes
- MFA Gatekeeper: 2FA redirect for sensitive paths
📊 Compliance & Reporting
check_nis2command for configuration auditing- Incident report generation for CSIRT (24h deadline)
- SIEM presets for Elasticsearch, Splunk, QRadar, Graylog, Sumo Logic, and Datadog
🔔 Real-time Alerting (v0.3.0+)
- Webhook notifications for security events
- Supports Slack, Microsoft Teams, Discord, and generic HTTP
📦 Installation
pip install django-nis2-shield
For development:
pip install django-nis2-shield[dev]
⚙️ Configuration
settings.py
INSTALLED_APPS = [
...,
'django_nis2_shield',
]
MIDDLEWARE = [
...,
# Add after SessionMiddleware and before CommonMiddleware
'django_nis2_shield.middleware.Nis2GuardMiddleware',
...,
]
# NIS2 Shield Configuration
NIS2_SHIELD = {
# Security Keys
'INTEGRITY_KEY': 'change-me-to-a-secure-secret',
'ENCRYPTION_KEY': b'your-32-byte-fernet-key-here=', # Fernet.generate_key()
# Privacy (GDPR)
'ANONYMIZE_IPS': True,
'ENCRYPT_PII': True,
'PII_FIELDS': ['user_id', 'email', 'ip', 'user_agent'],
# Active Defense
'ENABLE_RATE_LIMIT': True,
'RATE_LIMIT_THRESHOLD': 100, # requests per window
'RATE_LIMIT_WINDOW': 60, # seconds
'RATE_LIMIT_ALGORITHM': 'sliding_window', # or 'fixed_window'
'ENABLE_SESSION_GUARD': True,
'SESSION_IP_TOLERANCE': 'subnet', # 'exact', 'subnet', 'none'
'BLOCK_TOR_EXIT_NODES': True,
# MFA
'ENFORCE_MFA_ROUTES': ['/admin/', '/finance/'],
'MFA_SESSION_FLAG': 'is_verified_mfa',
'MFA_REDIRECT_URL': '/accounts/login/mfa/',
# Webhooks (v0.3.0+)
'ENABLE_WEBHOOKS': True,
'WEBHOOKS': [
{'url': 'https://hooks.slack.com/...', 'format': 'slack'},
]
}
Log Format: CEF (Enterprise SIEM)
For CEF output instead of JSON:
from django_nis2_shield.cef_formatter import get_cef_logging_config
LOGGING = get_cef_logging_config('/var/log/django_nis2.cef')
🚀 Usage
Configuration Audit
python manage.py check_nis2
Threat Intelligence Update
python manage.py update_threat_list
Incident Report Generation
python manage.py generate_incident_report --hours=24 --output=incident.json
📈 Dashboard Monitoring
The project includes a Docker stack for log visualization:
cd dashboard
docker compose up -d
# Access:
# - Kibana: http://localhost:5601
# - Grafana: http://localhost:3000 (admin/admin)
See dashboard/README.md for details.
🧪 Testing
# With pytest
pip install pytest pytest-django
PYTHONPATH=. pytest tests/ -v
📖 Recipes
Banking App with MFA & Rate Limiting
# settings.py
NIS2_SHIELD = {
'INTEGRITY_KEY': os.environ['NIS2_HMAC_KEY'],
'ENCRYPTION_KEY': os.environ['NIS2_AES_KEY'],
# Rate Limit: 50 requests per minute
'ENABLE_RATE_LIMIT': True,
'RATE_LIMIT_THRESHOLD': 50,
'RATE_LIMIT_WINDOW': 60,
# MFA for admin and finance
'ENFORCE_MFA_ROUTES': ['/admin/', '/finance/', '/transfers/'],
'MFA_REDIRECT_URL': '/accounts/mfa/verify/',
}
E-commerce with Splunk SIEM
# settings.py
import os
NIS2_SHIELD = {
'INTEGRITY_KEY': os.environ['NIS2_HMAC_KEY'],
'ANONYMIZE_IPS': True,
'ENCRYPT_PII': True,
# Webhooks for real-time alerts
'ENABLE_WEBHOOKS': True,
'WEBHOOKS': [
{'url': 'https://hooks.slack.com/...', 'format': 'slack'},
]
}
# Splunk SIEM Output
from django_nis2_shield.siem import get_splunk_logging_config
LOGGING = get_splunk_logging_config(
splunk_url='https://splunk.example.com:8088',
token=os.environ['SPLUNK_HEC_TOKEN']
)
Healthcare API with Session Guard
# Block session hijacking attempts with IP tolerance for mobile networks
NIS2_SHIELD = {
'ENABLE_SESSION_GUARD': True,
'SESSION_IP_TOLERANCE': 'subnet', # 'exact', 'subnet', or 'none'
'BLOCK_TOR_EXIT_NODES': True,
}
📄 License
MIT License - see LICENSE for details.
🤝 Contributing
Contributions are welcome! Open an issue or PR on GitHub.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_nis2_shield-0.3.2.tar.gz.
File metadata
- Download URL: django_nis2_shield-0.3.2.tar.gz
- Upload date:
- Size: 27.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3403ecffbb64f6c45310650006df1b3610b35f033501aa1d724845dce7df19ed
|
|
| MD5 |
4092f39d2a7a69baaddcbd80a24c0a8e
|
|
| BLAKE2b-256 |
b0f003a0590a698b2dcead4048058a6109e5a49ac6883f7dc68444527376171d
|
Provenance
The following attestation bundles were made for django_nis2_shield-0.3.2.tar.gz:
Publisher:
publish.yml on nis2shield/django-nis2-shield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_nis2_shield-0.3.2.tar.gz -
Subject digest:
3403ecffbb64f6c45310650006df1b3610b35f033501aa1d724845dce7df19ed - Sigstore transparency entry: 785543340
- Sigstore integration time:
-
Permalink:
nis2shield/django-nis2-shield@c5cefbb9ff61268f2035ede3b8bab716d124d794 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/nis2shield
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c5cefbb9ff61268f2035ede3b8bab716d124d794 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_nis2_shield-0.3.2-py3-none-any.whl.
File metadata
- Download URL: django_nis2_shield-0.3.2-py3-none-any.whl
- Upload date:
- Size: 22.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be9528e06fd07b71abdd917e9679009ea7d77abb6c5878bfd561ec8c870f8e48
|
|
| MD5 |
f662b6c81d69a3f63e97461a1dfa1f3c
|
|
| BLAKE2b-256 |
5ecfa7559ee69c65adcc9ddc84ecab87c641e2c71e5d27c35b2d79cd0ed72e5c
|
Provenance
The following attestation bundles were made for django_nis2_shield-0.3.2-py3-none-any.whl:
Publisher:
publish.yml on nis2shield/django-nis2-shield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_nis2_shield-0.3.2-py3-none-any.whl -
Subject digest:
be9528e06fd07b71abdd917e9679009ea7d77abb6c5878bfd561ec8c870f8e48 - Sigstore transparency entry: 785543395
- Sigstore integration time:
-
Permalink:
nis2shield/django-nis2-shield@c5cefbb9ff61268f2035ede3b8bab716d124d794 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/nis2shield
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c5cefbb9ff61268f2035ede3b8bab716d124d794 -
Trigger Event:
release
-
Statement type: