|
|
1 month ago | |
|---|---|---|
| .gitignore | 3 months ago | |
| Caddyfile.example | 3 months ago | |
| README.md | 3 months ago | |
| add_key.py | 1 month ago | |
| config.json.example | 3 months ago | |
| config.py | 1 month ago | |
| emergency-access.service | 3 months ago | |
| generate_passwords.py | 3 months ago | |
| install.sh | 3 months ago | |
| main.py | 1 month ago | |
| ntfy.yml | 3 months ago | |
| requirements.txt | 3 months ago | |
| test.py | 3 months ago |
A fail-safe webserver that provides secure access to multiple decryption key parts with HTTP Basic Authentication and mandatory notification system integration. Designed for emergency scenarios where key retrieval must be monitored and logged.
The system consists of multiple authenticated key endpoints and a health monitoring endpoint:
Emergency Key Endpoints (e.g., /emergency-key-backup, /emergency-key-master):
Health Check Endpoint (/health-check):
Log Monitoring: All application logs (WARNING level and above by default) are automatically sent to the health backends for real-time monitoring and alerting.
The server runs on localhost:1127 by default and is designed to be accessed through a Caddy reverse proxy for security and TLS termination.
Run the automated installation script as root:
sudo ./install.sh
The installation script will:
The system includes three key management scripts:
add_key.py - Add New KeysAdd new emergency access keys to your configuration:
# Interactive key addition (recommended)
python add_key.py --interactive
# Add key programmatically
python add_key.py --key-id backup \
--file /etc/emergency-access/backup-key.txt \
--backends matrix_sec,email \
--create-file
# List existing keys
python add_key.py --list
# Remove a key
python add_key.py --remove backup --remove-file
manage_keys.py - Key File OperationsManage key files, test access, and validate configuration:
# List all key files and their status
python manage_keys.py --list-files
# Validate all key files
python manage_keys.py --validate
# Test access to a specific key
python manage_keys.py --test-key backup --password "your_password"
# Test health endpoint
python manage_keys.py --test-health --password "health_password"
# Create/rotate key files
python manage_keys.py --rotate-key backup --key-type ssh
python manage_keys.py --create-key-file /path/to/key.txt --key-type api
# Generate key content
python manage_keys.py --generate-content ssh
generate_passwords.py - Password ManagementGenerate secure passwords and update configuration:
# Generate passwords for specific keys
python generate_passwords.py --keys backup master recovery
# Interactive password setup
python generate_passwords.py --interactive
# Update configuration with new passwords
python generate_passwords.py --keys backup --update-config config.json
# Hash a specific password
python generate_passwords.py --hash-password "my_secure_password"
Install system dependencies:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install python3 python3-pip python3-venv
# RHEL/CentOS/Fedora (venv is built-in with Python 3.3+)
sudo dnf install python3 python3-pip
# Verify venv is available
python3 -m venv --help
Create service user:
sudo groupadd --system emergency-access
sudo useradd --system --gid emergency-access --home-dir /opt/emergency-access \
--shell /bin/false emergency-access
Setup directories:
sudo mkdir -p /opt/emergency-access /etc/emergency-access
sudo chown emergency-access:emergency-access /opt/emergency-access /etc/emergency-access
sudo chmod 755 /opt/emergency-access
sudo chmod 750 /etc/emergency-access
Install application:
sudo cp *.py requirements.txt /opt/emergency-access/
sudo cp config.json.example /etc/emergency-access/config.json
sudo chown -R emergency-access:emergency-access /opt/emergency-access
Setup Python environment:
sudo -u emergency-access python3 -m venv /opt/emergency-access/venv
sudo -u emergency-access /opt/emergency-access/venv/bin/pip install -r /opt/emergency-access/requirements.txt
Install systemd service:
sudo cp emergency-access.service /etc/systemd/system/
sudo systemctl daemon-reload
Copy and edit the example configuration to /etc/emergency-access/config.json:
sudo cp config.json.example /etc/emergency-access/config.json
sudo nano /etc/emergency-access/config.json
Configuration structure:
{
"server": {
"host": "127.0.0.1",
"port": 1127
},
"routes": {
"health_route": "/health-check",
"health_username": "health_monitor",
"health_password_hash": "salt:hash_generated_by_password_tool"
},
"files": {
"dummy_file": "/etc/emergency-access/dummy.txt"
},
"keys": {
"backup_key": {
"route": "/emergency-key-backup",
"file": "/etc/emergency-access/backup-key.txt",
"username": "emergency_backup",
"password_hash": "salt:hash_generated_by_password_tool",
"backends": ["matrix_sec", "pushover_emergency"],
"message": "🚨 EMERGENCY: Backup decryption key accessed from server"
},
"master_key": {
"route": "/emergency-key-master",
"file": "/etc/emergency-access/master-key.txt",
"username": "emergency_master",
"password_hash": "salt:hash_generated_by_password_tool",
"backends": ["matrix_sec", "pushover_critical", "slack_emergency"],
"message": "🚨 CRITICAL: Master decryption key accessed from server"
},
"recovery_key": {
"route": "/emergency-key-recovery",
"file": "/etc/emergency-access/recovery-key.txt",
"username": "emergency_recovery",
"password_hash": "salt:hash_generated_by_password_tool",
"backends": ["matrix_sec", "email_emergency"],
"message": "🚨 EMERGENCY: Recovery decryption key accessed from server"
},
"admin_key": {
"route": "/emergency-key-admin",
"file": "/etc/emergency-access/admin-key.txt",
"username": "emergency_admin",
"password_hash": "salt:hash_generated_by_password_tool",
"backends": [
"matrix_sec",
"pushover_critical",
"slack_emergency",
"email_critical"
],
"message": "🚨 CRITICAL ALERT: Administrator master key accessed from server"
}
},
"notifications": {
"health_backends": ["matrix_health"],
"config_path": "/etc/emergency-access/ntfy.yml",
"health_message": "✅ Emergency access server health check completed",
"log_level": "WARNING",
"send_all_logs": true
}
}
host: Bind address (default: 127.0.0.1 for localhost only)port: Listen port (default: 1127)health_route: Path for health checks (e.g., /health-check)health_username: Username for health endpoint authenticationhealth_password_hash: PBKDF2 password hash for health endpointEach key in the keys object supports:
route: Path for this specific key (e.g., /emergency-key-backup)file: Path to the key file for this specific keyusername: Username for this key's authenticationpassword_hash: PBKDF2 password hash for this keybackends: List of notification backend names for this specific keymessage: Custom message sent when this specific key is accesseddummy_file: Path to dummy content for health checkshealth_backends: List of backend names from /etc/emergency-access/ntfy.yml for health check notifications and all application logsconfig_path: Path to the ntfy configuration file (default: /etc/emergency-access/ntfy.yml)health_message: Message sent for health checkslog_level: Minimum log level to send to health backends ("INFO", "WARNING", "ERROR")send_all_logs: Whether to send application logs to health backends (true/false)matrix_sec: Matrix backend for security alertspushover_emergency: Pushover backend for emergency notificationsslack_critical: Slack backend for critical alerts/etc/emergency-access/ntfy.ymlGenerate secure passwords and hashes:
# Generate passwords for all configured keys
python generate_passwords.py --keys backup master recovery admin
# Interactive password setup
python generate_passwords.py --interactive
# Update existing config with new passwords
python generate_passwords.py --keys backup master --update-config config.json
Create key files for each configured key:
# Backup key
echo "YOUR_BACKUP_KEY_PART_HERE" | sudo tee /etc/emergency-access/backup-key.txt
sudo chown emergency-access:emergency-access /etc/emergency-access/backup-key.txt
sudo chmod 600 /etc/emergency-access/backup-key.txt
# Master key
echo "YOUR_MASTER_KEY_PART_HERE" | sudo tee /etc/emergency-access/master-key.txt
sudo chown emergency-access:emergency-access /etc/emergency-access/master-key.txt
sudo chmod 600 /etc/emergency-access/master-key.txt
# Recovery key
echo "YOUR_RECOVERY_KEY_PART_HERE" | sudo tee /etc/emergency-access/recovery-key.txt
sudo chown emergency-access:emergency-access /etc/emergency-access/recovery-key.txt
sudo chmod 600 /etc/emergency-access/recovery-key.txt
# Admin key
echo "YOUR_ADMIN_KEY_PART_HERE" | sudo tee /etc/emergency-access/admin-key.txt
sudo chown emergency-access:emergency-access /etc/emergency-access/admin-key.txt
sudo chmod 600 /etc/emergency-access/admin-key.txt
Create dummy file:
echo "system_healthy" | sudo tee /etc/emergency-access/dummy.txt
sudo chown emergency-access:emergency-access /etc/emergency-access/dummy.txt
sudo chmod 644 /etc/emergency-access/dummy.txt
Store credentials securely:
The system uses a dedicated ntfy configuration file at /etc/emergency-access/ntfy.yml. Configure your notification backends in this file and reference them by name in the main configuration.
Edit the dedicated ntfy config (/etc/emergency-access/ntfy.yml):
backends:
- matrix_sec
- matrix_health
- pushover_emergency
matrix_sec:
backend: matrix
url: https://your-matrix-server.com
roomId: "!emergency-security:your-matrix-server.com"
userId: "@emergency-bot:your-matrix-server.com"
password: "your-matrix-bot-password"
matrix_health:
backend: matrix
url: https://your-matrix-server.com
roomId: "!emergency-health:your-matrix-server.com"
userId: "@emergency-bot:your-matrix-server.com"
password: "your-matrix-bot-password"
pushover_emergency:
backend: pushover
user_key: YOUR_PUSHOVER_USER_KEY
priority: 2
retry: 60
expire: 3600
sound: siren
Reference backend names in emergency access config:
"notifications": {
"key_backends": ["matrix_sec", "pushover_emergency"],
"health_backends": ["matrix_health"],
"config_path": "/etc/emergency-access/ntfy.yml"
}
Add more backends to /etc/emergency-access/ntfy.yml as needed:
# Additional backends in /etc/emergency-access/ntfy.yml
backends:
- matrix_sec
- matrix_health
- pushover_emergency
- slack_critical
- email_emergency
slack_critical:
backend: slack
token: YOUR_SLACK_BOT_TOKEN
recipient: "#emergency-alerts"
email_emergency:
backend: email
smtp_server: smtp.gmail.com
smtp_port: 587
username: your-email@gmail.com
password: your-app-password
to: emergency-team@company.com
from: emergency-access@company.com
# Start the service
sudo systemctl start emergency-access
# Enable automatic startup
sudo systemctl enable emergency-access
# Check status
sudo systemctl status emergency-access
# View real-time logs
sudo journalctl -u emergency-access -f
# View log file
sudo tail -f /var/log/emergency-access.log
# Check service health (through Caddy proxy)
curl https://your-domain.com/health-check-b8e3f4a2
# Or directly to local service (for testing)
curl http://localhost:1127/health-check-b8e3f4a2
# Access backup key with HTTP Basic Auth
curl -u emergency_backup:PASSWORD https://your-domain.com/emergency-key-backup
# Expected response:
{
"success": true,
"key_id": "backup_key",
"key_part": "YOUR_BACKUP_KEY_PART_HERE",
"timestamp": 1703123456.789,
"notified_backends": ["matrix_sec", "pushover_emergency"]
}
# Access master key with HTTP Basic Auth
curl -u emergency_master:PASSWORD https://your-domain.com/emergency-key-master
# Expected response:
{
"success": true,
"key_id": "master_key",
"key_part": "YOUR_MASTER_KEY_PART_HERE",
"timestamp": 1703123456.789,
"notified_backends": ["matrix_sec", "pushover_critical", "slack_emergency"]
}
# Access admin key with HTTP Basic Auth
curl -u emergency_admin:PASSWORD https://your-domain.com/emergency-key-admin
# Expected response:
{
"success": true,
"key_id": "admin_key",
"key_part": "YOUR_ADMIN_KEY_PART_HERE",
"timestamp": 1703123456.789,
"notified_backends": ["matrix_sec", "pushover_critical", "slack_emergency", "email_critical"]
}
# Authentication failure response:
{
"error": "Invalid credentials"
}
# Regular health monitoring with HTTP Basic Auth
curl -u health_monitor:PASSWORD https://your-domain.com/health-check
# Expected response (all systems operational):
{
"status": "ok",
"timestamp": 1703123456.789,
"health_backends_notified": ["matrix_health"],
"dummy_content_length": 14,
"keys_accessible": 4,
"key_files_status": {
"backup_key": true,
"master_key": true,
"recovery_key": true,
"admin_key": true
},
"key_backends_status": {
"backup_key": {
"backends": ["matrix_sec", "pushover_emergency"],
"success": true
},
"master_key": {
"backends": ["matrix_sec", "pushover_critical", "slack_emergency"],
"success": true
},
"recovery_key": {
"backends": ["matrix_sec", "email_emergency"],
"success": true
},
"admin_key": {
"backends": ["matrix_sec", "pushover_critical", "slack_emergency", "email_critical"],
"success": true
}
},
"emergency_system_ready": true
}
# Error response (when components fail):
{
"status": "error",
"message": "System components failed",
"details": [
"dummy file access failed: Permission denied",
"key file access failed for 'master_key'",
"key backends failed for 'recovery_key': Configuration error"
],
"health_notifications": true,
"dummy_file_access": false,
"key_files_status": {
"backup_key": true,
"master_key": false,
"recovery_key": true,
"admin_key": true
},
"key_backends_status": {
"backup_key": {
"backends": ["matrix_sec", "pushover_emergency"],
"success": true
},
"master_key": {
"backends": ["matrix_sec", "pushover_critical"],
"success": true
},
"recovery_key": {
"backends": ["matrix_sec", "email_emergency"],
"success": false,
"error": "Configuration error"
},
"admin_key": {
"backends": ["matrix_sec", "pushover_critical", "slack_emergency", "email_critical"],
"success": true
}
}
}
Basic Caddyfile configuration:
emergency.yourdomain.com {
tls your-email@example.com
reverse_proxy localhost:1127
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
}
rate_limit {
zone emergency {
key {remote_host}
events 10
window 1m
}
}
}
Path-based routing:
yourdomain.com {
handle /emergency/* {
uri strip_prefix /emergency
reverse_proxy localhost:1127
}
}
IP-restricted access:
:443 {
@allowed_ips remote_ip 192.168.0.0/16
handle @allowed_ips {
reverse_proxy localhost:1127
}
handle {
respond "Access Denied" 403
}
}
The service binds only to localhost (127.0.0.1:1127) and is accessed through your existing Caddy reverse proxy. No additional firewall configuration is required.
600 (owner read-only)640 (owner read/write, group read)644 (standard read permissions)Set up regular health checks:
# Cron job for health monitoring through Caddy
*/5 * * * * curl -s https://yourdomain.com/health-check-b8e3f4a2 > /dev/null
# Or direct to service for internal monitoring
*/5 * * * * curl -s http://localhost:1127/health-check-b8e3f4a2 > /dev/null
Monitor notification delivery:
Service won't start:
sudo journalctl -u emergency-access -n 50
sudo systemctl status emergency-access
Notification failures:
# Test dschep/ntfy installation and configuration
ntfy -c /etc/emergency-access/ntfy.yml send "test message"
# Check ntfy configuration
cat /etc/emergency-access/ntfy.yml
# Test specific backend
ntfy -c /etc/emergency-access/ntfy.yml -b matrix_sec send "test message"
File permission errors:
sudo chown -R emergency-access:emergency-access /opt/emergency-access
sudo chown emergency-access:emergency-access /etc/emergency-access/*
Test your setup before deployment:
# Validate configuration
sudo -u emergency-access /opt/emergency-access/venv/bin/python /opt/emergency-access/main.py --validate
# Test notifications manually with your backend
ntfy -c /etc/emergency-access/ntfy.yml -b matrix_sec send "Test notification"
ntfy -c /etc/emergency-access/ntfy.yml -b pushover_emergency send "Test emergency notification"
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Run with development config
EMERGENCY_CONFIG=config.json python main.py
# Run comprehensive test suite
python test.py
# Run quick configuration tests only
python test.py --quick
# Generate passwords for configuration
python generate_passwords.py --keys backup master recovery
# Test specific endpoints with authentication
curl -u emergency_backup:PASSWORD http://localhost:1127/emergency-key-backup
curl -u emergency_master:PASSWORD http://localhost:1127/emergency-key-master
curl -u health_monitor:PASSWORD http://localhost:1127/health-check
The application dynamically registers routes for each configured key:
for key_id, key_config in config.keys.items():
handler = create_key_handler(key_config)
endpoint_name = f'get_key_part_{key_id}'
app.add_url_rule(key_config.route, endpoint_name, handler, methods=['GET'])
Each key gets its own handler function with specific configuration:
def create_key_handler(key_config):
def get_key_part():
# Send notifications to key-specific backends
notification_success, successful_backends = send_ntfy_notification(
key_config.backends,
key_config.message,
"EMERGENCY ACCESS ALERT"
)
# Return key with key ID
return jsonify({
'success': True,
'key_id': key_config.key_id,
'key_part': content,
'timestamp': time.time(),
'notified_backends': successful_backends
})
return get_key_part
Health checks now validate all configured keys:
# Test all key files
for key_id, key_config in config.keys.items():
key_file_success, key_content = read_file_safely(key_config.file_path)
key_files_status[key_id] = key_file_success
Use the included password generator for secure authentication:
# Generate passwords for specific keys
python generate_passwords.py --keys backup master recovery
# Interactive password setup
python generate_passwords.py --interactive
# Generate and update existing config
python generate_passwords.py --keys backup master --update-config config.json
# Hash a specific password
python generate_passwords.py --hash-password "my_secure_password"
The password generator creates:
This implementation uses HTTP Basic Authentication for robust security:
This project is designed for emergency access scenarios. Use responsibly and ensure proper security measures are in place.
For issues and questions:
/var/log/emergency-access.log/etc/emergency-access/config.jsonsystemctl status emergency-accesspython generate_passwords.py --help# Validate configuration
python -c "from config import Config; Config('/etc/emergency-access/config.json')"
# Test file access
sudo -u emergency-access cat /etc/emergency-access/backup-key.txt
# Test notifications
ntfy -c /etc/emergency-access/ntfy.yml -b matrix_sec send "Test message"
# Generate secure passwords
python generate_passwords.py --keys backup master recovery
# Test authentication
curl -u emergency_backup:PASSWORD http://localhost:1127/emergency-key-backup