Passa al contenuto principale

Architettura di Sicurezza

Emblema implementa un'architettura di sicurezza multi-layer basata su standard enterprise, con autenticazione centralizzata via Keycloak, autorizzazione granulare RBAC, e cifratura end-to-end per proteggere dati sensibili e operazioni AI.

Panoramica Sicurezza

Loading diagram...

Livelli di Sicurezza

1. Perimeter Security

Traefik Reverse Proxy fornisce il primo livello di protezione:

# Configurazione sicurezza perimetrale
traefik:
command:
- --log.level=INFO
- --accesslog=true
- --metrics.prometheus=true
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.websecure.http.tls.options=default@file
labels:
# Middleware sicurezza applicati automaticamente
- "traefik.http.middlewares.security.headers.frameDeny=true"
- "traefik.http.middlewares.security.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security.headers.browserXssFilter=true"
- "traefik.http.middlewares.security.headers.forceSTSHeader=true"
- "traefik.http.middlewares.security.headers.stsSeconds=31536000"

Rate Limiting per prevenire attacchi DDoS:

# config/traefik/dynamic/rate-limit.yml
http:
middlewares:
api-rate-limit:
rateLimit:
burst: 100
average: 50
period: 1m
auth-rate-limit:
rateLimit:
burst: 10
average: 5
period: 1m

2. Network Security

Segmentazione di Rete tramite Docker networks:

networks:
emblema:
external: true
ipam:
config:
- subnet: 172.18.0.0/16
redis-net:
internal: true # Rete privata per Redis cluster
ipam:
config:
- subnet: 172.19.0.0/16

Firewall Rules a livello container:

# Esempio isolamento servizi sensibili
database-services:
networks:
- emblema
labels:
- "traefik.enable=false" # Non esposti pubblicamente
ports: [] # Nessuna porta host

Autenticazione (Authentication)

Keycloak Identity Provider

Emblema utilizza Keycloak 26.2 come Identity Provider centralizzato:

keycloak:
image: quay.io/keycloak/keycloak:26.2
environment:
KC_HOSTNAME: ${KEYCLOAK_HOSTNAME}
KC_HTTP_ENABLED: true
KC_HOSTNAME_STRICT_HTTPS: false
KC_PROXY_HEADERS: "xforwarded"
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres-keycloak/keycloak_db

Realm Configuration

{
"realm": "emblema",
"enabled": true,
"clients": [
{
"clientId": "web_client",
"name": "Emblema Web",
"enabled": true,
"clientAuthenticatorType": "client-secret",
"secret": "${EMBLEMA_WEB_AUTH_KEYCLOAK_SECRET}",
"redirectUris": [
"https://${EMBLEMA_WEB_HOSTNAME}/api/auth/callback/keycloak"
],
"standardFlowEnabled": true,
"serviceAccountsEnabled": true,
"authorizationServicesEnabled": true,
"protocol": "openid-connect"
}
]
}

OpenID Connect Flow

Loading diagram...

JWT Token Management

// Configurazione NextAuth con Keycloak
export const authOptions: NextAuthOptions = {
providers: [
KeycloakProvider({
clientId: process.env.AUTH_KEYCLOAK_ID!,
clientSecret: process.env.AUTH_KEYCLOAK_SECRET!,
issuer: process.env.AUTH_KEYCLOAK_ISSUER,
}),
],
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token;
token.refreshToken = account.refresh_token;
token.expiresAt = account.expires_at;
}
return token;
},
async session({ session, token }) {
session.accessToken = token.accessToken;
session.groups = token.groups || [];
return session;
},
},
};

Autorizzazione (Authorization)

Role-Based Access Control (RBAC)

Emblema implementa un sistema RBAC granulare con tre livelli:

1. Group-Level Authorization

// Middleware controllo gruppi autorizzati
const authGroupMiddleware: NextMiddleware = async (req) => {
const session = await auth();

if (session && !hasAuthorizedGroups(session.groups)) {
return NextResponse.redirect(new URL("/unauthorized", req.url));
}
};

// Validazione gruppi
export const hasAuthorizedGroups = (groups: string[]): boolean => {
const authorizedGroups = ["emblema-users", "emblema-admin"];
return groups.some((group) => authorizedGroups.includes(group));
};

2. Entity-Level Permissions

// Sistema permessi per tipo di entità
export enum EntityType {
Meeting = "Meeting",
KnowledgeBase = "KnowledgeBase",
File = "File",
Document = "Document",
Chunk = "Chunk",
EntityPermission = "EntityPermission",
RecordPermission = "RecordPermission",
}

// Controllo permessi per tipo entità
export const hasEntityTypePermission = async ({
userId,
entityType,
create,
read,
update,
delete: deletePermission,
}: {
userId: string;
entityType: EntityType;
create?: boolean;
read?: boolean;
update?: boolean;
delete?: boolean;
}) => {
const entityPermission = await entityPermissionHandler.get({
userId,
entityType,
});

if (!entityPermission) return false;

// Verifica ogni permesso richiesto
for (const permission of Object.keys(permissions)) {
if (!entityPermission[permission as keyof EntityPermission]) {
return false;
}
}

return true;
};

3. Record-Level Permissions

// Permessi granulari per singoli record
export const hasRecordPermission = async ({
userId,
entityId,
entityType,
...permissions
}: {
userId: string;
entityId: string;
entityType?: EntityType;
create?: boolean;
read?: boolean;
update?: boolean;
delete?: boolean;
}) => {
const recordPermission = await recordPermissionHandler.get({
userId,
parentId: entityId,
});

// Controllo ownership se no permessi espliciti
if (!recordPermission) {
const data = await getDataHandler(entityType).get(entityId);
return data?.createdBy === userId;
}

return checkPermissions(recordPermission, permissions);
};

Permission Matrix

RisorsaCreateReadUpdateDeleteNote
FileUserOwner/SharedOwnerOwnerUpload documenti
DocumentAutoOwner/SharedOwnerOwnerPost-elaborazione
KnowledgeBaseUserOwner/SharedOwnerOwnerCollezioni documenti
MeetingUserOwner/SharedOwnerOwnerTrascrizioni audio
ChunkSystemOwner/SharedOwnerSystemContenuti vettoriali
EntityPermissionAdminAdminAdminAdminGestione permessi

API Route Protection

// Pattern protezione API route
export async function GET(
request: Request,
{ params }: { params: { entityId: string } },
) {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

// Verifica permessi specifici
const { hasPermission, data } = await checkUserEntityPermission({
entityType: EntityType.Document,
entityId: params.entityId,
userId: session.user.id,
permissions: { read: true },
});

if (!hasPermission) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}

return NextResponse.json(data);
}

Crittografia e Protezione Dati

Transport Layer Security (TLS)

Terminazione TLS centralizzata su Traefik:

# Configurazione TLS sicura
tls:
options:
default:
minVersion: "VersionTLS12"
cipherSuites:
- "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
- "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
curvePreferences:
- "CurveP521"
- "CurveP384"

HTTP Security Headers:

http:
middlewares:
security:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
forceSTSHeader: true
stsSeconds: 31536000
stsIncludeSubdomains: true
contentSecurityPolicy: |
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' wss: https:;

Data Encryption at Rest

Database Encryption:

# PostgreSQL con TLS e encryption
postgres-vector:
environment:
POSTGRES_DB_ENCRYPTION: "on"
POSTGRES_SSL_MODE: "require"
command: |
postgres
-c ssl=on
-c ssl_cert_file=/etc/ssl/certs/server-cert.pem
-c ssl_key_file=/etc/ssl/private/server-key.pem

MinIO Object Storage:

minio:
environment:
MINIO_SERVER_SIDE_ENCRYPTION: "on"
MINIO_KMS_SECRET_KEY: "${MINIO_KMS_SECRET_KEY}"
command: |
server /data
--console-address ":9090"
--certs-dir /root/.minio/certs

Secrets Management

Environment-based Secrets:

# Pattern sicurezza per secrets
# Mai hardcoded nei file di configurazione

# Database passwords
POSTGRES_PASSWORD=secure_random_string_32_chars
REDIS_MASTER_PASSWORD=secure_random_string_32_chars

# JWT secrets
AUTH_SECRET=base64_encoded_secret_key
KEYCLOAK_ADMIN_PASSWORD=secure_admin_password

# API keys
LITELLM_MASTER_KEY=secure_api_key
HASURA_ADMIN_SECRET=secure_graphql_secret

# Encryption keys
MINIO_KMS_SECRET_KEY=32_byte_encryption_key

Secrets Rotation Policy:

# Automated secrets rotation (future implementation)
secrets-rotation:
schedule: "0 2 * * 0" # Weekly on Sunday 2 AM
targets:
- postgres_password
- redis_password
- jwt_secret
- api_keys

Network Security & CORS

CORS Configuration

# config/traefik/dynamic/cors.yml
http:
middlewares:
cors:
headers:
accessControlAllowOriginList:
- "https://${EMBLEMA_WEB_HOSTNAME}"
- "https://${DOCS_HOSTNAME}"
- "https://${KEYCLOAK_HOSTNAME}"
accessControlAllowMethods:
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "OPTIONS"
accessControlAllowHeaders:
- "Content-Type"
- "Authorization"
- "X-Requested-With"
accessControlAllowCredentials: true
accessControlMaxAge: 86400

Content Security Policy

// CSP header per prevenire XSS
const cspHeader = `
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval' ${KEYCLOAK_HOSTNAME};
style-src 'self' 'unsafe-inline';
img-src 'self' data: https: blob:;
font-src 'self' data:;
connect-src 'self' ${HASURA_HOSTNAME} ${KEYCLOAK_HOSTNAME} wss:;
media-src 'self' blob:;
worker-src 'self' blob:;
child-src 'self';
frame-ancestors 'none';
form-action 'self';
upgrade-insecure-requests;
`;

Audit e Compliance

Security Logging

# Logging strutturato per audit
x-logging: &security-logging
driver: "json-file"
options:
max-size: "100m"
max-file: "10"
labels: "service,security_event,user_id,timestamp"

# Pattern log eventi sicurezza
services:
www-emblema:
logging: *security-logging
environment:
LOG_LEVEL: "info"
SECURITY_LOG_ENABLED: "true"

Security Event Types:

  • Authentication Events: Login, logout, token refresh
  • Authorization Events: Permission denied, role changes
  • Data Access: CRUD operations on sensitive data
  • Administrative Actions: User management, permission changes
  • Security Violations: Failed auth attempts, suspicious activity

Compliance Requirements

// GDPR compliance helpers
export const logDataAccess = async ({
userId,
entityType,
entityId,
action,
ipAddress,
}: {
userId: string;
entityType: EntityType;
entityId: string;
action: "create" | "read" | "update" | "delete";
ipAddress: string;
}) => {
await auditLogHandler.create({
userId,
entityType,
entityId,
action,
ipAddress,
timestamp: new Date(),
userAgent: request.headers.get("user-agent"),
});
};

Security Monitoring

Intrusion Detection

# Fail2Ban-like protection via Traefik
http:
middlewares:
auth-protection:
rateLimit:
burst: 5
average: 1
period: 60s
sourceCriterion:
ipStrategy:
depth: 1

Security Metrics

// Metriche sicurezza per Prometheus
const securityMetrics = {
auth_attempts_total: "Counter for authentication attempts",
auth_failures_total: "Counter for authentication failures",
permission_denials_total: "Counter for authorization denials",
suspicious_activity_total: "Counter for suspicious activity",
active_sessions_gauge: "Gauge for currently active sessions",
};

Health Checks Security

# Health check che non espongono info sensibili
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Non includere dettagli interni nella risposta

Security Best Practices

Development Security

  1. Secure Coding Standards:

    • Input validation e sanitization
    • SQL injection prevention
    • XSS protection
    • CSRF tokens
  2. Dependency Security:

    # Scan dipendenze vulnerabilità
    pnpm audit
    docker scout cves
  3. Container Security:

    # Utenti non-privilegiati
    RUN adduser --system --uid 1001 appuser
    USER appuser

    # Filesystem read-only
    RUN chmod -R 755 /app && chown -R appuser:appgroup /app

Operational Security

  1. Regular Updates: Aggiornamenti automatici sicurezza
  2. Backup Encryption: Backup cifrati e testati
  3. Incident Response: Procedure risposta incidenti
  4. Penetration Testing: Test penetrazione periodici

Air-Gap Deployment

Per ambienti air-gapped:

# Configurazione offline-first
services:
emblema-services:
environment:
HF_HUB_OFFLINE: "1"
TRANSFORMERS_OFFLINE: "1"
CERT_RESOLVER: "" # Custom certificates only
volumes:
- ./models:/models:ro # Pre-cached AI models
- ./certs:/certs:ro # Custom SSL certificates

Security Incident Response

Incident Types

  1. Authentication Bypass
  2. Privilege Escalation
  3. Data Breach
  4. Service Compromise
  5. DDoS Attack

Response Procedures

# Emergency response commands
docker compose logs --since=1h | grep -i "error\|fail\|unauthorized"
docker compose exec www-emblema sh -c "tail -f /var/log/security.log"

# Isolate compromised service
docker compose stop suspected-service

# Rotate secrets immediately
./scripts/rotate-secrets.sh --emergency

# Enable enhanced logging
export LOG_LEVEL=debug
docker compose restart

Riferimenti

Prossimi Passi

Questa pagina ti è stata utile?