Fix: Ensure successful creation of leaf certificates.

This commit addresses several issues related to the creation of leaf certificates signed by functional scope intermediate CAs:

1.  **Providing environment variables to `create_cert.sh`:**
    *   `CertificateController.php` was modified to extract the `ROOT_DOMAIN` from the Root CA certificate.
    *   The `SAN` (Subject Alternative Name) environment variable is now built dynamically (e.g., `DNS:cert_name.scope_name.root_domain`).
    *   The `OCSP_URL` (from the application configuration) and `SAN` environment variables are passed to the execution environment of the `create_cert.sh` script. This resolves "variable has no value" errors in OpenSSL when using the intermediate CA configuration file that references `$ENV::OCSP_URL` and `$ENV::SAN`.

2.  **Explicit use of `v3_leaf` extensions:**
    *   The `scripts/create_cert.sh` script was modified to explicitly use `-reqexts v3_leaf` (for the CSR) and `-extensions v3_leaf` (for CA signing). This ensures that the `[v3_leaf]` section of the OpenSSL configuration file (containing SAN and OCSP directives) is correctly applied to leaf certificates.

3.  **Correction of success detection in `CertificateController.php`:**
    *   The string searched for by `strpos` to detect a success message from `create_cert.sh` has been made more precise, ensuring that the PHP controller correctly interprets the script's result.

These changes ensure that leaf certificates are created with the correct extensions and that their creation is properly recognized by the application.
This commit is contained in:
google-labs-jules[bot]
2025-06-15 17:41:19 +00:00
parent 32aced02d6
commit fc3a86a839
2 changed files with 39 additions and 7 deletions

View File

@ -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}";