diff --git a/app/src/Controllers/CertificateController.php b/app/src/Controllers/CertificateController.php index b92b5e9..bbb5b9f 100644 --- a/app/src/Controllers/CertificateController.php +++ b/app/src/Controllers/CertificateController.php @@ -238,16 +238,14 @@ class CertificateController exit(); } - // Empêcher la révocation des certificats Root ou Intermédiaires via l'interface - if ($cert['type'] === 'root' || $cert['type'] === 'intermediate') { - $_SESSION['error'] = $this->langService->__('cert_revoke_error_ca_revocation'); + // Empêcher la révocation des certificats Root via l'interface + if ($cert['type'] === 'root') { + $_SESSION['error'] = $this->langService->__('cert_revoke_error_ca_revocation'); // Peut-être une clé dédiée pour root si le message doit être différent header('Location: /certificates'); exit(); } - // Préparer le nom de base du certificat pour le script (sans l'extension .pem) - $certBaseName = str_replace('.cert.pem', '.cert', $cert['name']); - $functionalPerimeterName = $cert['perimeter_name']; + $functionalPerimeterName = $cert['perimeter_name']; // Déjà récupéré plus haut, mais utile ici aussi // Vérifier si le certificat n'est pas déjà révoqué dans la DB if ($cert['is_revoked']) { @@ -256,29 +254,79 @@ class CertificateController exit(); } - // Appeler le script shell de révocation - $command = escapeshellcmd(SCRIPTS_PATH . '/revoke_cert.sh') . ' ' . - escapeshellarg($certBaseName) . ' ' . - escapeshellarg($functionalPerimeterName); + if ($cert['type'] === 'intermediate') { + // Logique de révocation pour les certificats intermédiaires + $intermediateCertPath = "/opt/tls/intermediate/" . $functionalPerimeterName . "/certs/" . $cert['name']; + $rootCaConfigPath = "/opt/tls/root/openssl.cnf"; // Chemin vers la configuration OpenSSL du CA Racine + $rootCaCrlPath = "/opt/tls/root/crl/crl.pem"; // Chemin vers la CRL du CA Racine - $this->logService->log('info', "Tentative de révocation du certificat '{$cert['name']}' pour le périmètre '$functionalPerimeterName'. Commande: '$command'", $userId, $ipAddress); + // Commande pour révoquer le certificat intermédiaire avec le CA Racine + $revokeCmd = sprintf( + "openssl ca -batch -config %s -revoke %s", + escapeshellarg($rootCaConfigPath), + escapeshellarg($intermediateCertPath) + ); - $output = shell_exec($command . ' 2>&1'); + $this->logService->log('info', "Tentative de révocation du certificat intermédiaire '{$cert['name']}' pour le périmètre '$functionalPerimeterName'. Commande: '$revokeCmd'", $userId, $ipAddress); + $outputRevoke = shell_exec($revokeCmd . ' 2>&1'); - if (strpos($output, "Certificat '$certBaseName' révoqué avec succès.") !== false) { - // Mettre à jour le statut du certificat dans la base de données - $stmt = $this->db->prepare("UPDATE certificates SET is_revoked = TRUE, revoked_at = NOW() WHERE id = ?"); - $stmt->execute([$certificateId]); + if (strpos($outputRevoke, "Data Base Updated") !== false || strpos($outputRevoke, "Successfully revoked certificate") !== false) { + // Commande pour régénérer la CRL du CA Racine + $generateCrlCmd = sprintf( + "openssl ca -batch -config %s -gencrl -out %s", + escapeshellarg($rootCaConfigPath), + escapeshellarg($rootCaCrlPath) + ); + + $this->logService->log('info', "Révocation réussie. Tentative de mise à jour de la CRL du CA Racine. Commande: '$generateCrlCmd'", $userId, $ipAddress); + $outputCrl = shell_exec($generateCrlCmd . ' 2>&1'); + + // Vérifier si la CRL a été générée et si le fichier existe + if ((strpos($outputCrl, "CRL Generated") !== false || strpos($outputCrl, "CRL generated") !== false) && file_exists($rootCaCrlPath)) { + // Mettre à jour le statut du certificat dans la base de données + $stmt_update = $this->db->prepare("UPDATE certificates SET is_revoked = TRUE, revoked_at = NOW() WHERE id = ?"); + $stmt_update->execute([$certificateId]); + + $this->logService->log('info', "Certificat intermédiaire '{$cert['name']}' révoqué et CRL du CA Racine mise à jour.", $userId, $ipAddress); + $_SESSION['success'] = $this->langService->__('cert_revoke_success_intermediate', ['name' => $cert['name']]); + } else { + $this->logService->log('error', "Échec de la mise à jour de la CRL du CA Racine pour le cert intermédiaire '{$cert['name']}'. Output CRL: $outputCrl. Output Revoke: $outputRevoke", $userId, $ipAddress); + $_SESSION['error'] = $this->langService->__('cert_revoke_warn_crl_update_failed_intermediate', ['name' => $cert['name']]); + } + } else { + $_SESSION['error'] = $this->langService->__('cert_revoke_error_intermediate', ['name' => $cert['name'], 'output' => htmlspecialchars($outputRevoke)]); + $this->logService->log('error', "Échec de la révocation du certificat intermédiaire '{$cert['name']}'. Output: $outputRevoke", $userId, $ipAddress); + } + header('Location: /certificates'); + exit(); - $this->logService->log('info', "Certificat '{$cert['name']}' révoqué et enregistré en DB.", $userId, $ipAddress); - $_SESSION['success'] = $this->langService->__('cert_revoke_success'); } else { - $_SESSION['error'] = $this->langService->__('cert_revoke_error', ['output' => htmlspecialchars($output)]); - $this->logService->log('error', "Échec révocation certificat '{$cert['name']}': $output", $userId, $ipAddress); - } + // Logique existante pour les certificats 'simple' + $certBaseName = str_replace('.cert.pem', '.cert', $cert['name']); - header('Location: /certificates'); - exit(); + // Appeler le script shell de révocation + $command = escapeshellcmd(SCRIPTS_PATH . '/revoke_cert.sh') . ' ' . + escapeshellarg($certBaseName) . ' ' . + escapeshellarg($functionalPerimeterName); + + $this->logService->log('info', "Tentative de révocation du certificat simple '{$cert['name']}' pour le périmètre '$functionalPerimeterName'. Commande: '$command'", $userId, $ipAddress); + + $output = shell_exec($command . ' 2>&1'); + + if (strpos($output, "Certificat '$certBaseName' révoqué avec succès.") !== false) { + // Mettre à jour le statut du certificat dans la base de données + $stmt_update = $this->db->prepare("UPDATE certificates SET is_revoked = TRUE, revoked_at = NOW() WHERE id = ?"); + $stmt_update->execute([$certificateId]); + + $this->logService->log('info', "Certificat simple '{$cert['name']}' révoqué et enregistré en DB.", $userId, $ipAddress); + $_SESSION['success'] = $this->langService->__('cert_revoke_success'); + } else { + $_SESSION['error'] = $this->langService->__('cert_revoke_error', ['output' => htmlspecialchars($output)]); + $this->logService->log('error', "Échec révocation certificat simple '{$cert['name']}': $output", $userId, $ipAddress); + } + header('Location: /certificates'); + exit(); + } } /** diff --git a/app/src/Lang/fr.json b/app/src/Lang/fr.json index 203b1bb..d1d0dcc 100644 --- a/app/src/Lang/fr.json +++ b/app/src/Lang/fr.json @@ -61,7 +61,7 @@ "cert_create_error": "Erreur lors de la création du certificat: {output}", "cert_revoke_error_id_missing": "ID du certificat manquant pour la révocation.", "cert_revoke_error_not_found": "Certificat introuvable pour la révocation.", - "cert_revoke_error_ca_revocation": "Les certificats ROOT et INTERMÉDIAIRES ne peuvent pas être révoqués via l'interface pour des raisons de sécurité PKI.", + "cert_revoke_error_ca_revocation": "Les certificats ROOT ne peuvent pas être révoqués via l'interface pour des raisons de sécurité PKI.", "cert_revoke_error_already_revoked": "Ce certificat est déjà révoqué.", "cert_revoke_success": "Certificat révoqué avec succès.", "cert_revoke_error": "Erreur lors de la révocation du certificat: {output}", @@ -80,5 +80,8 @@ "user_delete_success": "Utilisateur '{username}' supprimé avec succès.", "user_delete_error_not_found": "Utilisateur introuvable pour la suppression.", "user_delete_error_db": "Erreur lors de la suppression de l'utilisateur dans la base de données.", - "self_delete_not_allowed": "Vous ne pouvez pas vous supprimer vous-même." + "self_delete_not_allowed": "Vous ne pouvez pas vous supprimer vous-même.", + "cert_revoke_success_intermediate": "Le certificat intermédiaire '{name}' a été révoqué avec succès et la CRL du CA Racine a été mise à jour.", + "cert_revoke_warn_crl_update_failed_intermediate": "Le certificat intermédiaire '{name}' a été révoqué, mais la mise à jour de la CRL du CA Racine a rencontré un problème. Veuillez contacter un administrateur.", + "cert_revoke_error_intermediate": "Erreur lors de la révocation du certificat intermédiaire '{name}': {output}" } diff --git a/app/src/Views/certificates/index.php b/app/src/Views/certificates/index.php index d06a411..ba6d7a5 100644 --- a/app/src/Views/certificates/index.php +++ b/app/src/Views/certificates/index.php @@ -49,8 +49,8 @@ require_once APP_ROOT_DIR . '/src/Views/shared/header.php';