Système de notification de mise à jour de Dangerzone : Architecture et implémentation

Présentation du projet

Dangerzone est un outil open source conçu pour convertir des documents potentiellement dangereux (PDF, fichiers bureautiques, images) en PDF sécurisés. Son système de mise à jour intègre une stratégie de vérification asynchrone pour fournir les dernières correctifs de sécurité sans impacter l'expérience utilisaetur.

Conception architecturale

Le mécanisme repose sur une architecture modulaire avec composants principaux : un gestionnaire de préférences utilisateur, un contrôleur de fréquence, un client API et une interface de notification. Un modèle à états régit le cycle de vérification des mises à jour.

Détails d'implémentation des fonctionnalités

1. Gestion des préférences utilisateur

Le système adopte une approche progressive pour recueillir le consentement de l'utilisateur :

def verifier_autorisation_mise_a_jour(self) -> bool:
    if self.parametres.get("autorisation_mise_a_jour") is not None:
        return self.parametres["autorisation_mise_a_jour"]
    
    if systeme_exploitation() == "Linux" and not environnement_dev():
        self.parametres["autorisation_mise_a_jour"] = False
        return False
    
    if not self.horodatage_derniere_verification:
        self.horodatage_derniere_verification = 0
        self.sauvegarder_configuration()
        return False
    
    choix = solliciter_consentement_utilisateur()
    self.parametres["autorisation_mise_a_jour"] = choix
    return choix

2. Mécanisme de temporisation intelligent

Un intervalle de 12 heures entre les vérifications réduit la charge réseau :

INTERVALLE_VERIFICATION_SEC = 43200

def appliquer_temporisation(self) -> bool:
    horodatage_courant = obtenir_temps_actuel()
    dernier_check = self.parametres["horodatage_derniere_verification"]
    if horodatage_courant < dernier_check + INTERVALLE_VERIFICATION_SEC:
        logger.debug("Temporisation active")
        return True
    return False

3. Intégration avec l'API GitHub

Les informations de version sont récupérées via l'endpoint des releases GitHub :

Point d'accès Timeout Traitement
https://api.github.com/repos/freedomofpress/dangerzone/releases/latest 15 secondes Analyse JSON et conversion Markdown
def recuperer_derniere_version(self) -> BulletinMiseAJour:
    try:
        reponse = requetes.get(self.ADRESSE_API, timeout=self.DELAI_REQUETE)
        if reponse.status_code != 200:
            raise Exception(f"Erreur HTTP {reponse.status_code}")
        
        donnees = reponse.json()
        numero_version = donnees["tag_name"].replace("v", "")
        journal_modifications = convertir_markdown(donnees["body"])
        return BulletinMiseAJour(version=numero_version, changelog=journal_modifications)
    except Exception as e:
        raise Exception(f"Échec de la récupération : {e}")

4. Traitement asynchrone

L'utilisation de threads Qt assure une vérification non bloquante :

class ThreadVerification(QtCore.QThread):
    signal_fin = QtCore.Signal(BulletinMiseAJour)
    
    def run(self) -> None:
        resultat = effectuer_verification()
        self.signal_fin.emit(resultat)

Interface utilisateur

Indicateurs visuels dans le menu

État Icône Signification
Mise à jour disponible Point vert Nouvelle version téléchargeable
Erreur de vérification Point rouge Échec de la procédure
État normal Icône par défaut Aucune mise à jour

Dialogue de notification

def presenter_mise_a_jour(self) -> None:
    version_dispo = self.parametres["derniere_version"]
    details = self.parametres["journal_mise_a_jour"]
    
    conteneur_details = WidgetDeroulable("Nouvelles fonctionnalités")
    zone_affichage = QtWidgets.QTextBrowser()
    zone_affichage.setHtml(details)
    
    fenetre = BoiteDialogue(
        self.app,
        titre=f"Version {version_dispo} de Dangerzone",
        corps=MESSAGE_NOTIFICATION,
        element_central=conteneur_details,
        bouton_valider="Compris",
        sans_annulation=True
    )
    fenetre.afficher()

Gestion des erreurs

def traiter_resultat_verification(self, bulletin: BulletinMiseAJour) -> None:
    if bulletin.est_erreur:
        compte_erreurs = self.parametres["nb_erreurs_consecutives"] + 1
        self.parametres["nb_erreurs_consecutives"] = compte_erreurs
        
        if compte_erreurs < 3:
            logger.debug(f"Erreur non signalée ({compte_erreurs})")
            return
        
        self.bouton_menu.changer_icone(ICONE_ERREUR)
        self.afficher_alerte_erreur()

Sécurité et confidentialité

Mesure Implémentation Objectif
Limitation de fréquence Intervalle de 12 heures Réduire l'empreinte réseau
Désactivation sur Linux Comportement par défaut Respect de la vie privée
Contrôle des timeouts Expiration après 15 secondes Éviter les blocages

Le système respecte les principes de minimisation des données : aucune collecte d'informations personnelles, requêtes uniquement en lecture sur l'API publique.

Paramètres de configuration

Clé Type Valeur par défaut Description
autorisation_mise_a_jour Booléen optionnel Non défini Préférence utilisateur pour les mises à jour
horodatage_derniere_verification Entier 0 Timestamp de la dernière vérification
derniere_version Chaîne Version courante Version mise en cache
journal_mise_a_jour Chaîne Vide Journal des modifications en cache
nb_erreurs_consecutives Entier 0 Compteur d'échecs consécutifs

Recommandations

Pour les utilisateurs standards

  • Activer les vérifications automatiques pour bénéficier des correctifs de sécurité
  • Effectuer des vérifications manuelles régulières même si le système automatique est désactivé
  • Prêter attention aux indicateurs d'erreur pour identifier les problèmes de connectivité

Pour les environnements sensibles

  • Désactiver les mises à jour automatiques dans les réseaux isolés (air-gap)
  • Personnaliser les sources de mise à jour pour les déploiements internes
  • Surveiller les journaux pour tracer l'activité des vérifications

Pour les développeurs

  • Tester le flux complet de vérification et la gestion des erreurs
  • Envisager l'ajout de signatures cryptographiques pour valider les paquets
  • Prévoir des mécanismes de restauration en cas d'échec de mise à jour

Étiquettes: Dangerzone Python Qt github-api PDF

Publié le 7 juin à 00h30