import type { Edge, Node } from "@xyflow/react"; import { MarkerType } from "@xyflow/react"; import type { ZTNodeData, ZTScenarioDefinition } from "../types"; const node = ( id: string, x: number, y: number, data: ZTNodeData, ): Node => ({ id, type: "ztNode", position: { x, y }, data, }); const edge = ( id: string, source: string, target: string, label: string, color?: string, handles?: { sourceHandle?: string; targetHandle?: string }, ): Edge => ({ id, source, target, label, sourceHandle: handles?.sourceHandle, targetHandle: handles?.targetHandle, animated: true, markerEnd: { type: MarkerType.ArrowClosed, width: 18, height: 18 }, style: { stroke: color ?? "#0f766e" }, labelStyle: { fill: "#134e4a", fontWeight: 500, fontSize: 11 }, labelBgStyle: { fill: "#ecfdf5", fillOpacity: 0.95 }, }); export const zeroTrustAccessScenario: ZTScenarioDefinition = { id: "zero-trust-access", title: "Accès avec vérification continue", subtitle: "Chaque requête est évaluée : identité, contexte, politique", intro: "Approche alignée sur NIST SP 800-207 : pas de confiance implicite au réseau. L’identité et le contexte (appareil, risque) alimentent une décision d’accès avant d’atteindre l’application et les données.", nodes: [ node("user", 40, 220, { kind: "user", label: "Utilisateur", role: "Identité", }), node("device", 220, 220, { kind: "device", label: "Poste / mobile", role: "Appareil", }), node("idp", 220, 40, { kind: "idp", label: "IdP (OIDC)", role: "Authentification", }), node("pep", 420, 220, { kind: "gateway", label: "PEP / API GW", role: "Application du contrôle", }), node("app", 600, 120, { kind: "workload", label: "Application", role: "Charge de travail", }), node("data", 600, 300, { kind: "data", label: "Données", role: "Stockage chiffré", }), ], edges: [ edge("e-ud", "user", "device", "Interaction", undefined, { sourceHandle: "right-s", targetHandle: "left-t", }), edge("e-di", "device", "idp", "Authorization Code + PKCE", "#0369a1", { sourceHandle: "top-s", targetHandle: "bot-t", }), edge("e-id", "idp", "device", "Jetons (access, refresh)", "#0369a1", { sourceHandle: "bot-s", targetHandle: "top-t", }), edge("e-dp", "device", "pep", "Requête + jeton", "#0f766e", { sourceHandle: "right-s", targetHandle: "left-t", }), edge("e-pa", "pep", "app", "Autorisé si politique OK", "#0f766e", { sourceHandle: "top-s", targetHandle: "bot-t", }), edge("e-ad", "app", "data", "mTLS / chiffrement", "#7c3aed", { sourceHandle: "bot-s", targetHandle: "top-t", }), ], steps: [ { id: "z1", title: "Authentification forte et contexte", description: "L’IdP émet des jetons après vérification de l’identité et du contexte (MFA, risque, appareil).", highlightNodes: ["user", "device", "idp"], highlightEdges: ["e-ud", "e-di", "e-id"], pillars: ["identity", "device"], practices: [ "MFA adaptatif ; pas de secrets long-terme exposés côté client (PKCE pour les clients publics).", "Évaluer la posture de l’appareil avant d’accorder la session.", ], }, { id: "z2", title: "Décision de politique au point d’application", description: "Le PEP (Policy Enforcement Point) applique les règles : qui, quoi, depuis où, avec quel risque — avant d’atteindre la charge de travail.", highlightNodes: ["device", "pep", "app"], highlightEdges: ["e-dp", "e-pa"], pillars: ["application", "network"], practices: [ "Séparer clairement PDP (politique) et PEP (application) dans l’architecture cible.", "Moindre privilège : scopes OAuth/OIDC minimaux, rôles applicatifs justifiés.", ], }, { id: "z3", title: "Protection des données jusqu’au stockage", description: "Les flux vers les données sont chiffrés et tracés ; l’accès reste soumis au contrôle continu (révocation, session courte, audit).", highlightNodes: ["app", "data"], highlightEdges: ["e-ad"], pillars: ["data", "application"], practices: [ "Chiffrement au repos et en transit ; classification des données sensibles.", "Observabilité : journaux corrélés pour détecter les abus de jetons ou les accès anormaux.", ], }, ], };