Preskočiť na obsah

Hardening

Bezpečnostné odporúčania a checklist pre produkčné nasadenie GitPulse.

Systémový hardening

Operačný systém

Bash
# Ubuntu/Debian hardening

# 1. Aktualizácia systému
sudo apt update && sudo apt upgrade -y

# 2. Automatické security updates
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

# 3. Disable root SSH login
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart sshd

# 4. SSH key-only auth
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

# 5. Firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp   # SSH
sudo ufw allow 80/tcp   # HTTP
sudo ufw allow 443/tcp  # HTTPS
sudo ufw enable

# 6. Fail2ban
sudo apt install fail2ban
sudo systemctl enable fail2ban

Firewall pravidlá

Bash
1
2
3
4
5
6
7
8
9
# /etc/ufw/applications.d/gitpulse
[GitPulse]
title=GitPulse
description=GitPulse web application
ports=80,443/tcp

# Aplikovať
sudo ufw app update GitPulse
sudo ufw allow GitPulse

Docker hardening

Dockerfile best practices

Docker
# Dockerfile
# 1. Použiť slim base image
FROM python:3.12-slim AS base

# 2. Non-root user
RUN groupadd -r app && useradd -r -g app app

# 3. Minimálne závislosti
RUN apt-get update && apt-get install -y --no-install-recommends \
    libpq5 \
    && rm -rf /var/lib/apt/lists/*

# 4. Copy len potrebné súbory
COPY --chown=app:app requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY --chown=app:app src/ ./src/

# 5. Switch to non-root
USER app

# 6. Read-only filesystem (ak možné)
# V docker-compose: read_only: true

# 7. No new privileges
# V docker-compose: security_opt: ["no-new-privileges:true"]

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Docker Compose security

YAML
# docker-compose.yml
services:
  api:
    image: gitpulse-api:latest
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE  # Ak potrebné
    tmpfs:
      - /tmp
    user: "1000:1000"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G

Docker daemon

JSON
// /etc/docker/daemon.json
{
  "icc": false,
  "userns-remap": "default",
  "no-new-privileges": true,
  "live-restore": true,
  "userland-proxy": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Databáza hardening

PostgreSQL

SQL
-- 1. Silné heslo
ALTER USER gitpulse PASSWORD 'VeryStrongPassword123!';

-- 2. Obmedzené oprávnenia pre aplikáciu
CREATE ROLE app_user WITH LOGIN PASSWORD 'AppPassword123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
REVOKE CREATE ON SCHEMA public FROM app_user;

-- 3. Read-only user pre reporting
CREATE ROLE report_user WITH LOGIN PASSWORD 'ReportPassword123!';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO report_user;

-- 4. SSL povinné
ALTER SYSTEM SET ssl = 'on';
ALTER SYSTEM SET ssl_cert_file = '/etc/ssl/certs/server.crt';
ALTER SYSTEM SET ssl_key_file = '/etc/ssl/private/server.key';
Bash
# pg_hba.conf - len SSL spojenia
hostssl all all 0.0.0.0/0 scram-sha-256

Redis

Bash
# redis.conf
# 1. Heslo
requirepass VeryStrongRedisPassword123!

# 2. Disable dangerous commands
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG ""

# 3. Bind len na localhost
bind 127.0.0.1

# 4. TLS
tls-port 6379
port 0
tls-cert-file /etc/ssl/redis.crt
tls-key-file /etc/ssl/redis.key

Aplikačný hardening

Environment variables

Bash
1
2
3
4
5
6
# Nikdy v kóde!
# Správne
DATABASE_URL=${DATABASE_URL}

# Zle
DATABASE_URL="postgresql://user:password@host/db"

Secrets management

YAML
# docker-compose.yml s Docker secrets
services:
  api:
    secrets:
      - db_password
      - gitlab_token
      - secret_key
    environment:
      DATABASE_PASSWORD_FILE: /run/secrets/db_password
      GITLAB_TOKEN_FILE: /run/secrets/gitlab_token
      SECRET_KEY_FILE: /run/secrets/secret_key

secrets:
  db_password:
    file: ./secrets/db_password.txt
  gitlab_token:
    file: ./secrets/gitlab_token.txt
  secret_key:
    file: ./secrets/secret_key.txt
Python
# Načítanie secrets
import os
from pathlib import Path

def get_secret(name: str) -> str:
    """Load secret from file or environment."""
    file_path = os.environ.get(f"{name.upper()}_FILE")
    if file_path and Path(file_path).exists():
        return Path(file_path).read_text().strip()
    return os.environ.get(name.upper(), "")

Security headers

Python
# src/app/middleware/security.py
SECURITY_HEADERS = {
    "X-Content-Type-Options": "nosniff",
    "X-Frame-Options": "DENY",
    "X-XSS-Protection": "1; mode=block",
    "Referrer-Policy": "strict-origin-when-cross-origin",
    "Permissions-Policy": "geolocation=(), microphone=(), camera=()",
    "Content-Security-Policy": (
        "default-src 'self'; "
        "script-src 'self'; "
        "style-src 'self' 'unsafe-inline'; "
        "img-src 'self' data:; "
        "font-src 'self'; "
        "frame-ancestors 'none'"
    ),
}

TLS hardening

Caddy konfigurácia

Text Only
# Caddyfile
{
    # Zakázať admin API v produkcii
    admin off

    # OCSP stapling
    ocsp_stapling on
}

gitpulse.kpi.fei.tuke.sk {
    # Len TLS 1.2+
    tls {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    }

    # Security headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "strict-origin-when-cross-origin"
        -Server
    }

    # Rate limiting
    rate_limit {
        zone api {
            key {remote_host}
            events 100
            window 1m
        }
    }

    reverse_proxy api:8000
}

Logging a monitoring

Audit logging

Python
# Všetky security-relevantné udalosti
AUDIT_EVENTS = [
    "login_success",
    "login_failure",
    "logout",
    "password_change",
    "permission_denied",
    "resource_access",
    "admin_action",
    "api_key_created",
    "api_key_revoked",
]

async def log_security_event(
    event_type: str,
    user_id: str | None,
    details: dict,
    severity: str = "info"
):
    """Log security event."""
    logger.log(
        logging.INFO if severity == "info" else logging.WARNING,
        f"SECURITY_EVENT: {event_type}",
        extra={
            "event_type": event_type,
            "user_id": user_id,
            "timestamp": datetime.utcnow().isoformat(),
            "details": details,
            "severity": severity,
        }
    )

Security monitoring

YAML
# Prometheus alerts
groups:
  - name: security
    rules:
      - alert: MultipleLoginFailures
        expr: rate(login_failures_total[5m]) > 10
        labels:
          severity: warning
        annotations:
          summary: "Multiple login failures detected"

      - alert: PermissionDenied
        expr: rate(permission_denied_total[5m]) > 5
        labels:
          severity: warning
        annotations:
          summary: "Multiple permission denied events"

      - alert: UnusualAdminActivity
        expr: rate(admin_actions_total[1h]) > 50
        labels:
          severity: warning
        annotations:
          summary: "Unusual admin activity"

Security Checklist

Pre-deployment

  • Všetky default heslá zmenené
  • SECRET_KEY je unikátny a silný (min. 32 bytes)
  • DEBUG=false v produkcii
  • HTTPS enforced (HSTS)
  • Security headers nakonfigurované
  • Rate limiting aktívny
  • Input validation na všetkých endpointoch
  • SQL injection ochrana (ORM/parameterized queries)
  • XSS ochrana (CSP, output encoding)
  • CSRF ochrana
  • Audit logging aktívny

Infrastructure

  • Firewall nakonfigurovaný
  • SSH hardened (key-only, no root)
  • Automatické security updates
  • Docker running as non-root
  • Minimal container privileges
  • Database SSL enabled
  • Redis password protected
  • Secrets nie sú v Git

Operational

  • Zálohy šifrované
  • Log retention policy
  • Incident response plán
  • Security monitoring aktívny
  • Vulnerability scanning
  • Penetration testing (ročne)

Vulnerability Management

Dependency scanning

Bash
1
2
3
4
5
6
7
8
9
# Python dependencies
pip install safety
safety check

# Docker image scanning
docker scout cves gitpulse-api:latest

# Trivy scanner
trivy image gitpulse-api:latest

Pravidelné úlohy

Úloha Frekvencia
Dependency updates Týždenne
Security patches Ihneď
Vulnerability scan Týždenne
Penetration test Ročne
Access review Štvrťročne
Key rotation Štvrťročne

Ďalšie čítanie