Aller au contenu principal

Configuration de sécurité

English: en/configuration.md

Source : services/control-plane/src/eai/config.py (préfixe EAI_, listes séparées par des virgules ou en JSON). La configuration générale est décrite dans operations/configuration.md.

Réglages EAI_*​

RéglageDéfautRecommandation production
EAI_ENVIRONMENTdevprod (active la garde de démarrage)
EAI_AUTH_DEVfalsefalse (obligatoire)
EAI_AUTH_SPIFFEfalsetrue derrière un proxy de confiance
EAI_CORS_ORIGINSvideorigines exactes du portail, jamais *
EAI_ALLOWED_HOSTS*noms publics de l'API
EAI_TRUSTED_PROXIES127.0.0.1/32,::1/128CIDR des pods de la passerelle (ex. 10.42.0.0/16), jamais 0.0.0.0/0
EAI_DOCS_ENABLEDtruefalse
EAI_SECURITY_HEADERS_ENABLEDtruetrue
EAI_HSTS_ENABLEDfalsetrue
EAI_HSTS_MAX_AGE_SECONDS3153600031536000
EAI_MAX_BODY_BYTES10485760 (10 Mio)10485760
EAI_MAX_UPLOAD_BYTES104857600 (100 Mio)selon l'usage
EAI_MAX_JSON_DEPTH6464
EAI_RATE_LIMIT_ENABLEDtruetrue
EAI_RATE_LIMIT_PER_MINUTE1200à ajuster, voir runbooks.md
EAI_RATE_LIMIT_GATEWAY_PER_MINUTE600à ajuster
EAI_RATE_LIMIT_AUTH_FAILURES_PER_MINUTE2020 ou moins
EAI_REDIS_URLvide (compteurs en mémoire)rediss:// dès plusieurs réplicas, stocké dans OpenBao
EAI_JWT_ALGORITHMSRS256,RS384,RS512,PS256,PS384,ES256,ES384RS256,PS256,ES256 ; jamais HS* ni none
EAI_JWT_LEEWAY_SECONDS3030
EAI_EGRESS_PRIVATE_ALLOWLISTvideservices internes exacts hôte:port
EAI_EGRESS_ALLOWED_PORTS80,443,8443443
EAI_EGRESS_ALLOW_HTTPfalsefalse (obligatoire)
EAI_EGRESS_DNS_TIMEOUT_SECONDS3.03.0
EAI_PROMPT_INJECTION_DEFAULT_MODEdetectblock
EAI_MASTER_KEY / EAI_OPENBAO_URLvidel'un des deux est obligatoire ; OpenBao recommandé
EAI_DATABASE_URLlocalsslmode=verify-full avec CA

Garde de démarrage en production​

eai.security.startup.enforce appelle problems(settings) et refuse de démarrer quand EAI_ENVIRONMENT=prod en listant chaque problème (en staging, il avertit). Il refuse :

  • EAI_AUTH_DEV activé ;
  • * dans EAI_CORS_ORIGINS ou EAI_ALLOWED_HOSTS ;
  • EAI_EGRESS_ALLOW_HTTP activé ;
  • un réseau trop large dans EAI_TRUSTED_PROXIES ;
  • un algorithme symétrique ou none dans EAI_JWT_ALGORITHMS (symmetric_algorithms) ;
  • ni EAI_MASTER_KEY ni EAI_OPENBAO_URL ;
  • EAI_DOCS_ENABLED activé, EAI_HSTS_ENABLED désactivé ;
  • EAI_DATABASE_URL sans sslmode=require, verify-ca ou verify-full (database_tls) ;
  • EAI_LIVEKIT_URL défini avec EAI_LIVEKIT_API_KEY / EAI_LIVEKIT_API_SECRET absents, égaux aux valeurs du serveur LiveKit de développement (devkey / secret) ou avec un secret de moins de 32 octets. Hors dev et test, la création d'une session temps réel est alors refusée (503 livekit_not_configured ou livekit_secret_weak).

Tests : test_security_http.py::test_startup_guard_refuses_each_unsafe_prod_setting, test_security_http.py::test_startup_guard_lists_every_problem_and_warns_in_staging.

Réglages de sécurité par tenant​

eai.security.tenant_settings (defaults, merge, load, validate) :

CléDéfautValeurs
prompt_injection_modeEAI_PROMPT_INJECTION_DEFAULT_MODEoff, detect, block
untrusted_content_wrappingtruebooléen
output_linksstrip_untrustedallow, strip_untrusted
output_link_allowlist[]noms d'hôtes publics (*.suffixe admis), 200 au plus
egress_allowed_hosts[]noms d'hôtes publics ; s'il est non vide, la sortie du tenant est restreinte à cette liste

API : GET /v1/security/settings et PUT /v1/security/settings (rôles tenant_admin ou security_officer, modification auditée). Tests : test_security_api.py::test_settings_get_put_persist_and_audit, test_security_api.py::test_settings_validation, test_security_api.py::test_settings_roles, test_security_tenant_settings.py::test_validate_rejects_bad_values.

API de posture​

GET /v1/security/posture (rôles security_officer ou tenant_admin) renvoie les protections actives (eai.domains.security.posture.protections), les contrôles (checks) et un résumé (summary). Identifiants des contrôles : auth_dev_disabled, cors_restricted, allowed_hosts_restricted, hsts_enabled, docs_disabled, secrets_backend, oidc_configured, egress_http_disabled, egress_private_allowlist_narrow, rate_limit_enabled, trusted_proxies_restricted, spiffe_behind_proxy, database_tls, jwt_algorithms_asymmetric, prompt_injection_enabled. Tests : test_security_api.py::test_posture_roles_and_shape, test_security_api.py::test_posture_check_logic. Contrat : control-plane-v1.md.

Clés Helm (deploy/helm/enterprise-ai/values-prod.yaml)​

  • global.environment: prod, global.networkPolicy: cilium, global.secretsMode: external-secrets.
  • controlPlane.config : EAI_ENVIRONMENT, EAI_AUTH_DEV, EAI_AUTH_SPIFFE, EAI_ALLOWED_HOSTS, EAI_TRUSTED_PROXIES, EAI_DOCS_ENABLED, EAI_HSTS_ENABLED, EAI_MAX_BODY_BYTES, EAI_MAX_UPLOAD_BYTES, EAI_RATE_LIMIT_ENABLED, EAI_JWT_ALGORITHMS, EAI_EGRESS_PRIVATE_ALLOWLIST, EAI_EGRESS_ALLOWED_PORTS, EAI_EGRESS_ALLOW_HTTP, EAI_PROMPT_INJECTION_DEFAULT_MODE, URL TLS des services de données.
  • controlPlane.secrets.keys : valeurs sensibles lues dans OpenBao (EAI_DATABASE_URL, EAI_REDIS_URL, EAI_MASTER_KEY, ...).
  • controlPlane.secretFormats : formats exigés (EAI_REDIS_URL en ^rediss://, EAI_DATABASE_URL avec sslmode=verify-full, EAI_NATS_URL en ^tls://).

Tests : test_platform_security_manifests.py::test_prod_security_settings, test_platform_security_manifests.py::test_prod_configmap_renders_security_settings.

Réglages d'identité, de politique et de clés​

Défauts relevés dans services/control-plane/src/eai/config.py.

RéglageDéfautRecommandation production
EAI_OIDC_ISSUER / EAI_OIDC_AUDIENCEvideémetteur du realm Keycloak ; audience du client (rend aud obligatoire)
EAI_OIDC_JWKS_URLvide (découverte depuis l'émetteur)vide sauf JWKS servi ailleurs
EAI_OIDC_GROUP_SYNCtruetrue (correspondances de groupes appliquées à chaque connexion)
EAI_OIDC_PLATFORM_ADMIN_GROUPSnavin-platform-adminsgroupe d'annuaire restreint
EAI_OIDC_TENANT_ADMIN_GROUP_PREFIXnavin-admins-préfixe réservé aux administrateurs
EAI_LOCAL_AUTH_ENABLEDtruefalse si tout passe par Keycloak
EAI_LOCAL_AUTH_MAX_FAILURES / EAI_LOCAL_AUTH_LOCKOUT_SECONDS5 / 9005 / 900 ou plus strict
EAI_LOCAL_PASSWORD_MIN_LENGTH1212 ou plus
EAI_LOCAL_SESSION_TTL_SECONDS28800selon la politique de session
EAI_OPA_URLvide (moteur intégré seul)URL TLS d'OPA
EAI_OPA_DELIVERYpushbundle avec EAI_POLICY_BUNDLE_SIGNING_KEY_FILE
EAI_POLICY_DEFAULTallowdeny pour refuser ce qu'aucune règle ne couvre
EAI_OPENFGA_URL / EAI_OPENFGA_STORE_ID / EAI_OPENFGA_MODEL_IDvide (tuples intégrés)magasin OpenFGA dédié, avec EAI_OPENFGA_API_TOKEN
EAI_KMS_PROVIDERnoneopenbao ou pkcs11
EAI_CONTEXT_REQUIREDfalsetrue (obligatoire)
EAI_CONTEXT_SIGNING_KEY_REFvideréférence OpenBao (obligatoire)
EAI_BREAK_GLASS_MAX_SECONDS36003600 ou moins
EAI_APPROVAL_TTL_SECONDS86400 (lu par eai.domains.approvals.service)selon les délais de décision
EAI_FILE_SCAN_MODEdevenforce (obligatoire)
EAI_METRICS_TOKENvide32 caractères minimum (obligatoire)

Autres refus de la garde de démarrage​

En plus de la liste ci-dessus, eai.security.startup.problems refuse en production :

  • EAI_METRICS_TOKEN absent ou de moins de 32 caractères ;
  • EAI_RUNTIME_DATABASE_URL sans TLS, EAI_REDIS_URL sans rediss://, Redis sans EAI_REDIS_PASSWORD_FILE ;
  • EAI_OPENBAO_URL et EAI_OPENBAO_TOKEN absents ou EAI_AUDIT_SIGNING=hmac ;
  • EAI_CONTEXT_REQUIRED désactivé, EAI_CONTEXT_SIGNING_KEY en clair sans EAI_CONTEXT_SIGNING_KEY_REF, ou aucune clé ;
  • EAI_AUDIT_SEAL_SIGNING_KEY_REF absent, EAI_AUDIT_PAYLOAD_KEK différent de openbao-transit, EAI_AUDIT_CLOCK_SKEW_SECONDS hors de 0 à 3600 ;
  • EAI_OPA_DELIVERY différent de push ou bundle, ou bundle sans EAI_POLICY_BUNDLE_SIGNING_KEY_FILE ;
  • EAI_KMS_PROVIDER inconnu, ou pkcs11 sans EAI_KMS_PKCS11_MODULE, EAI_KMS_PKCS11_TOKEN_LABEL et EAI_KMS_PKCS11_PIN_FILE ;
  • EAI_FILE_SCAN_MODE différent de enforce, un moteur ClamAV ou YARA-X hors https:// ou sans clé Bearer ;
  • EAI_REALTIME_CONSENT_REQUIRED=false ;
  • EAI_SOC_WEBHOOK_SECRET de moins de 32 caractères, EAI_SOC_CORRELATION_WINDOW_SECONDS hors de 60 à 86400 ;
  • EAI_STORAGE_PRESIGN_MAX_SECONDS hors de 1 à 86400, EAI_STORAGE_CAPABILITY_MAX_AGE_SECONDS hors de 60 à 604800, EAI_STORAGE_CA_BUNDLE illisible ;
  • EAI_BOOTSTRAP_ADMIN_PASSWORD faible quand les comptes locaux sont actifs.

La procédure complète de durcissement est dans hardening.md.