Guides
Architecture & Déploiement
Sécurité

Sécurité

Meilleures pratiques de sécurité pour CSWeb Community Platform.

⚠️

Production : Ne jamais utiliser les credentials par défaut (admin/admin123). Changer immédiatement après installation.

Authentication OAuth2

Password Grant Flow

Configuration :

# .env
OAUTH_CLIENT_ID=csweb_client
OAUTH_CLIENT_SECRET=your_secret_key_here

Obtenir Token :

curl -X POST http://localhost:8080/api/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "username=admin" \
  -d "password=admin123"

Response :

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Sécuriser Endpoints

// config/packages/security.yaml
security:
    firewalls:
        api:
            pattern: ^/api
            stateless: true
            oauth2: true
 
    access_control:
        - { path: ^/api/admin, roles: ROLE_ADMIN }
        - { path: ^/api, roles: ROLE_USER }

HTTPS Setup

Nginx Reverse Proxy

Configuration Production :

# /etc/nginx/sites-available/csweb
server {
    listen 443 ssl http2;
    server_name csweb.example.com;
 
    ssl_certificate /etc/letsencrypt/live/csweb.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/csweb.example.com/privkey.pem;
 
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
 
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}
 
# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name csweb.example.com;
    return 301 https://$server_name$request_uri;
}

Let's Encrypt SSL

# Installation Certbot
sudo apt install certbot python3-certbot-nginx
 
# Obtenir certificat
sudo certbot --nginx -d csweb.example.com
 
# Auto-renewal
sudo certbot renew --dry-run

Database Security

Connection Sécurisée

PostgreSQL SSL :

# .env
POSTGRES_SSL_MODE=require
POSTGRES_SSL_CERT=/certs/client-cert.pem
POSTGRES_SSL_KEY=/certs/client-key.pem

Restreindre Accès :

# postgresql.conf
listen_addresses = 'localhost'
 
# pg_hba.conf
host    all    all    127.0.0.1/32    scram-sha-256

Password Policy

Symfony Security :

# config/packages/security.yaml
security:
    password_hashers:
        App\Entity\User:
            algorithm: bcrypt
            cost: 12

Validation :

// src/Entity/User.php
/**
 * @Assert\NotCompromisedPassword(
 *     message="This password has been leaked in a data breach."
 * )
 * @Assert\Length(min=8, minMessage="Password must be at least 8 characters")
 */
private $password;

Secrets Management

Variables d'Environnement

Ne JAMAIS commit :

# .gitignore
.env
.env.local
*.key
*.pem

Utiliser Vault (Production) :

# HashiCorp Vault
vault kv put secret/csweb \
  POSTGRES_PASSWORD=secure_password \
  OAUTH_CLIENT_SECRET=secure_secret

Docker Secrets :

# docker-compose.yml
services:
  csweb:
    secrets:
      - postgres_password
 
secrets:
  postgres_password:
    file: ./secrets/postgres_password.txt

Firewall Configuration

Docker Network Isolation

# docker-compose.yml
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true
 
services:
  csweb:
    networks:
      - frontend
      - backend
 
  postgres:
    networks:
      - backend  # Pas d'accès externe

UFW Rules

# Allow HTTPS only
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp  # Redirect to HTTPS
 
# Deny direct access to DB
sudo ufw deny 5432/tcp
sudo ufw deny 3306/tcp
 
sudo ufw enable

Audit Logging

Tracking User Actions

-- Table audit logs
CREATE TABLE audit_logs (
    id SERIAL PRIMARY KEY,
    user_id INT,
    action VARCHAR(50),
    resource VARCHAR(100),
    details JSONB,
    ip_address INET,
    created_at TIMESTAMP DEFAULT NOW()
);
 
-- Exemple
INSERT INTO audit_logs (user_id, action, resource, ip_address)
VALUES (1, 'BREAKOUT_START', 'EVAL_DICT', '192.168.1.100');

Log Failed Login Attempts

// src/Security/LoginFailureHandler.php
class LoginFailureHandler implements AuthenticationFailureHandlerInterface
{
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $this->logger->warning('Failed login attempt', [
            'username' => $request->request->get('username'),
            'ip' => $request->getClientIp(),
        ]);
 
        return new JsonResponse(['error' => 'Invalid credentials'], 401);
    }
}

CORS Configuration

Restrict Origins

// config/packages/nelmio_cors.yaml
nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['^https://csweb\.example\.com$']
        allow_methods: ['GET', 'POST', 'PUT', 'DELETE']
        allow_headers: ['Authorization', 'Content-Type']
        expose_headers: ['X-Total-Count']
        max_age: 3600

Rate Limiting

Prevent Brute Force

# config/packages/rate_limiter.yaml
framework:
    rate_limiter:
        login:
            policy: 'sliding_window'
            limit: 5
            interval: '15 minutes'
// src/Controller/AuthController.php
#[RateLimiter('login')]
public function login(Request $request): JsonResponse
{
    // Login logic
}

Security Headers

Nginx Headers

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;

Checklist Production

Avant Déploiement :

  • Changer credentials admin par défaut
  • Configurer HTTPS avec certificat valide
  • Activer SSL pour connexions DB
  • Configurer firewall (UFW/iptables)
  • Isoler DB dans réseau privé
  • Utiliser Docker secrets pour passwords
  • Activer audit logging
  • Configurer rate limiting
  • Ajouter security headers
  • Restreindre CORS origins
  • Configurer backup chiffré
  • Désactiver debug mode (APP_ENV=prod)

Vulnerability Scanning

Composer Security Checker

# Check dependencies
composer audit
 
# Auto-update security fixes
composer update --with-all-dependencies

Docker Image Scanning

# Trivy scanner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image csweb:latest

Troubleshooting

HTTPS Redirect Loop

Cause : Nginx proxy headers mal configurés.

Solution :

proxy_set_header X-Forwarded-Proto $scheme;

OAuth Token Invalid

Cause : Token expiré ou secret incorrect.

Solution :

# Vérifier expiration
echo $TOKEN | base64 -d | jq '.exp'
 
# Regénérer token
curl -X POST http://localhost:8080/api/token ...

Database Connection Refused

Cause : SSL requis mais non configuré.

Solution :

# .env
POSTGRES_SSL_MODE=disable  # Dev only

Ressources