""" DORA Compliance Assessment Tool Digital Operational Resilience Act - Interactive Assessment Powered by AYI-NEDJIMI Consultants """ import gradio as gr import plotly.graph_objects as go import pandas as pd import json from datetime import datetime # --------------------------------------------------------------------------- # Translations # --------------------------------------------------------------------------- TEXTS = { "FR": { "title": "Evaluation de Conformite DORA", "subtitle": "Digital Operational Resilience Act - Outil interactif", "tab_assessment": "Evaluation DORA", "tab_explorer": "Explorateur des Piliers", "tab_incident": "Classification des Incidents ICT", "tab_tlpt": "Preparation TLPT", "tab_timeline": "Calendrier & Sanctions", "tab_resources": "Ressources", "yes": "Oui", "partial": "Partiel", "no": "Non", "na": "N/A", "submit": "Lancer le diagnostic", "overall_score": "Score global de conformite DORA", "pillar_scores": "Scores par pilier", "gap_analysis": "Analyse des ecarts et priorites", "maturity": "Niveau de maturite", "critical": "Critique", "low": "Faible", "medium": "Moyen", "high": "Eleve", "compliant": "Conforme", "remediation": "Actions de remediation recommandees", "timeline_est": "Calendrier de remediation estime", "pillar1": "Pilier 1 - Gestion des risques ICT", "pillar2": "Pilier 2 - Gestion des incidents ICT", "pillar3": "Pilier 3 - Tests de resilience operationnelle", "pillar4": "Pilier 4 - Risques lies aux tiers ICT", "pillar5": "Pilier 5 - Partage d informations", "incident_desc": "Description de l incident", "affected_services": "Services affectes", "impact_level": "Niveau d impact", "classify_btn": "Classifier l incident", "severity": "Severite", "reporting_timeline": "Delai de notification", "notification_tpl": "Modele de notification", "high_impact": "Eleve", "medium_impact": "Moyen", "low_impact": "Faible", "critical_impact": "Critique", "explorer_select": "Selectionnez un pilier", "articles_ref": "References articles", "key_req": "Exigences cles", "tech_measures": "Mesures techniques", "evidence": "Preuves necessaires", "common_gaps": "Ecarts courants", "footer": "Propulse par", }, "EN": { "title": "DORA Compliance Assessment", "subtitle": "Digital Operational Resilience Act - Interactive Tool", "tab_assessment": "DORA Assessment", "tab_explorer": "Pillar Explorer", "tab_incident": "ICT Incident Classification", "tab_tlpt": "TLPT Readiness", "tab_timeline": "Timeline & Penalties", "tab_resources": "Resources", "yes": "Yes", "partial": "Partial", "no": "No", "na": "N/A", "submit": "Run Assessment", "overall_score": "Overall DORA Compliance Score", "pillar_scores": "Pillar Scores", "gap_analysis": "Gap Analysis & Priorities", "maturity": "Maturity Level", "critical": "Critical", "low": "Low", "medium": "Medium", "high": "High", "compliant": "Compliant", "remediation": "Recommended Remediation Actions", "timeline_est": "Estimated Remediation Timeline", "pillar1": "Pillar 1 - ICT Risk Management", "pillar2": "Pillar 2 - ICT Incident Management", "pillar3": "Pillar 3 - Digital Operational Resilience Testing", "pillar4": "Pillar 4 - ICT Third-Party Risk", "pillar5": "Pillar 5 - Information Sharing", "incident_desc": "Incident Description", "affected_services": "Affected Services", "impact_level": "Impact Level", "classify_btn": "Classify Incident", "severity": "Severity", "reporting_timeline": "Reporting Timeline", "notification_tpl": "Notification Template", "high_impact": "High", "medium_impact": "Medium", "low_impact": "Low", "critical_impact": "Critical", "explorer_select": "Select a pillar", "articles_ref": "Article References", "key_req": "Key Requirements", "tech_measures": "Technical Measures", "evidence": "Evidence Needed", "common_gaps": "Common Gaps", "footer": "Powered by", }, } # --------------------------------------------------------------------------- # Questions per pillar # --------------------------------------------------------------------------- QUESTIONS = { "FR": { "pillar1": [ "Disposez-vous d un cadre documente de gestion des risques ICT ?", "Existe-t-il une fonction dediee a la gestion des risques ICT ?", "Realisez-vous des evaluations regulieres des risques ICT ?", "Disposez-vous de plans de continuite pour les perturbations ICT ?", "Les politiques de securite ICT sont-elles approuvees par la direction ?", "Maintenez-vous un inventaire des actifs ICT ?", "Les systemes ICT sont-ils regulierement corriges et mis a jour ?", "Disposez-vous d un processus de gestion des vulnerabilites ?", "Les normes de chiffrement sont-elles appliquees (repos et transit) ?", "Realisez-vous regulierement des analyses d impact (BIA) ?", ], "pillar2": [ "Disposez-vous d un schema de classification des incidents ICT ?", "Pouvez-vous detecter les incidents ICT dans les delais definis ?", "Avez-vous des processus de notification initiale sous 4 heures ?", "Pouvez-vous produire des rapports intermediaires sous 72 heures ?", "Disposez-vous de procedures d analyse des causes profondes ?", "Existe-t-il un plan de communication des incidents ?", "Suivez-vous les incidents ICT dans un systeme centralise ?", "Les lecons apprises sont-elles documentees et appliquees ?", ], "pillar3": [ "Realisez-vous des tests ICT reguliers (scans, pentests) ?", "Avez-vous identifie les fonctions critiques necessitant des TLPT ?", "Utilisez-vous des testeurs externes qualifies pour les TLPT ?", "Les resultats des tests sont-ils partages avec les autorites ?", "Realisez-vous des tests bases sur des scenarios ?", "Les plans de remediation sont-ils suivis jusqu a resolution ?", "Testez-vous les procedures de sauvegarde et de reprise ?", ], "pillar4": [ "Maintenez-vous un registre des prestataires ICT tiers ?", "Les exigences contractuelles sont-elles alignees sur DORA ?", "Evaluez-vous le risque de concentration ?", "Les strategies de sortie sont-elles documentees pour les prestataires critiques ?", "Surveillez-vous la performance des prestataires tiers ?", "Les chaines de sous-traitance sont-elles documentees ?", "Realisez-vous une due diligence avant integration ?", "Les prestataires ICT tiers critiques sont-ils identifies ?", ], "pillar5": [ "Participez-vous au partage de renseignements sur les menaces ?", "Les processus CTI sont-ils documentes ?", "Partagez-vous des informations sur les incidents avec vos pairs ?", "Les accords de partage d informations sont-ils formalises ?", "Consommez-vous des flux de menaces (ISACs/CERTs) ?", ], }, "EN": { "pillar1": [ "Do you have a documented ICT risk management framework?", "Is there a dedicated ICT risk management function?", "Do you conduct regular ICT risk assessments?", "Do you have business continuity plans for ICT disruptions?", "Are ICT security policies approved by management body?", "Do you maintain an ICT asset inventory?", "Are ICT systems regularly patched and updated?", "Do you have a vulnerability management process?", "Are encryption standards implemented for data at rest and in transit?", "Do you conduct regular BIA (Business Impact Analysis)?", ], "pillar2": [ "Do you have an ICT incident classification scheme?", "Can you detect ICT-related incidents within defined timeframes?", "Do you have processes for initial notification within 4 hours?", "Can you produce intermediate reports within 72 hours?", "Do you have root cause analysis procedures?", "Is there an incident communication plan?", "Do you track ICT incidents in a centralized system?", "Are lessons learned documented and implemented?", ], "pillar3": [ "Do you conduct regular ICT testing (vulnerability scanning, pen testing)?", "Have you identified critical functions requiring TLPT?", "Do you use qualified external testers for TLPT?", "Are test results shared with competent authorities?", "Do you conduct scenario-based testing?", "Are remediation plans tracked to completion?", "Do you test backup and recovery procedures?", ], "pillar4": [ "Do you maintain a register of ICT third-party providers?", "Are contractual requirements aligned with DORA?", "Do you assess concentration risk?", "Are exit strategies documented for critical providers?", "Do you monitor third-party performance?", "Are sub-outsourcing chains documented?", "Do you conduct due diligence before onboarding?", "Are critical ICT third-party providers identified?", ], "pillar5": [ "Do you participate in threat intelligence sharing?", "Are CTI processes documented?", "Do you share incident information with peers?", "Are information sharing arrangements formalized?", "Do you consume threat feeds from ISACs/CERTs?", ], }, } # --------------------------------------------------------------------------- # Pillar explorer data # --------------------------------------------------------------------------- PILLAR_DATA = { "FR": { "pillar1": { "articles": "Articles 5 a 16 du Reglement DORA (UE 2022/2554)", "requirements": [ "Cadre de gestion des risques ICT documente et approuve", "Fonction de controle independante des risques ICT", "Strategie de resilience operationnelle numerique", "Politiques de securite de l information", "Gestion des actifs ICT et inventaire complet", "Gestion des vulnerabilites et correctifs", "Chiffrement et controles cryptographiques", "Plans de continuite d activite ICT", "Analyses d impact sur les activites (BIA)", "Formation et sensibilisation du personnel", ], "tech_measures": [ "SIEM / SOC pour la surveillance continue", "Solutions de gestion des vulnerabilites (Qualys, Nessus)", "Chiffrement AES-256 pour les donnees au repos", "TLS 1.3 pour les donnees en transit", "Gestion des identites et des acces (IAM)", "Segmentation reseau et pare-feu de nouvelle generation", "Solutions de sauvegarde et reprise apres sinistre", "CMDB pour l inventaire des actifs", ], "evidence": [ "Politique de gestion des risques ICT approuvee", "Registre des risques ICT a jour", "Rapports d evaluation des risques", "Plans de continuite testes", "Preuves de formation du personnel", "Inventaire des actifs ICT", "Rapports de scans de vulnerabilites", ], "gaps": [ "Absence de cadre formalise de gestion des risques ICT", "Inventaire des actifs ICT incomplet", "Plans de continuite non testes regulierement", "Manque de formation specifique DORA", "Politiques de securite non approuvees par la direction", "Absence de BIA formalise", ], }, "pillar2": { "articles": "Articles 17 a 23 du Reglement DORA", "requirements": [ "Processus de gestion des incidents ICT", "Classification des incidents selon les criteres DORA", "Notification initiale sous 4 heures", "Rapport intermediaire sous 72 heures", "Rapport final sous 1 mois", "Analyse des causes profondes (RCA)", "Registre centralise des incidents", "Communication interne et externe", ], "tech_measures": [ "Plateforme ITSM (ServiceNow, Jira Service Management)", "SOAR pour l automatisation de la reponse", "Outils de forensique numerique", "Systeme de ticketing centralise", "Outils de communication de crise", "Tableaux de bord de suivi des incidents", ], "evidence": [ "Procedure de gestion des incidents documentee", "Schema de classification des incidents", "Registre des incidents ICT", "Rapports de notification aux autorites", "Rapports d analyse des causes profondes", "Preuves de lecons apprises implementees", ], "gaps": [ "Absence de classification conforme DORA", "Delais de notification non respectes", "Pas d analyse systematique des causes profondes", "Registre des incidents incomplet", "Lecons apprises non formalisees", ], }, "pillar3": { "articles": "Articles 24 a 27 du Reglement DORA", "requirements": [ "Programme de tests de resilience operationnelle", "Tests de vulnerabilite et scans reguliers", "Tests de penetration bases sur les menaces (TLPT)", "Utilisation de testeurs externes qualifies", "Partage des resultats avec les autorites", "Plans de remediation suivis", "Tests des sauvegardes et de la reprise", ], "tech_measures": [ "Scanners de vulnerabilites (Nessus, OpenVAS)", "Outils de tests de penetration (Metasploit, Burp Suite)", "Cadre TIBER-EU pour les TLPT", "Outils de red team / purple team", "Solutions de test de sauvegarde automatise", "Plateformes de simulation d attaques (BAS)", ], "evidence": [ "Programme de tests annuel documente", "Rapports de scans de vulnerabilites", "Rapports de tests de penetration", "Rapports TLPT (si applicable)", "Plans de remediation avec suivi", "Resultats des tests de sauvegarde", ], "gaps": [ "Absence de programme de tests formalise", "TLPT non realises pour les fonctions critiques", "Resultats de tests non partages avec les autorites", "Plans de remediation non suivis", "Tests de sauvegarde insuffisants", ], }, "pillar4": { "articles": "Articles 28 a 44 du Reglement DORA", "requirements": [ "Registre des prestataires ICT tiers", "Exigences contractuelles alignees DORA", "Evaluation du risque de concentration", "Strategies de sortie documentees", "Surveillance continue de la performance", "Documentation des chaines de sous-traitance", "Due diligence avant integration", "Identification des prestataires critiques", ], "tech_measures": [ "Plateforme de gestion des tiers (TPRM)", "Outils de notation des risques fournisseurs", "Monitoring continu des prestataires", "Solutions de gestion contractuelle (CLM)", "Outils d evaluation de la concentration", "Portail fournisseurs pour la collecte de donnees", ], "evidence": [ "Registre complet des prestataires ICT", "Contrats avec clauses DORA", "Evaluation du risque de concentration", "Strategies de sortie documentees", "Rapports de surveillance des prestataires", "Documentation des sous-traitances", "Rapports de due diligence", ], "gaps": [ "Registre des prestataires incomplet", "Contrats non conformes DORA", "Risque de concentration non evalue", "Strategies de sortie absentes", "Sous-traitance non documentee", "Due diligence insuffisante", ], }, "pillar5": { "articles": "Article 45 du Reglement DORA", "requirements": [ "Participation au partage de renseignements sur les menaces", "Processus CTI documentes", "Partage d informations sur les incidents", "Accords de partage formalises", "Consommation de flux de menaces (ISACs/CERTs)", ], "tech_measures": [ "Plateforme de Threat Intelligence (MISP, OpenCTI)", "Flux STIX/TAXII", "Abonnement ISACs sectoriels", "Flux CERTs nationaux et europeens", "Integration CTI dans le SIEM", ], "evidence": [ "Politique de partage d informations", "Accords de partage signes", "Preuves de participation aux ISACs", "Rapports CTI consommes et produits", "Integration des flux dans les outils de detection", ], "gaps": [ "Aucune participation au partage de renseignements", "Processus CTI non formalises", "Absence d accords de partage", "Pas de consommation de flux de menaces", ], }, }, "EN": { "pillar1": { "articles": "Articles 5 to 16 of DORA Regulation (EU 2022/2554)", "requirements": [ "Documented and approved ICT risk management framework", "Independent ICT risk control function", "Digital operational resilience strategy", "Information security policies", "ICT asset management and complete inventory", "Vulnerability and patch management", "Encryption and cryptographic controls", "ICT business continuity plans", "Business Impact Analysis (BIA)", "Staff training and awareness", ], "tech_measures": [ "SIEM / SOC for continuous monitoring", "Vulnerability management solutions (Qualys, Nessus)", "AES-256 encryption for data at rest", "TLS 1.3 for data in transit", "Identity and Access Management (IAM)", "Network segmentation and next-gen firewalls", "Backup and disaster recovery solutions", "CMDB for asset inventory", ], "evidence": [ "Approved ICT risk management policy", "Up-to-date ICT risk register", "Risk assessment reports", "Tested continuity plans", "Staff training evidence", "ICT asset inventory", "Vulnerability scan reports", ], "gaps": [ "No formalized ICT risk management framework", "Incomplete ICT asset inventory", "Continuity plans not regularly tested", "Lack of DORA-specific training", "Security policies not approved by management", "No formalized BIA", ], }, "pillar2": { "articles": "Articles 17 to 23 of DORA Regulation", "requirements": [ "ICT incident management process", "Incident classification per DORA criteria", "Initial notification within 4 hours", "Intermediate report within 72 hours", "Final report within 1 month", "Root Cause Analysis (RCA)", "Centralized incident register", "Internal and external communication", ], "tech_measures": [ "ITSM platform (ServiceNow, Jira Service Management)", "SOAR for response automation", "Digital forensics tools", "Centralized ticketing system", "Crisis communication tools", "Incident tracking dashboards", ], "evidence": [ "Documented incident management procedure", "Incident classification scheme", "ICT incident register", "Authority notification reports", "Root cause analysis reports", "Evidence of lessons learned implemented", ], "gaps": [ "No DORA-compliant classification", "Notification timelines not met", "No systematic root cause analysis", "Incomplete incident register", "Lessons learned not formalized", ], }, "pillar3": { "articles": "Articles 24 to 27 of DORA Regulation", "requirements": [ "Operational resilience testing programme", "Regular vulnerability testing and scanning", "Threat-Led Penetration Testing (TLPT)", "Use of qualified external testers", "Sharing results with authorities", "Remediation plans tracked", "Backup and recovery testing", ], "tech_measures": [ "Vulnerability scanners (Nessus, OpenVAS)", "Penetration testing tools (Metasploit, Burp Suite)", "TIBER-EU framework for TLPT", "Red team / Purple team tools", "Automated backup test solutions", "Breach & Attack Simulation (BAS) platforms", ], "evidence": [ "Documented annual testing programme", "Vulnerability scan reports", "Penetration test reports", "TLPT reports (if applicable)", "Remediation plans with tracking", "Backup test results", ], "gaps": [ "No formalized testing programme", "TLPT not performed for critical functions", "Test results not shared with authorities", "Remediation plans not tracked", "Insufficient backup testing", ], }, "pillar4": { "articles": "Articles 28 to 44 of DORA Regulation", "requirements": [ "Register of ICT third-party providers", "Contractual requirements aligned with DORA", "Concentration risk assessment", "Documented exit strategies", "Continuous performance monitoring", "Sub-outsourcing chain documentation", "Due diligence before onboarding", "Identification of critical providers", ], "tech_measures": [ "Third-Party Risk Management (TPRM) platform", "Vendor risk scoring tools", "Continuous provider monitoring", "Contract Lifecycle Management (CLM) solutions", "Concentration assessment tools", "Vendor portal for data collection", ], "evidence": [ "Complete ICT provider register", "Contracts with DORA clauses", "Concentration risk assessment", "Documented exit strategies", "Provider monitoring reports", "Sub-outsourcing documentation", "Due diligence reports", ], "gaps": [ "Incomplete provider register", "Non-DORA-compliant contracts", "Concentration risk not assessed", "Missing exit strategies", "Sub-outsourcing not documented", "Insufficient due diligence", ], }, "pillar5": { "articles": "Article 45 of DORA Regulation", "requirements": [ "Participation in threat intelligence sharing", "Documented CTI processes", "Incident information sharing with peers", "Formalized sharing arrangements", "Threat feed consumption from ISACs/CERTs", ], "tech_measures": [ "Threat Intelligence platform (MISP, OpenCTI)", "STIX/TAXII feeds", "Sector ISAC subscriptions", "National and European CERT feeds", "CTI integration into SIEM", ], "evidence": [ "Information sharing policy", "Signed sharing agreements", "ISAC participation evidence", "CTI reports consumed and produced", "Feed integration into detection tools", ], "gaps": [ "No participation in intelligence sharing", "CTI processes not formalized", "No sharing agreements in place", "No threat feed consumption", ], }, }, } # --------------------------------------------------------------------------- # Remediation actions per pillar # --------------------------------------------------------------------------- REMEDIATION = { "FR": { "pillar1": [ "Rediger et faire approuver un cadre de gestion des risques ICT", "Nommer un responsable des risques ICT", "Mettre en place un inventaire complet des actifs ICT", "Deployer un programme de gestion des vulnerabilites", "Implementer le chiffrement conforme aux standards", "Realiser une BIA et mettre a jour les plans de continuite", ], "pillar2": [ "Definir un schema de classification des incidents DORA", "Mettre en place des processus de notification (4h/72h/1 mois)", "Deployer un systeme centralise de suivi des incidents", "Formaliser les procedures d analyse des causes profondes", "Creer un processus de lecons apprises", ], "pillar3": [ "Etablir un programme annuel de tests de resilience", "Identifier les fonctions critiques necessitant des TLPT", "Engager des testeurs externes qualifies", "Mettre en place un suivi des plans de remediation", "Tester regulierement les sauvegardes et la reprise", ], "pillar4": [ "Creer un registre complet des prestataires ICT tiers", "Reviser les contrats pour inclure les clauses DORA", "Evaluer le risque de concentration fournisseurs", "Documenter les strategies de sortie", "Mettre en place une surveillance continue des prestataires", ], "pillar5": [ "Rejoindre un ISAC sectoriel", "Mettre en place une plateforme CTI (MISP/OpenCTI)", "Formaliser les accords de partage d informations", "Integrer les flux de menaces dans le SIEM", ], }, "EN": { "pillar1": [ "Draft and approve an ICT risk management framework", "Appoint a dedicated ICT risk officer", "Implement a complete ICT asset inventory", "Deploy a vulnerability management programme", "Implement compliant encryption standards", "Conduct BIA and update continuity plans", ], "pillar2": [ "Define a DORA incident classification scheme", "Implement notification processes (4h/72h/1 month)", "Deploy a centralized incident tracking system", "Formalize root cause analysis procedures", "Create a lessons learned process", ], "pillar3": [ "Establish an annual resilience testing programme", "Identify critical functions requiring TLPT", "Engage qualified external testers", "Implement remediation plan tracking", "Regularly test backups and recovery", ], "pillar4": [ "Create a complete ICT third-party provider register", "Review contracts to include DORA clauses", "Assess vendor concentration risk", "Document exit strategies", "Implement continuous provider monitoring", ], "pillar5": [ "Join a sector ISAC", "Deploy a CTI platform (MISP/OpenCTI)", "Formalize information sharing agreements", "Integrate threat feeds into SIEM", ], }, } # --------------------------------------------------------------------------- # TLPT checklist # --------------------------------------------------------------------------- TLPT_CHECKLIST = { "FR": { "scope": [ "Fonctions critiques ou importantes identifiees", "Perimetre du TLPT defini et approuve", "Surfaces d attaque cartographiees", "Scenarios de menaces selectionnes (TIBER-EU)", "Objectifs du test documentes", ], "testers": [ "Testeurs externes qualifies selectionnes", "Independance des testeurs verifiee", "Contrat et NDA signes", "Assurance responsabilite civile verifiee", "Experience TIBER-EU / CBEST confirmee", ], "purple_team": [ "Equipe purple team constituee", "Regles d engagement definies", "Canaux de communication etablis", "Criteres d arret definis", "Planning des sessions coordonne", ], "remediation": [ "Processus de suivi des vulnerabilites en place", "Priorites de remediation definies", "Responsables des actions identifies", "Delais de remediation convenus", "Rapport de cloture prevu", ], }, "EN": { "scope": [ "Critical or important functions identified", "TLPT scope defined and approved", "Attack surfaces mapped", "Threat scenarios selected (TIBER-EU)", "Test objectives documented", ], "testers": [ "Qualified external testers selected", "Tester independence verified", "Contract and NDA signed", "Professional liability insurance verified", "TIBER-EU / CBEST experience confirmed", ], "purple_team": [ "Purple team assembled", "Rules of engagement defined", "Communication channels established", "Stop criteria defined", "Session planning coordinated", ], "remediation": [ "Vulnerability tracking process in place", "Remediation priorities defined", "Action owners identified", "Remediation timelines agreed", "Closure report planned", ], }, } # --------------------------------------------------------------------------- # Helper functions # --------------------------------------------------------------------------- def get_maturity_label(score, lang): t = TEXTS[lang] if score < 20: return t["critical"], "#dc3545" elif score < 40: return t["low"], "#fd7e14" elif score < 60: return t["medium"], "#ffc107" elif score < 80: return t["high"], "#28a745" else: return t["compliant"], "#007bff" def get_remediation_timeline(score, lang): if lang == "FR": if score < 20: return "Immediat - 3 mois : Actions critiques urgentes" elif score < 40: return "3 - 6 mois : Plan de remediation prioritaire" elif score < 60: return "6 - 12 mois : Amelioration continue" elif score < 80: return "12 - 18 mois : Optimisation et formalisation" else: return "Maintenance continue : Revues periodiques" else: if score < 20: return "Immediate - 3 months: Critical urgent actions" elif score < 40: return "3 - 6 months: Priority remediation plan" elif score < 60: return "6 - 12 months: Continuous improvement" elif score < 80: return "12 - 18 months: Optimization and formalization" else: return "Ongoing maintenance: Periodic reviews" def compute_scores(answers, lang): """Compute pillar scores from answer lists.""" pillar_keys = ["pillar1", "pillar2", "pillar3", "pillar4", "pillar5"] t = TEXTS[lang] pillar_labels = [t["pillar1"], t["pillar2"], t["pillar3"], t["pillar4"], t["pillar5"]] scores = {} idx = 0 for pk in pillar_keys: q_count = len(QUESTIONS[lang][pk]) total = 0 applicable = 0 for _ in range(q_count): ans = answers[idx] if idx < len(answers) else t["no"] if ans == t["yes"]: total += 1 applicable += 1 elif ans == t["partial"]: total += 0.5 applicable += 1 elif ans == t["no"]: applicable += 1 # N/A does not count idx += 1 scores[pk] = (total / applicable * 100) if applicable > 0 else 0 overall = sum(scores.values()) / len(scores) if scores else 0 return scores, overall, pillar_labels def build_radar_chart(scores, pillar_labels, lang): """Build a Plotly radar chart for pillar scores.""" values = list(scores.values()) values_closed = values + [values[0]] labels_closed = pillar_labels + [pillar_labels[0]] fig = go.Figure() fig.add_trace(go.Scatterpolar( r=values_closed, theta=labels_closed, fill="toself", name="Score", line_color="#1a73e8", fillcolor="rgba(26, 115, 232, 0.25)", )) chart_title = "Scores par pilier DORA" if lang == "FR" else "DORA Pillar Scores" fig.update_layout( polar=dict(radialaxis=dict(visible=True, range=[0, 100])), showlegend=False, title=chart_title, template="plotly_white", height=500, ) return fig def build_gap_analysis(scores, lang): """Return gap analysis markdown sorted by priority.""" t = TEXTS[lang] pillar_names = { "pillar1": t["pillar1"], "pillar2": t["pillar2"], "pillar3": t["pillar3"], "pillar4": t["pillar4"], "pillar5": t["pillar5"], } sorted_pillars = sorted(scores.items(), key=lambda x: x[1]) if lang == "FR": md = "## Analyse des ecarts - Priorites\n\n" md += "| Priorite | Pilier | Score | Niveau |\n|:---:|---|:---:|:---:|\n" else: md = "## Gap Analysis - Priorities\n\n" md += "| Priority | Pillar | Score | Level |\n|:---:|---|:---:|:---:|\n" for i, (pk, sc) in enumerate(sorted_pillars, 1): label, color = get_maturity_label(sc, lang) md += f"| {i} | {pillar_names[pk]} | {sc:.0f}% | {label} |\n" return md def build_remediation_md(scores, lang): """Build remediation recommendations for pillars below 80%.""" t = TEXTS[lang] pillar_names = { "pillar1": t["pillar1"], "pillar2": t["pillar2"], "pillar3": t["pillar3"], "pillar4": t["pillar4"], "pillar5": t["pillar5"], } header = "## Actions de remediation recommandees\n\n" if lang == "FR" else "## Recommended Remediation Actions\n\n" md = header sorted_pillars = sorted(scores.items(), key=lambda x: x[1]) for pk, sc in sorted_pillars: if sc < 80: md += f"### {pillar_names[pk]} ({sc:.0f}%)\n\n" actions = REMEDIATION[lang].get(pk, []) for a in actions: md += f"- {a}\n" md += "\n" if all(sc >= 80 for sc in scores.values()): if lang == "FR": md += "Felicitations ! Tous les piliers sont au-dessus de 80%. Continuez la surveillance et les revues periodiques.\n" else: md += "Congratulations! All pillars are above 80%. Continue monitoring and periodic reviews.\n" return md def run_assessment(lang, *answers): """Main assessment function.""" answers_list = list(answers) scores, overall, pillar_labels = compute_scores(answers_list, lang) maturity_label, maturity_color = get_maturity_label(overall, lang) radar = build_radar_chart(scores, pillar_labels, lang) gap_md = build_gap_analysis(scores, lang) rem_md = build_remediation_md(scores, lang) timeline = get_remediation_timeline(overall, lang) if lang == "FR": overall_md = f"# Score global : {overall:.1f}%\n\n" overall_md += f"**Niveau de maturite : {maturity_label}**\n\n" overall_md += f"**Calendrier de remediation : {timeline}**\n" else: overall_md = f"# Overall Score: {overall:.1f}%\n\n" overall_md += f"**Maturity Level: {maturity_label}**\n\n" overall_md += f"**Remediation Timeline: {timeline}**\n" return overall_md, radar, gap_md, rem_md def classify_incident(lang, description, services, impact): """Classify an ICT incident according to DORA criteria.""" t = TEXTS[lang] if impact in (t["critical_impact"], "Critique", "Critical"): severity = t["critical_impact"] timeline = "4h / 72h / 1 month" if lang == "EN" else "4h / 72h / 1 mois" color = "red" elif impact in (t["high_impact"], "Eleve", "High"): severity = t["high_impact"] timeline = "4h / 72h / 1 month" if lang == "EN" else "4h / 72h / 1 mois" color = "orange" elif impact in (t["medium_impact"], "Moyen", "Medium"): severity = t["medium_impact"] timeline = "72h / 1 month" if lang == "EN" else "72h / 1 mois" color = "yellow" else: severity = t["low_impact"] timeline = "1 month" if lang == "EN" else "1 mois" color = "green" now = datetime.now().strftime("%Y-%m-%d %H:%M") if lang == "FR": classification_md = f"""## Resultat de la classification | Champ | Valeur | |---|---| | **Severite** | {severity} | | **Delai de notification** | {timeline} | | **Date d analyse** | {now} | | **Services affectes** | {services} | """ template_md = f"""## Modele de notification **A :** Autorite competente (ACPR / AMF) **De :** [Nom de l entite] **Date :** {now} **Objet :** Notification d incident ICT majeur - DORA Art. 19 --- **1. Description de l incident** {description} **2. Services affectes** {services} **3. Niveau d impact** {severity} **4. Chronologie** - Detection : {now} - Notification initiale : dans les 4 heures - Rapport intermediaire : dans les 72 heures - Rapport final : dans 1 mois **5. Mesures prises** [A completer] **6. Actions correctives prevues** [A completer] """ else: classification_md = f"""## Classification Result | Field | Value | |---|---| | **Severity** | {severity} | | **Reporting Timeline** | {timeline} | | **Analysis Date** | {now} | | **Affected Services** | {services} | """ template_md = f"""## Notification Template **To:** Competent Authority **From:** [Entity Name] **Date:** {now} **Subject:** Major ICT Incident Notification - DORA Art. 19 --- **1. Incident Description** {description} **2. Affected Services** {services} **3. Impact Level** {severity} **4. Timeline** - Detection: {now} - Initial notification: within 4 hours - Intermediate report: within 72 hours - Final report: within 1 month **5. Measures Taken** [To be completed] **6. Planned Corrective Actions** [To be completed] """ return classification_md, template_md def show_pillar_detail(lang, pillar_choice): """Return detailed info for a selected pillar.""" pillar_map_fr = { "Pilier 1 - Gestion des risques ICT": "pillar1", "Pilier 2 - Gestion des incidents ICT": "pillar2", "Pilier 3 - Tests de resilience operationnelle": "pillar3", "Pilier 4 - Risques lies aux tiers ICT": "pillar4", "Pilier 5 - Partage d informations": "pillar5", } pillar_map_en = { "Pillar 1 - ICT Risk Management": "pillar1", "Pillar 2 - ICT Incident Management": "pillar2", "Pillar 3 - Digital Operational Resilience Testing": "pillar3", "Pillar 4 - ICT Third-Party Risk": "pillar4", "Pillar 5 - Information Sharing": "pillar5", } pmap = pillar_map_fr if lang == "FR" else pillar_map_en pk = pmap.get(pillar_choice) if not pk: return "Please select a pillar." if lang == "EN" else "Veuillez selectionner un pilier." data = PILLAR_DATA[lang][pk] t = TEXTS[lang] md = f"## {pillar_choice}\n\n" md += f"### {t['articles_ref']}\n{data['articles']}\n\n" md += f"### {t['key_req']}\n" for r in data["requirements"]: md += f"- {r}\n" md += f"\n### {t['tech_measures']}\n" for m in data["tech_measures"]: md += f"- {m}\n" md += f"\n### {t['evidence']}\n" for e in data["evidence"]: md += f"- {e}\n" md += f"\n### {t['common_gaps']}\n" for g in data["gaps"]: md += f"- {g}\n" return md # --------------------------------------------------------------------------- # Build Gradio UI # --------------------------------------------------------------------------- FOOTER_HTML = """
Powered by AYI-NEDJIMI Consultants | DORA 2026 Guide | All Datasets
Digital Operational Resilience Act (EU 2022/2554)
") with gr.Row(): lang_toggle = gr.Radio( choices=["FR", "EN"], value="FR", label="Langue / Language", interactive=True, ) # Collect all Radio components for assessment questions all_radios = [] with gr.Tab("Evaluation DORA / DORA Assessment"): gr.Markdown("### Pilier 1 - Gestion des risques ICT / ICT Risk Management") for i, (q_fr, q_en) in enumerate(zip(QUESTIONS["FR"]["pillar1"], QUESTIONS["EN"]["pillar1"])): label_text = f"P1.{i+1} | {q_fr} / {q_en}" r = gr.Radio( choices=["Oui", "Partiel", "Non", "N/A"], value="Non", label=label_text, interactive=True, ) all_radios.append(r) gr.Markdown("### Pilier 2 - Gestion des incidents ICT / ICT Incident Management") for i, (q_fr, q_en) in enumerate(zip(QUESTIONS["FR"]["pillar2"], QUESTIONS["EN"]["pillar2"])): label_text = f"P2.{i+1} | {q_fr} / {q_en}" r = gr.Radio( choices=["Oui", "Partiel", "Non", "N/A"], value="Non", label=label_text, interactive=True, ) all_radios.append(r) gr.Markdown("### Pilier 3 - Tests de resilience / Resilience Testing") for i, (q_fr, q_en) in enumerate(zip(QUESTIONS["FR"]["pillar3"], QUESTIONS["EN"]["pillar3"])): label_text = f"P3.{i+1} | {q_fr} / {q_en}" r = gr.Radio( choices=["Oui", "Partiel", "Non", "N/A"], value="Non", label=label_text, interactive=True, ) all_radios.append(r) gr.Markdown("### Pilier 4 - Risques tiers ICT / ICT Third-Party Risk") for i, (q_fr, q_en) in enumerate(zip(QUESTIONS["FR"]["pillar4"], QUESTIONS["EN"]["pillar4"])): label_text = f"P4.{i+1} | {q_fr} / {q_en}" r = gr.Radio( choices=["Oui", "Partiel", "Non", "N/A"], value="Non", label=label_text, interactive=True, ) all_radios.append(r) gr.Markdown("### Pilier 5 - Partage d informations / Information Sharing") for i, (q_fr, q_en) in enumerate(zip(QUESTIONS["FR"]["pillar5"], QUESTIONS["EN"]["pillar5"])): label_text = f"P5.{i+1} | {q_fr} / {q_en}" r = gr.Radio( choices=["Oui", "Partiel", "Non", "N/A"], value="Non", label=label_text, interactive=True, ) all_radios.append(r) submit_btn = gr.Button("Lancer le diagnostic / Run Assessment", variant="primary") overall_output = gr.Markdown() radar_output = gr.Plot() gap_output = gr.Markdown() remediation_output = gr.Markdown() def assessment_wrapper(lang_val, *answers): # Map FR radio values for scoring mapped = [] t = TEXTS[lang_val] for a in answers: if a == "Oui": mapped.append(t["yes"]) elif a == "Partiel": mapped.append(t["partial"]) elif a == "N/A": mapped.append(t["na"]) else: mapped.append(t["no"]) return run_assessment(lang_val, *mapped) submit_btn.click( fn=assessment_wrapper, inputs=[lang_state] + all_radios, outputs=[overall_output, radar_output, gap_output, remediation_output], ) with gr.Tab("Explorateur des Piliers / Pillar Explorer"): pillar_choices_combined = [ "Pilier 1 - Gestion des risques ICT", "Pilier 2 - Gestion des incidents ICT", "Pilier 3 - Tests de resilience operationnelle", "Pilier 4 - Risques lies aux tiers ICT", "Pilier 5 - Partage d informations", ] pillar_dd = gr.Dropdown( choices=pillar_choices_combined, label="Selectionnez un pilier / Select a pillar", interactive=True, ) explorer_output = gr.Markdown() def explorer_wrapper(lang_val, choice): if not choice: if lang_val == "FR": return "Veuillez selectionner un pilier." return "Please select a pillar." # Map FR choices to both languages for lookup fr_to_en = { "Pilier 1 - Gestion des risques ICT": "Pillar 1 - ICT Risk Management", "Pilier 2 - Gestion des incidents ICT": "Pillar 2 - ICT Incident Management", "Pilier 3 - Tests de resilience operationnelle": "Pillar 3 - Digital Operational Resilience Testing", "Pilier 4 - Risques lies aux tiers ICT": "Pillar 4 - ICT Third-Party Risk", "Pilier 5 - Partage d informations": "Pillar 5 - Information Sharing", } if lang_val == "EN": en_choice = fr_to_en.get(choice, choice) return show_pillar_detail("EN", en_choice) return show_pillar_detail("FR", choice) pillar_dd.change( fn=explorer_wrapper, inputs=[lang_state, pillar_dd], outputs=[explorer_output], ) with gr.Tab("Classification Incidents / Incident Classification"): gr.Markdown("### Classification des incidents ICT selon DORA / ICT Incident Classification per DORA") inc_desc = gr.Textbox( label="Description de l incident / Incident Description", lines=4, placeholder="Decrivez l incident ICT... / Describe the ICT incident...", ) inc_services = gr.Textbox( label="Services affectes / Affected Services", placeholder="Ex: Core Banking, Payment Gateway...", ) inc_impact = gr.Dropdown( choices=["Critique / Critical", "Eleve / High", "Moyen / Medium", "Faible / Low"], label="Niveau d impact / Impact Level", ) classify_btn = gr.Button("Classifier / Classify", variant="primary") class_output = gr.Markdown() template_output = gr.Markdown() def classify_wrapper(lang_val, desc, services, impact): if not desc: msg = "Veuillez decrire l incident." if lang_val == "FR" else "Please describe the incident." return msg, "" # Map combined impact to single language impact_map = { "Critique / Critical": ("Critique", "Critical"), "Eleve / High": ("Eleve", "High"), "Moyen / Medium": ("Moyen", "Medium"), "Faible / Low": ("Faible", "Low"), } fr_imp, en_imp = impact_map.get(impact, ("Faible", "Low")) imp = fr_imp if lang_val == "FR" else en_imp return classify_incident(lang_val, desc, services, imp) classify_btn.click( fn=classify_wrapper, inputs=[lang_state, inc_desc, inc_services, inc_impact], outputs=[class_output, template_output], ) with gr.Tab("Preparation TLPT / TLPT Readiness"): gr.Markdown("### Checklist de preparation TLPT / TLPT Readiness Checklist") gr.Markdown("*Threat-Led Penetration Testing (Articles 26-27 DORA)*") tlpt_sections = { "scope": "Definition du perimetre / Scope Definition", "testers": "Exigences testeurs externes / External Tester Requirements", "purple_team": "Planification Purple Team / Purple Team Planning", "remediation": "Suivi de remediation / Remediation Tracking", } tlpt_checkboxes = {} for section_key, section_label in tlpt_sections.items(): gr.Markdown(f"#### {section_label}") items_fr = TLPT_CHECKLIST["FR"][section_key] items_en = TLPT_CHECKLIST["EN"][section_key] combined = [f"{fr} / {en}" for fr, en in zip(items_fr, items_en)] cb = gr.CheckboxGroup( choices=combined, label=section_label, interactive=True, ) tlpt_checkboxes[section_key] = cb tlpt_btn = gr.Button("Evaluer la preparation / Assess Readiness", variant="primary") tlpt_output = gr.Markdown() def tlpt_assess(lang_val, scope_sel, testers_sel, purple_sel, remed_sel): sections = { "scope": (scope_sel, len(TLPT_CHECKLIST["FR"]["scope"])), "testers": (testers_sel, len(TLPT_CHECKLIST["FR"]["testers"])), "purple_team": (purple_sel, len(TLPT_CHECKLIST["FR"]["purple_team"])), "remediation": (remed_sel, len(TLPT_CHECKLIST["FR"]["remediation"])), } section_labels = { "scope": "Perimetre / Scope", "testers": "Testeurs / Testers", "purple_team": "Purple Team", "remediation": "Remediation", } total_checked = 0 total_items = 0 if lang_val == "FR": md = "## Resultat de la preparation TLPT\n\n" md += "| Section | Completude |\n|---|---|\n" else: md = "## TLPT Readiness Result\n\n" md += "| Section | Completeness |\n|---|---|\n" for sk, (selected, count) in sections.items(): n = len(selected) if selected else 0 total_checked += n total_items += count pct = (n / count * 100) if count > 0 else 0 md += f"| {section_labels[sk]} | {n}/{count} ({pct:.0f}%) |\n" overall_pct = (total_checked / total_items * 100) if total_items > 0 else 0 if lang_val == "FR": md += f"\n**Preparation globale : {overall_pct:.0f}%**\n\n" if overall_pct < 50: md += "Niveau : **Non pret** - Des actions significatives sont necessaires avant de lancer un TLPT.\n" elif overall_pct < 80: md += "Niveau : **En cours** - Finalisez les elements manquants avant le lancement.\n" else: md += "Niveau : **Pret** - Vous pouvez planifier le TLPT.\n" else: md += f"\n**Overall Readiness: {overall_pct:.0f}%**\n\n" if overall_pct < 50: md += "Level: **Not Ready** - Significant actions needed before launching TLPT.\n" elif overall_pct < 80: md += "Level: **In Progress** - Finalize missing items before launch.\n" else: md += "Level: **Ready** - You can schedule the TLPT.\n" return md tlpt_btn.click( fn=tlpt_assess, inputs=[lang_state] + list(tlpt_checkboxes.values()), outputs=[tlpt_output], ) with gr.Tab("Calendrier & Sanctions / Timeline & Penalties"): gr.Markdown(""" ## DORA Timeline / Calendrier DORA | Date | Event / Evenement | |---|---| | **27 Dec 2022** | DORA published in Official Journal / Publication au Journal Officiel | | **17 Jan 2023** | Entry into force / Entree en vigueur | | **17 Jan 2024** | First batch RTS/ITS published / Publication premier lot RTS/ITS | | **17 Jul 2024** | Second batch RTS/ITS published / Publication deuxieme lot RTS/ITS | | **17 Jan 2025** | **Application date / Date d application** | | **17 Jan 2025** | Entities must be fully compliant / Les entites doivent etre pleinement conformes | | **2025-2026** | First supervisory reviews / Premieres revues de supervision | --- ## Penalty Framework / Cadre des sanctions ### For Financial Entities / Pour les entites financieres : - **Administrative penalties** up to **1% of average daily global turnover** of the preceding business year, imposed **daily** until compliance is achieved, for a maximum of **6 months** - Competent authorities may issue **public statements** identifying the entity and the nature of the breach - **Cease and desist orders** / Injonctions de mise en conformite - **Temporary bans** on management body members / Interdictions temporaires pour les membres de direction ### For Critical ICT Third-Party Providers / Pour les prestataires ICT tiers critiques : - **Periodic penalty payments** of up to **1% of average daily worldwide turnover** in the preceding business year - The Lead Overseer can impose penalties of up to **2% of annual worldwide turnover** for critical ICT third-party providers that fail to comply with oversight recommendations - **Maximum daily penalty period: 6 months** ### Aggravating factors / Facteurs aggravants : - Intentional breach / Infraction intentionnelle - Failure to take remedial action / Absence de mesures correctives - Repeated breaches / Infractions repetees - Financial gain from the breach / Gain financier tire de l infraction ### Mitigating factors / Facteurs attenuants : - Prompt remedial action / Mesures correctives rapides - Cooperation with authorities / Cooperation avec les autorites - First-time offence / Premiere infraction - Self-reporting / Auto-signalement --- *Source: Regulation (EU) 2022/2554 (DORA), Articles 50-52* """) with gr.Tab("Ressources / Resources"): gr.Markdown(""" ## Ressources DORA / DORA Resources ### Articles AYI-NEDJIMI Consultants - [DORA 2026 : Bilan de conformite](https://ayinedjimi-consultants.fr/articles/conformite/dora-2026-bilan-conformite.html) - Guide complet sur la conformite DORA - [Site AYI-NEDJIMI Consultants](https://ayinedjimi-consultants.fr) - Conseil en cybersecurite et conformite ### Official Texts / Textes officiels - [Regulation (EU) 2022/2554 - DORA](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32022R2554) - Full text / Texte integral - [EBA DORA Page](https://www.eba.europa.eu/regulation-and-policy/operational-resilience) - RTS/ITS and guidelines - [ESMA DORA Resources](https://www.esma.europa.eu/policy-activities/digital-operational-resilience-act) - ESMA implementation - [EIOPA DORA Page](https://www.eiopa.europa.eu/digital-operational-resilience-act-dora_en) - Insurance sector guidance ### Frameworks & Standards / Cadres et normes - [TIBER-EU Framework](https://www.ecb.europa.eu/paym/cyber-resilience/tiber-eu/html/index.en.html) - Threat-Led Penetration Testing - [ISO 27001:2022](https://www.iso.org/standard/27001) - Information Security Management - [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework) - Complementary framework - [COBIT 2019](https://www.isaca.org/resources/cobit) - IT Governance ### Tools & Datasets / Outils et jeux de donnees - [AYI-NEDJIMI Cybersecurity Collection](https://huggingface.co/collections/AYI-NEDJIMI/cybersecurity-datasets-and-tools-by-ayi-nedjimi-698e4b5777848dba76c8b169) - Datasets and tools on Hugging Face ### Community / Communaute - [FS-ISAC](https://www.fsisac.com/) - Financial Services ISAC - [ENISA](https://www.enisa.europa.eu/) - EU Agency for Cybersecurity - [FIRST](https://www.first.org/) - Forum of Incident Response and Security Teams """) # Language toggle updates state lang_toggle.change(fn=lambda x: x, inputs=[lang_toggle], outputs=[lang_state]) gr.HTML(FOOTER_HTML) # --------------------------------------------------------------------------- # Launch # --------------------------------------------------------------------------- if __name__ == "__main__": demo.launch()