mirror of
https://github.com/tips-of-mine/gestion-certificats2.git
synced 2025-06-28 09:18:42 +02:00
Merge pull request #10 from tips-of-mine/fix/functional-perimeter-creation
Fix/functional perimeter creation
This commit is contained in:
@ -81,6 +81,8 @@ if ($userCount === 0 || !$rootCertExists) {
|
||||
if (isset($_POST['admin_password'], $_POST['root_domain']) && !empty($_POST['admin_password']) && !empty($_POST['root_domain'])) {
|
||||
$_SESSION['init_admin_password'] = $_POST['admin_password'];
|
||||
$_SESSION['init_root_domain'] = $_POST['root_domain'];
|
||||
$logService->log('debug', 'Initialisation - POST data received: admin_password_present=' . !empty($_POST['admin_password']) . ', root_domain=' . ($_POST['root_domain'] ?? 'not_set_or_empty'));
|
||||
$logService->log('debug', 'Initialisation - Session variables SET: init_admin_password_present=' . !empty($_SESSION['init_admin_password']) . ', init_root_domain=' . ($_SESSION['init_root_domain'] ?? 'not_set_or_empty'));
|
||||
header('Location: ' . $_SERVER['PHP_SELF']);
|
||||
exit();
|
||||
} else {
|
||||
@ -108,6 +110,25 @@ if ($userCount === 0 || !$rootCertExists) {
|
||||
if (!$rootCertExists) {
|
||||
echo "<p>Création du certificat Root CA en cours...</p>";
|
||||
$logService->log('info', 'Lancement de la création du certificat Root CA pour le domaine: ' . $_SESSION['init_root_domain'], null, $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
$logService->log('debug', 'Initialisation - About to call create_root_cert.sh. Value of $_SESSION[\'init_root_domain\']: ' . ($_SESSION['init_root_domain'] ?? 'NOT SET OR EMPTY'));
|
||||
if (empty($_SESSION['init_root_domain'])) {
|
||||
$logService->log('error', 'Initialisation - CRITICAL: $_SESSION[\'init_root_domain\'] is empty or not set right before calling create_root_cert.sh. Forcing display of error and form again.');
|
||||
// Code to re-display form or a clear error message, then exit.
|
||||
// This is to prevent the script from being called with an empty argument.
|
||||
echo "<p style='color: red;'><strong>Erreur Critique:</strong> La variable de session pour le domaine racine est vide avant d'appeler le script de création. Veuillez réessayer.</p>";
|
||||
// Minimal form for resubmission:
|
||||
echo "<form method='POST' action='" . htmlspecialchars($_SERVER['PHP_SELF']) . "'>";
|
||||
echo "<div><label for='admin_password'>Mot de passe administrateur initial :</label><input type='password' id='admin_password' name='admin_password' required></div>";
|
||||
echo "<div><label for='root_domain'>Domaine racine (ROOT_DOMAIN) pour le certificat CA :</label><input type='text' id='root_domain' name='root_domain' required><small>Exemple: exemple.com</small></div>";
|
||||
echo "<button type='submit'>Configurer</button>";
|
||||
echo "</form>";
|
||||
// Optionally, unset session variables to force re-entry of CAS 1.2 logic fully.
|
||||
unset($_SESSION['init_admin_password']);
|
||||
unset($_SESSION['init_root_domain']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Exécution du script shell de création de certificat root avec le domaine racine
|
||||
$command = escapeshellcmd(SCRIPTS_PATH . '/create_root_cert.sh ' . escapeshellarg($_SESSION['init_root_domain']));
|
||||
$output = shell_exec($command . ' 2>&1');
|
||||
|
@ -133,9 +133,38 @@ class CertificateController
|
||||
}
|
||||
$functionalPerimeterName = $perimeter['name'];
|
||||
|
||||
// Préparer la commande du script shell
|
||||
// Important: utiliser escapeshellarg pour protéger les arguments
|
||||
$command = escapeshellcmd(SCRIPTS_PATH . '/create_cert.sh') . ' ' .
|
||||
// Extraire ROOT_DOMAIN du certificat CA racine pour SAN et OCSP
|
||||
$rootCaCertPath = ROOT_CA_PATH . '/certs/ca.cert.pem';
|
||||
if (!file_exists($rootCaCertPath)) {
|
||||
$this->logService->log('error', "Certificat CA racine non trouvé pour extraction ROOT_DOMAIN lors de la création de cert feuille.", $userId, $ipAddress);
|
||||
$_SESSION['error'] = $this->langService->__('cert_create_error_root_cert_missing'); // Needs this translation key
|
||||
header('Location: /certificates/create');
|
||||
exit();
|
||||
}
|
||||
$subjectCommand = "openssl x509 -noout -subject -in " . escapeshellarg($rootCaCertPath);
|
||||
$subjectLine = shell_exec($subjectCommand);
|
||||
$rootDomain = null;
|
||||
if ($subjectLine && preg_match('/CN\s*=\s*ca\.([^\/,\s]+)/', $subjectLine, $matches)) {
|
||||
$rootDomain = $matches[1];
|
||||
}
|
||||
if (empty($rootDomain)) {
|
||||
$this->logService->log('error', "Impossible d'extraire ROOT_DOMAIN du cert CA racine (pour SAN). Regex: '/CN\s*=\s*ca\.([^\/,\s]+)/' Sujet: " . ($subjectLine ?: 'vide'), $userId, $ipAddress);
|
||||
$_SESSION['error'] = $this->langService->__('cert_create_error_root_domain_extraction'); // Needs this translation key
|
||||
header('Location: /certificates/create');
|
||||
exit();
|
||||
}
|
||||
$this->logService->log('info', "ROOT_DOMAIN extrait pour SAN/OCSP: $rootDomain", $userId, $ipAddress);
|
||||
|
||||
// Construire la valeur SAN
|
||||
$sanValue = "DNS:" . $subdomainName . "." . $functionalPerimeterName . "." . $rootDomain;
|
||||
|
||||
// Récupérer OCSP_URL
|
||||
$ocspUrl = OCSP_URL; // Constante de app/src/config/app.php
|
||||
|
||||
// Préparer la commande du script shell avec les variables d'environnement
|
||||
$scriptPath = SCRIPTS_PATH . '/create_cert.sh';
|
||||
$command = "OCSP_URL=" . escapeshellarg($ocspUrl) . " SAN=" . escapeshellarg($sanValue) . " " .
|
||||
escapeshellcmd($scriptPath) . ' ' .
|
||||
escapeshellarg($subdomainName) . ' ' .
|
||||
escapeshellarg($functionalPerimeterName);
|
||||
|
||||
@ -144,8 +173,11 @@ class CertificateController
|
||||
// Exécuter le script shell
|
||||
$output = shell_exec($command . ' 2>&1'); // Redirige stderr vers stdout
|
||||
|
||||
// Vérifier le résultat du script (simple vérification de chaîne, une meilleure parsage serait utile)
|
||||
if (strpos($output, "Certificat '${subdomainName}.${functionalPerimeterName}.cert' créé avec succès") !== false) {
|
||||
// Vérifier le résultat du script
|
||||
// Le script create_cert.sh sort "Certificat '$CERT_BASE_NAME' créé avec succès : $CERT_FILE"
|
||||
// où $CERT_BASE_NAME est "${SUBDOMAIN_OR_CN_NAME}.${FUNCTIONAL_PERIMETER_NAME}"
|
||||
$certBaseNameForCheck = $subdomainName . '.' . $functionalPerimeterName;
|
||||
if (strpos($output, "Certificat '" . $certBaseNameForCheck . "' créé avec succès :") !== false) {
|
||||
// Extraire la date d'expiration du certificat créé (en lisant le fichier cert ou en estimant 1 an)
|
||||
$certFileName = "{$subdomainName}.{$functionalPerimeterName}.cert.pem";
|
||||
$fullCertPath = INTERMEDIATE_CA_PATH_BASE . "/{$functionalPerimeterName}/certs/{$certFileName}";
|
||||
|
@ -89,6 +89,10 @@ class PerimeterController
|
||||
$perimeterName = trim($_POST['name'] ?? '');
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
$userId = $this->authService->getUserId();
|
||||
// La passphrase est optionnelle pour l'intermédiaire, mais le script attend l'argument.
|
||||
// Le script create_intermediate_cert.sh a été modifié pour accepter "EMPTY_STRING"
|
||||
// si aucune passphrase n'est fournie.
|
||||
$passphrase = trim($_POST['intermediate_passphrase'] ?? ''); // Assumons que cela vient du formulaire
|
||||
|
||||
if (empty($perimeterName)) {
|
||||
$_SESSION['error'] = $this->langService->__('perimeter_create_error_empty_name');
|
||||
@ -105,14 +109,58 @@ class PerimeterController
|
||||
exit();
|
||||
}
|
||||
|
||||
// Extraire ROOT_DOMAIN du certificat CA racine
|
||||
$rootCaCertPath = ROOT_CA_PATH . '/certs/ca.cert.pem';
|
||||
$rootDomain = null;
|
||||
if (!file_exists($rootCaCertPath)) {
|
||||
$this->logService->log('error', "Certificat CA racine non trouvé à: $rootCaCertPath", $userId, $ipAddress);
|
||||
$_SESSION['error'] = $this->langService->__('perimeter_create_error_root_cert_missing'); // Nouvelle clé de traduction
|
||||
header('Location: /perimeters/create');
|
||||
exit();
|
||||
}
|
||||
|
||||
$subjectCommand = "openssl x509 -noout -subject -in " . escapeshellarg($rootCaCertPath);
|
||||
$subjectLine = shell_exec($subjectCommand);
|
||||
|
||||
if ($subjectLine && preg_match('/CN\s*=\s*ca\.([^\/,\s]+)/', $subjectLine, $matches)) {
|
||||
$rootDomain = $matches[1];
|
||||
}
|
||||
|
||||
if (empty($rootDomain)) {
|
||||
$this->logService->log('error', "Impossible d'extraire ROOT_DOMAIN du certificat CA racine. Regex: '/CN\s*=\s*ca\.([^\/,\s]+)/' Sujet obtenu: " . ($subjectLine ?: 'vide ou non recupere'), $userId, $ipAddress);
|
||||
$_SESSION['error'] = $this->langService->__('perimeter_create_error_root_domain'); // Clé de traduction existante ou à ajouter
|
||||
header('Location: /perimeters/create');
|
||||
exit();
|
||||
}
|
||||
$this->logService->log('info', "ROOT_DOMAIN extrait avec succès: $rootDomain", $userId, $ipAddress);
|
||||
|
||||
// Appeler le script shell pour créer le certificat intermédiaire
|
||||
$command = escapeshellcmd(SCRIPTS_PATH . '/create_intermediate_cert.sh') . ' ' . escapeshellarg($perimeterName);
|
||||
// Retrieve OCSP_URL from defined constant
|
||||
$ocspUrl = OCSP_URL; // This constant is defined in app/src/config/app.php
|
||||
$sanValue = ''; // SAN is not typically needed for an intermediate CA, set to empty
|
||||
|
||||
$passphraseArg = !empty($passphrase) ? $passphrase : "EMPTY_STRING";
|
||||
|
||||
// Construct the shell command with environment variables
|
||||
// Note: escapeshellcmd is applied to the script path.
|
||||
// Environment variable values should also be safe.
|
||||
// Using escapeshellarg for values assigned to env vars is a good practice.
|
||||
$scriptPath = SCRIPTS_PATH . '/create_intermediate_cert.sh';
|
||||
$command = "OCSP_URL=" . escapeshellarg($ocspUrl) . " SAN=" . escapeshellarg($sanValue) . " " .
|
||||
escapeshellcmd($scriptPath) . ' ' .
|
||||
escapeshellarg($perimeterName) . ' ' .
|
||||
escapeshellarg($passphraseArg) . ' ' .
|
||||
escapeshellarg($rootDomain);
|
||||
|
||||
$this->logService->log('info', "Tentative de création du périmètre '$perimeterName' et de son certificat intermédiaire. Commande: '$command'", $userId, $ipAddress);
|
||||
|
||||
$output = shell_exec($command . ' 2>&1');
|
||||
|
||||
if (strpos($output, "Certificat Intermédiaire CA pour '$perimeterName' créé avec succès") !== false) {
|
||||
// La condition de succès doit correspondre à la sortie du script.
|
||||
// Le script create_intermediate_cert.sh se termine par :
|
||||
// echo "Certificat Intermédiaire CA pour '$FUNCTIONAL_PERIMETER_NAME' créé : $INTERMEDIATE_CERT"
|
||||
// Nous allons donc chercher une partie de cette chaîne.
|
||||
if (strpos($output, "Certificat Intermédiaire CA pour '$perimeterName' créé") !== false) {
|
||||
// Enregistrer le périmètre dans la base de données
|
||||
$stmt = $this->db->prepare("INSERT INTO functional_perimeters (name, intermediate_cert_name) VALUES (?, ?)");
|
||||
$intermediateCertFileName = "intermediate.cert.pem"; // Nom générique du fichier pour l'intermédiaire
|
||||
|
Reference in New Issue
Block a user