mirror of
https://github.com/dyzulk/trustlab-api.git
synced 2026-01-26 13:22:05 +07:00
feat: implement bulkRenewStrategy and renewAll endpoint in OpenSslService
This commit is contained in:
@@ -78,6 +78,25 @@ class RootCaApiController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renewAll(Request $request)
|
||||||
|
{
|
||||||
|
$this->authorizeAdminOrOwner();
|
||||||
|
$days = (int) $request->input('days', 3650);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->sslService->bulkRenewStrategy($days);
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Entire CA Chain (Root & Intermediates) renewed successfully.'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Bulk renewal failed: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function syncCrtOnly(Request $request)
|
public function syncCrtOnly(Request $request)
|
||||||
{
|
{
|
||||||
$this->authorizeAdminOrOwner();
|
$this->authorizeAdminOrOwner();
|
||||||
|
|||||||
@@ -377,8 +377,16 @@ class OpenSslService
|
|||||||
$issuerCert = null;
|
$issuerCert = null;
|
||||||
$issuerKey = $privKey;
|
$issuerKey = $privKey;
|
||||||
} else {
|
} else {
|
||||||
// Intermediate is signed by Root
|
// Intermediate is signed by the LATEST Root
|
||||||
$root = CaCertificate::where('ca_type', 'root')->first();
|
$root = CaCertificate::where('ca_type', 'root')
|
||||||
|
->where('is_latest', true)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
// Fallback if no is_latest yet (during initial setuptransition)
|
||||||
|
if (!$root) {
|
||||||
|
$root = CaCertificate::where('ca_type', 'root')->latest()->first();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$root) throw new \Exception('Root CA not found for signing intermediate renewal.');
|
if (!$root) throw new \Exception('Root CA not found for signing intermediate renewal.');
|
||||||
$issuerCert = $root->cert_content;
|
$issuerCert = $root->cert_content;
|
||||||
$issuerKey = openssl_pkey_get_private($root->key_content);
|
$issuerKey = openssl_pkey_get_private($root->key_content);
|
||||||
@@ -414,6 +422,67 @@ class OpenSslService
|
|||||||
if ($configFile && file_exists($configFile)) unlink($configFile);
|
if ($configFile && file_exists($configFile)) unlink($configFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a coordinated renewal of the entire CA chain.
|
||||||
|
* Order: Root -> Intermediates.
|
||||||
|
*/
|
||||||
|
public function bulkRenewStrategy(int $days = 3650)
|
||||||
|
{
|
||||||
|
// 1. Get current latest Root
|
||||||
|
$root = CaCertificate::where('ca_type', 'root')->where('is_latest', true)->first();
|
||||||
|
if (!$root) throw new \Exception("Current Root CA not found.");
|
||||||
|
|
||||||
|
// 2. Renew Root
|
||||||
|
$newRoot = $this->executeRenewalFlow($root, $days);
|
||||||
|
|
||||||
|
// 3. Renew Intermediates using the NEW Root
|
||||||
|
$intermediates = CaCertificate::whereIn('ca_type', ['intermediate_2048', 'intermediate_4096'])
|
||||||
|
->where('is_latest', true)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($intermediates as $int) {
|
||||||
|
$this->executeRenewalFlow($int, $days);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Final Mass Sync
|
||||||
|
$this->syncAllBundles();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal helper to handle the DB + CDN flow for a single renewal.
|
||||||
|
*/
|
||||||
|
private function executeRenewalFlow(CaCertificate $cert, int $days)
|
||||||
|
{
|
||||||
|
$newData = $this->renewCaCertificate($cert, $days);
|
||||||
|
|
||||||
|
// Unset latest for others of same type/CN
|
||||||
|
CaCertificate::where('ca_type', $cert->ca_type)
|
||||||
|
->where('common_name', $cert->common_name)
|
||||||
|
->update(['is_latest' => false]);
|
||||||
|
|
||||||
|
// Create new
|
||||||
|
$newCert = CaCertificate::create([
|
||||||
|
'ca_type' => $cert->ca_type,
|
||||||
|
'common_name' => $cert->common_name,
|
||||||
|
'organization' => $cert->organization,
|
||||||
|
'key_content' => $cert->key_content,
|
||||||
|
'cert_content' => $newData['cert_content'],
|
||||||
|
'serial_number' => $newData['serial_number'],
|
||||||
|
'valid_from' => $newData['valid_from'],
|
||||||
|
'valid_to' => $newData['valid_to'],
|
||||||
|
'is_latest' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Sync to CDN
|
||||||
|
$this->uploadPublicCertsOnly($newCert, 'both');
|
||||||
|
$this->uploadIndividualInstallersOnly($newCert, 'both');
|
||||||
|
|
||||||
|
return $newCert;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate Windows Installer (.bat)
|
* Generate Windows Installer (.bat)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ Route::middleware(['auth:sanctum'])->group(function () {
|
|||||||
Route::post('/admin/ca-certificates/sync-installers', [RootCaApiController::class, 'syncInstallersOnly']);
|
Route::post('/admin/ca-certificates/sync-installers', [RootCaApiController::class, 'syncInstallersOnly']);
|
||||||
Route::post('/admin/ca-certificates/sync-bundles', [RootCaApiController::class, 'syncBundlesOnly']);
|
Route::post('/admin/ca-certificates/sync-bundles', [RootCaApiController::class, 'syncBundlesOnly']);
|
||||||
Route::post('/admin/ca-certificates/{certificate}/renew', [RootCaApiController::class, 'renew']);
|
Route::post('/admin/ca-certificates/{certificate}/renew', [RootCaApiController::class, 'renew']);
|
||||||
|
Route::post('/admin/ca-certificates/renew-all', [RootCaApiController::class, 'renewAll']);
|
||||||
Route::post('/admin/ca-certificates/{certificate}/promote', [RootCaApiController::class, 'promote']);
|
Route::post('/admin/ca-certificates/{certificate}/promote', [RootCaApiController::class, 'promote']);
|
||||||
|
|
||||||
// API Keys Management
|
// API Keys Management
|
||||||
|
|||||||
Reference in New Issue
Block a user