설명 없음

zehe e9eb409331 multi-key setup 3 달 전
.gitignore e9eb409331 multi-key setup 3 달 전
Caddyfile.example 8292e4d81c initial commit 3 달 전
README.md e9eb409331 multi-key setup 3 달 전
config.py e9eb409331 multi-key setup 3 달 전
emergency-access.service f79f0e53f0 changed to custom ntfy config 3 달 전
install.sh e9eb409331 multi-key setup 3 달 전
main.py e9eb409331 multi-key setup 3 달 전
ntfy.yml f79f0e53f0 changed to custom ntfy config 3 달 전
requirements.txt f7184f7761 actually fixed ntfy config 3 달 전
test.py e9eb409331 multi-key setup 3 달 전

README.md

Emergency Access Server

A fail-safe webserver that provides secure access to multiple decryption key parts with mandatory notification system integration. Designed for emergency scenarios where key retrieval must be monitored and logged.

Features

  • Multiple key support: Configure multiple decryption keys with individual routes and notification backends
  • Fail-safe design: All operations require successful notification delivery
  • Dynamic endpoint system: Emergency key access and health monitoring with configurable routes
  • dschep/ntfy integration: Real-time notifications via multiple backends (Pushover, Pushbullet, Slack, etc.)
  • Real-time log monitoring: All application logs automatically sent to notification backends
  • Configurable security: Extremely long random endpoint paths (100+ characters) and file locations per key
  • Caddy reverse proxy ready: Runs on localhost for secure proxy setup
  • Systemd integration: Automatic startup and service management
  • Comprehensive logging: Detailed audit trail of all operations with live notifications

Architecture

The system consists of multiple key endpoints and a health monitoring endpoint:

  1. Emergency Key Endpoints (e.g., /emergency-key-backup-a7f9d2e1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8a1d4b7c0e3f6d9a2b5c8e1f4a7b0d3):

    • Each serves a specific decryption key part
    • Extremely long paths (100+ characters) to prevent accidental access
    • Individual notification backends per key
    • Custom messages per key type
    • Fails closed if notifications cannot be sent
    • Supports unlimited number of keys
  2. Health Check Endpoint (/health-check-f8d9e2a1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8):

    • Verifies all system components required for emergency access
    • Tests both health and all key notification backends
    • Validates file system access for dummy and all key files
    • Ensures complete emergency system readiness for all configured keys
    • Used for regular system verification

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.

Installation

Quick Install

Run the automated installation script as root:

sudo ./install.sh

Manual Installation

  1. 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
    
  2. Create service user:

    sudo groupadd --system emergency-access
    sudo useradd --system --gid emergency-access --home-dir /opt/emergency-access \
                --shell /bin/false emergency-access
    
  3. 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
    
  4. 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
    
  5. 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
    
  6. Install systemd service:

    sudo cp emergency-access.service /etc/systemd/system/
    sudo systemctl daemon-reload
    

Configuration

Main Configuration File

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-f8d9e2a1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8"
  },
  "files": {
    "dummy_file": "/etc/emergency-access/dummy.txt"
  },
  "keys": {
    "backup_key": {
      "route": "/emergency-key-backup-a7f9d2e1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8a1d4b7c0e3f6d9a2b5c8e1f4a7b0d3",
      "file": "/etc/emergency-access/backup-key.txt",
      "backends": ["matrix_sec", "pushover_emergency"],
      "message": "🚨 EMERGENCY: Backup decryption key accessed from server"
    },
    "master_key": {
      "route": "/emergency-key-master-x3k8m9n2p5q7r1t4u6v9w2y5z8b1c4d7e0f3g6h9j2k5l8m1n4o7p0q3r6s9t2u5v8w1x4y7z0a3b6c9d2e5f8",
      "file": "/etc/emergency-access/master-key.txt",
      "backends": ["matrix_sec", "pushover_critical", "slack_emergency"],
      "message": "🚨 CRITICAL: Master decryption key accessed from server"
    },
    "recovery_key": {
      "route": "/emergency-key-recovery-q5w7r8t1u3i6o9p0a2s4d6f8g0h2j4k7l9z1x3c5v7b9n1m3q6w8e0r2t4y6u8i0o2p4a6s8d0f2g4h6j8k0l2z4x6c8v0",
      "file": "/etc/emergency-access/recovery-key.txt",
      "backends": ["matrix_sec", "email_emergency"],
      "message": "🚨 EMERGENCY: Recovery decryption key accessed from server"
    },
    "admin_key": {
      "route": "/emergency-key-admin-z9x7c5v3b1n8m6k4j2h0g9f7d5s3a1p0o9i8u7y6t5r4e3w2q1z0x9c8v7b6n5m4k3j2h1g0f9d8s7a6p5o4i3u2y1t0r9",
      "file": "/etc/emergency-access/admin-key.txt",
      "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
  }
}

Configuration Options

Server Settings

  • host: Bind address (default: 127.0.0.1 for localhost only)
  • port: Listen port (default: 1127)

Route Settings

  • health_route: Path for health checks - must be 100+ characters long to prevent accidental access

Keys Configuration

Each key in the keys object supports:

  • route: Unique random path for this specific key - must be 100+ characters long to prevent accidental access
  • file: Path to the key file for this specific key
  • backends: List of notification backend names for this specific key
  • message: Custom message sent when this specific key is accessed

File Settings

  • dummy_file: Path to dummy content for health checks

Notification Settings

  • health_backends: List of backend names from /etc/emergency-access/ntfy.yml for health check notifications and all application logs
  • config_path: Path to the ntfy configuration file (default: /etc/emergency-access/ntfy.yml)
  • health_message: Message sent for health checks
  • log_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)

Backend Name Examples

  • matrix_sec: Matrix backend for security alerts
  • pushover_emergency: Pushover backend for emergency notifications
  • slack_critical: Slack backend for critical alerts
  • Any backend name configured in /etc/emergency-access/ntfy.yml

Key and Dummy Files

  1. 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
    
  2. 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
    

dschep/ntfy Backend Setup

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.

Configuring Notification Backends

  1. 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
    
  2. 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"
    }
    

Adding Additional Backends

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

Service Management

Start and Enable Service

# Start the service
sudo systemctl start emergency-access

# Enable automatic startup
sudo systemctl enable emergency-access

# Check status
sudo systemctl status emergency-access

Monitoring and Logs

# 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

Usage

Emergency Key Access

# Access backup key
curl https://your-domain.com/emergency-key-backup-a7f9d2e1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8a1d4b7c0e3f6d9a2b5c8e1f4a7b0d3

# 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
curl https://your-domain.com/emergency-key-master-x3k8m9n2p5q7r1t4u6v9w2y5z8b1c4d7e0f3g6h9j2k5l8m1n4o7p0q3r6s9t2u5v8w1x4y7z0a3b6c9d2e5f8

# 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
curl https://your-domain.com/emergency-key-admin-z9x7c5v3b1n8m6k4j2h0g9f7d5s3a1p0o9i8u7y6t5r4e3w2q1z0x9c8v7b6n5m4k3j2h1g0f9d8s7a6p5o4i3u2y1t0r9

# 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"]
}

Health Check

# Regular health monitoring
curl https://your-domain.com/health-check-f8d9e2a1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8

# 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
    }
  }
}

Security Considerations

Caddy Reverse Proxy Setup

  1. 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
           }
       }
    }
    
  2. Path-based routing:

    yourdomain.com {
       handle /emergency/* {
           uri strip_prefix /emergency
           reverse_proxy localhost:1127
       }
    }
    
  3. 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
       }
    }
    

Network Security

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.

File Permissions

  • Key file: 600 (owner read-only)
  • Config file: 640 (owner read/write, group read)
  • Application files: 644 (standard read permissions)

Monitoring

  1. 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
    
  2. Monitor notification delivery:

    • Configure notification backends (Pushover, Pushbullet, etc.)
    • Set up monitoring of notification delivery in your backends
    • Monitor log files for errors
    • All application logs are automatically sent to health backends for real-time monitoring

Troubleshooting

Common Issues

  1. Service won't start:

    sudo journalctl -u emergency-access -n 50
    sudo systemctl status emergency-access
    
  2. 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"
    
  3. File permission errors:

    sudo chown -R emergency-access:emergency-access /opt/emergency-access
    sudo chown emergency-access:emergency-access /etc/emergency-access/*
    

Configuration Validation

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"

Development

Running in Development Mode

# 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

Testing

# Run comprehensive test suite
python test.py

# Run quick configuration tests only
python test.py --quick

# Test specific endpoints (replace with your actual paths)
curl http://localhost:1127/emergency-key-backup-[YOUR_SECURE_PATH]
curl http://localhost:1127/emergency-key-master-[YOUR_SECURE_PATH]
curl http://localhost:1127/health-check-[YOUR_SECURE_PATH]

# Generate new configuration with secure paths
python generate_secure_paths.py --keys 3 --output config

Multiple Key Implementation Details

Path Security

Path Length Requirements

  • Minimum: 100 characters
  • Recommended: 120+ characters
  • Example length: /emergency-key-backup-a7f9d2e1b4c7f3e6d9a2b5c8e1f4d7a0b3c6e9f2a5d8b1c4e7f0a3d6b9c2e5f8a1d4b7c0e3f6d9a2b5c8e1f4a7b0d3 (130 chars)

Why Ultra-Long Paths?

  1. Prevent accidental access: Impossible to guess or stumble upon
  2. Reduce false positives: No accidental emergency notifications
  3. Security through obscurity: Additional layer of protection
  4. URL safety: Only lowercase letters and numbers

Dynamic Route Registration

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'])

Individual Key Handlers

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 Check Validation

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

Generate Secure Configuration

Use the included path generator for cryptographically secure paths:

# Generate new configuration with secure paths
python generate_secure_paths.py --keys 3 --output config

# Generate complete setup including Caddy config and setup scripts
python generate_secure_paths.py --keys 4 --domain your-domain.com --output all

# Generate just secure paths for existing configuration
python generate_secure_paths.py --keys 2 --output paths

The path generator creates:

  • Configuration file: Complete JSON config with secure paths
  • Caddy configuration: Reverse proxy setup with path restrictions
  • Setup script: Automated key file creation with proper permissions
  • Security validation: Ensures all paths meet minimum length requirements

Security Best Practices

Path Storage

  • Store paths in secure password manager
  • Document which path corresponds to which key
  • Never store paths in plain text logs
  • Use the path generator for cryptographically secure random paths

Access Monitoring

  • Monitor reverse proxy logs for path access
  • Set up alerts for any key access
  • Regularly audit notification delivery
  • Implement rate limiting to prevent brute force attempts

Emergency Procedures

  1. Key Compromise: Change the path, not the key content
  2. False Positive: Investigate immediately, check logs
  3. Path Leak: Generate new paths and update configuration
  4. Notification Failure: Validate all backends before deployment

Migration Considerations

This implementation removes legacy single-key support for enhanced security:

Clean Architecture

  • Removed all legacy single-key configuration support
  • Simplified configuration structure with only keys section
  • All paths must be 100+ characters for security
  • Each key requires explicit configuration
  • No backward compatibility to ensure security by default

License

This project is designed for emergency access scenarios. Use responsibly and ensure proper security measures are in place.

Support

For issues and questions:

  1. Check the logs: /var/log/emergency-access.log
  2. Verify configuration: /etc/emergency-access/config.json
  3. Test notification systems independently
  4. Monitor service status: systemctl status emergency-access
  5. Use path generator: python generate_secure_paths.py --help

Validation Commands

# 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 new secure paths
python generate_secure_paths.py --keys 3 --path-length 120