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_hereObtenir 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-runDatabase 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.pemRestreindre Accès :
# postgresql.conf
listen_addresses = 'localhost'
# pg_hba.conf
host all all 127.0.0.1/32 scram-sha-256Password Policy
Symfony Security :
# config/packages/security.yaml
security:
password_hashers:
App\Entity\User:
algorithm: bcrypt
cost: 12Validation :
// 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
*.pemUtiliser Vault (Production) :
# HashiCorp Vault
vault kv put secret/csweb \
POSTGRES_PASSWORD=secure_password \
OAUTH_CLIENT_SECRET=secure_secretDocker Secrets :
# docker-compose.yml
services:
csweb:
secrets:
- postgres_password
secrets:
postgres_password:
file: ./secrets/postgres_password.txtFirewall 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 externeUFW 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 enableAudit 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: 3600Rate 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-dependenciesDocker Image Scanning
# Trivy scanner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image csweb:latestTroubleshooting
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