mirror of
https://github.com/tips-of-mine/gestion-certificats2.git
synced 2025-06-28 12:48:42 +02:00
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:
@ -133,9 +133,38 @@ class CertificateController
|
|||||||
}
|
}
|
||||||
$functionalPerimeterName = $perimeter['name'];
|
$functionalPerimeterName = $perimeter['name'];
|
||||||
|
|
||||||
// Préparer la commande du script shell
|
// Extraire ROOT_DOMAIN du certificat CA racine pour SAN et OCSP
|
||||||
// Important: utiliser escapeshellarg pour protéger les arguments
|
$rootCaCertPath = ROOT_CA_PATH . '/certs/ca.cert.pem';
|
||||||
$command = escapeshellcmd(SCRIPTS_PATH . '/create_cert.sh') . ' ' .
|
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($subdomainName) . ' ' .
|
||||||
escapeshellarg($functionalPerimeterName);
|
escapeshellarg($functionalPerimeterName);
|
||||||
|
|
||||||
@ -144,8 +173,11 @@ class CertificateController
|
|||||||
// Exécuter le script shell
|
// Exécuter le script shell
|
||||||
$output = shell_exec($command . ' 2>&1'); // Redirige stderr vers stdout
|
$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)
|
// Vérifier le résultat du script
|
||||||
if (strpos($output, "Certificat '${subdomainName}.${functionalPerimeterName}.cert' créé avec succès") !== false) {
|
// 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)
|
// Extraire la date d'expiration du certificat créé (en lisant le fichier cert ou en estimant 1 an)
|
||||||
$certFileName = "{$subdomainName}.{$functionalPerimeterName}.cert.pem";
|
$certFileName = "{$subdomainName}.{$functionalPerimeterName}.cert.pem";
|
||||||
$fullCertPath = INTERMEDIATE_CA_PATH_BASE . "/{$functionalPerimeterName}/certs/{$certFileName}";
|
$fullCertPath = INTERMEDIATE_CA_PATH_BASE . "/{$functionalPerimeterName}/certs/{$certFileName}";
|
||||||
|
@ -42,10 +42,10 @@ chmod 400 "$KEY_FILE" # Permissions strictes
|
|||||||
# Le Common Name (CN) est important pour les certificats SSL/TLS
|
# Le Common Name (CN) est important pour les certificats SSL/TLS
|
||||||
openssl req -new -sha256 -key "$KEY_FILE" -out "$CSR_FILE" \
|
openssl req -new -sha256 -key "$KEY_FILE" -out "$CSR_FILE" \
|
||||||
-subj "/C=FR/ST=Hauts-de-France/L=Roubaix/O=GestionCertif/OU=${FUNCTIONAL_PERIMETER_NAME}/CN=${SUBDOMAIN_OR_CN_NAME}.cert-gestion.local" \
|
-subj "/C=FR/ST=Hauts-de-France/L=Roubaix/O=GestionCertif/OU=${FUNCTIONAL_PERIMETER_NAME}/CN=${SUBDOMAIN_OR_CN_NAME}.cert-gestion.local" \
|
||||||
-reqexts usr_cert -config "$INTERMEDIATE_CNF" # Utilise le CNF de l'intermédiaire et ses extensions usr_cert
|
-reqexts v3_leaf -config "$INTERMEDIATE_CNF" # Utilise le CNF de l'intermédiaire et ses extensions v3_leaf
|
||||||
|
|
||||||
# Signer la CSR avec le CA intermédiaire
|
# Signer la CSR avec le CA intermédiaire
|
||||||
openssl ca -batch -config "$INTERMEDIATE_CNF" -extensions usr_cert -days 365 -notext -md sha256 \
|
openssl ca -batch -config "$INTERMEDIATE_CNF" -extensions v3_leaf -days 365 -notext -md sha256 \
|
||||||
-in "$CSR_FILE" \
|
-in "$CSR_FILE" \
|
||||||
-out "$CERT_FILE"
|
-out "$CERT_FILE"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user