@company-manager/docs
Deployment

Sécurité

Guide de sécurité pour le déploiement de Company Manager.

Sécurité

Guide complet des mesures de sécurité pour le déploiement de Company Manager.

Configuration de Base

HTTPS

# Configuration Nginx SSL
server {
    listen 443 ssl http2;
    server_name app.company-manager.com;

    ssl_certificate /etc/letsencrypt/live/app.company-manager.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.company-manager.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;
}

Headers de Sécurité

// Configuration des headers
const securityHeaders = {
  'Content-Security-Policy': `
    default-src 'self';
    script-src 'self' 'unsafe-inline' 'unsafe-eval';
    style-src 'self' 'unsafe-inline';
    img-src 'self' data: https:;
  `,
  'X-Frame-Options': 'DENY',
  'X-Content-Type-Options': 'nosniff',
  'Referrer-Policy': 'strict-origin-when-cross-origin',
  'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
};

Authentification

Configuration JWT

// Configuration des tokens
const jwtConfig = {
  secret: process.env.JWT_SECRET,
  expiresIn: '1d',
  algorithm: 'HS256',
  issuer: 'company-manager',
};

// Validation des tokens
const validateToken = async (token: string) => {
  try {
    const decoded = jwt.verify(token, jwtConfig.secret, {
      algorithms: [jwtConfig.algorithm],
      issuer: jwtConfig.issuer,
    });
    return decoded;
  } catch (error) {
    throw new TokenValidationError(error.message);
  }
};

Rate Limiting

// Configuration du rate limiting
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limite par IP
  message: 'Trop de requêtes, veuillez réessayer plus tard.',
  standardHeaders: true,
  legacyHeaders: false,
});

Base de Données

Chiffrement des Données

// Service de chiffrement
class EncryptionService {
  private readonly algorithm = 'aes-256-gcm';
  private readonly key = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex');

  encrypt(text: string): EncryptedData {
    const iv = crypto.randomBytes(12);
    const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
    
    const encrypted = Buffer.concat([
      cipher.update(text, 'utf8'),
      cipher.final(),
    ]);
    
    const tag = cipher.getAuthTag();
    
    return {
      encrypted: encrypted.toString('hex'),
      iv: iv.toString('hex'),
      tag: tag.toString('hex'),
    };
  }

  decrypt(data: EncryptedData): string {
    const decipher = crypto.createDecipheriv(
      this.algorithm,
      this.key,
      Buffer.from(data.iv, 'hex')
    );
    
    decipher.setAuthTag(Buffer.from(data.tag, 'hex'));
    
    return Buffer.concat([
      decipher.update(Buffer.from(data.encrypted, 'hex')),
      decipher.final(),
    ]).toString('utf8');
  }
}

Sécurité PostgreSQL

-- Configuration PostgreSQL
ALTER SYSTEM SET ssl = on;
ALTER SYSTEM SET ssl_cert_file = 'server.crt';
ALTER SYSTEM SET ssl_key_file = 'server.key';

-- Permissions restrictives
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;

Monitoring de Sécurité

Logs de Sécurité

// Configuration des logs de sécurité
const securityLogger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'security' },
  transports: [
    new winston.transports.File({
      filename: 'logs/security.log',
      level: 'info',
    }),
  ],
});

// Logging des événements de sécurité
const logSecurityEvent = (
  event: string,
  details: Record<string, unknown>
) => {
  securityLogger.info(event, {
    timestamp: new Date().toISOString(),
    ...details,
  });
};

Alertes

// Service d'alertes
class SecurityAlertService {
  async sendAlert(
    level: 'high' | 'medium' | 'low',
    message: string,
    details: any
  ) {
    await prisma.securityAlert.create({
      data: {
        level,
        message,
        details,
        timestamp: new Date(),
      },
    });

    if (level === 'high') {
      await this.notifySecurityTeam(message, details);
    }
  }

  private async notifySecurityTeam(
    message: string,
    details: any
  ) {
    // Notification par email, Slack, etc.
  }
}

Protection des Données

Masquage des Données Sensibles

// Middleware de masquage
const maskSensitiveData = (data: any): any => {
  const sensitiveFields = ['password', 'credit_card', 'ssn'];
  
  return Object.entries(data).reduce(
    (acc, [key, value]) => ({
      ...acc,
      [key]: sensitiveFields.includes(key)
        ? '********'
        : value,
    }),
    {}
  );
};

Audit Trail

// Service d'audit
class AuditService {
  async logAction(
    userId: string,
    action: string,
    resource: string,
    details: any
  ) {
    await prisma.auditLog.create({
      data: {
        userId,
        action,
        resource,
        details,
        ipAddress: getCurrentIp(),
        userAgent: getCurrentUserAgent(),
        timestamp: new Date(),
      },
    });
  }

  async getAuditTrail(
    filters: AuditFilters
  ): Promise<AuditLog[]> {
    return prisma.auditLog.findMany({
      where: filters,
      orderBy: { timestamp: 'desc' },
    });
  }
}

Bonnes Pratiques

Gestion des Secrets

// Service de gestion des secrets
class SecretManager {
  private readonly vault: Vault;

  constructor() {
    this.vault = new Vault({
      token: process.env.VAULT_TOKEN,
      endpoint: process.env.VAULT_URL,
    });
  }

  async getSecret(path: string): Promise<string> {
    const { data } = await this.vault.read(`secret/data/${path}`);
    return data.data;
  }

  async rotateSecret(path: string): Promise<void> {
    const newSecret = crypto.randomBytes(32).toString('hex');
    await this.vault.write(`secret/data/${path}`, {
      data: { value: newSecret },
    });
  }
}

Sécurité des Dépendances

# Audit des dépendances
bun audit

# Mise à jour des dépendances vulnérables
bun update --security

# Vérification des licences
npx license-checker --summary

Tests de Sécurité

Tests Automatisés

// Tests de sécurité
describe('Security', () => {
  it('should hash passwords correctly', async () => {
    const password = 'test123';
    const hash = await hashPassword(password);
    
    expect(hash).not.toBe(password);
    expect(await verifyPassword(password, hash)).toBe(true);
  });

  it('should prevent SQL injection', async () => {
    const maliciousInput = "'; DROP TABLE users; --";
    
    await expect(
      userService.findByName(maliciousInput)
    ).rejects.toThrow();
  });
});

Scan de Vulnérabilités

# GitHub Actions security scan
name: Security Scan
on: [push, pull_request]
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run OWASP ZAP scan
        uses: zaproxy/action-full-scan@v0.4.0
      - name: Run Snyk scan
        uses: snyk/actions/node@master