From d6d1c9ad82dbcccd49badbdba204a510de700da8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:02:15 +0200 Subject: [PATCH] feat(database): add CA certificate generation for database servers --- app/Actions/Database/StartDragonfly.php | 11 ++++++ app/Actions/Database/StartKeydb.php | 11 ++++++ app/Actions/Database/StartMariadb.php | 11 ++++++ app/Actions/Database/StartMongodb.php | 10 +++++ app/Actions/Database/StartMysql.php | 11 ++++++ app/Actions/Database/StartPostgresql.php | 11 ++++++ app/Actions/Database/StartRedis.php | 11 ++++++ .../Project/Database/Dragonfly/General.php | 15 ++++++- app/Models/Server.php | 39 +++++++++++++++++++ 9 files changed, 129 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartDragonfly.php b/app/Actions/Database/StartDragonfly.php index 882ed3c2e..38ad99d2e 100644 --- a/app/Actions/Database/StartDragonfly.php +++ b/app/Actions/Database/StartDragonfly.php @@ -57,6 +57,17 @@ class StartDragonfly $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartKeydb.php b/app/Actions/Database/StartKeydb.php index 311b5094a..59bcd4123 100644 --- a/app/Actions/Database/StartKeydb.php +++ b/app/Actions/Database/StartKeydb.php @@ -58,6 +58,17 @@ class StartKeydb $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php index c29273a66..13dba4b43 100644 --- a/app/Actions/Database/StartMariadb.php +++ b/app/Actions/Database/StartMariadb.php @@ -59,6 +59,17 @@ class StartMariadb $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php index 3ea8287ac..ff0233e62 100644 --- a/app/Actions/Database/StartMongodb.php +++ b/app/Actions/Database/StartMongodb.php @@ -63,6 +63,16 @@ class StartMongodb $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php index a2e08c316..5d5611e07 100644 --- a/app/Actions/Database/StartMysql.php +++ b/app/Actions/Database/StartMysql.php @@ -59,6 +59,17 @@ class StartMysql $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php index 97e565ec8..a40eac17b 100644 --- a/app/Actions/Database/StartPostgresql.php +++ b/app/Actions/Database/StartPostgresql.php @@ -64,6 +64,17 @@ class StartPostgresql $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 9e7a2a084..68a1f3fe3 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -58,6 +58,17 @@ class StartRedis $server = $this->database->destination->server; $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php index 9aef91ac4..0fffbef31 100644 --- a/app/Livewire/Project/Database/Dragonfly/General.php +++ b/app/Livewire/Project/Database/Dragonfly/General.php @@ -214,10 +214,23 @@ class General extends Component return; } - $caCert = SslCertificate::where('server_id', $existingCert->server_id) + $server = $this->database->destination->server; + + $caCert = SslCertificate::where('server_id', $server->id) ->where('is_ca_certificate', true) ->first(); + if (! $caCert) { + $server->generateCaCertificate(); + $caCert = SslCertificate::where('server_id', $server->id)->where('is_ca_certificate', true)->first(); + } + + if (! $caCert) { + $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); + + return; + } + SslHelper::generateSslCertificate( commonName: $existingCert->commonName, subjectAlternativeNames: $existingCert->subjectAlternativeNames ?? [], diff --git a/app/Models/Server.php b/app/Models/Server.php index fedb95697..56aa58e87 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -7,7 +7,9 @@ use App\Actions\Server\InstallDocker; use App\Actions\Server\StartSentinel; use App\Enums\ProxyTypes; use App\Events\ServerReachabilityChanged; +use App\Helpers\SslHelper; use App\Jobs\CheckAndStartSentinelJob; +use App\Jobs\RegenerateSslCertJob; use App\Notifications\Server\Reachable; use App\Notifications\Server\Unreachable; use App\Services\ConfigurationRepository; @@ -1337,4 +1339,41 @@ $schema://$host { $configRepository = app(ConfigurationRepository::class); $configRepository->disableSshMux(); } + + public function generateCaCertificate() + { + try { + ray('Generating CA certificate for server', $this->id); + SslHelper::generateSslCertificate( + commonName: 'Coolify CA Certificate', + serverId: $this->id, + isCaCertificate: true, + validityDays: 10 * 365 + ); + $caCertificate = SslCertificate::where('server_id', $this->id)->where('is_ca_certificate', true)->first(); + ray('CA certificate generated', $caCertificate); + if ($caCertificate) { + $certificateContent = $caCertificate->ssl_certificate; + $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; + + $commands = collect([ + "mkdir -p $caCertPath", + "chown -R 9999:root $caCertPath", + "chmod -R 700 $caCertPath", + "rm -rf $caCertPath/coolify-ca.crt", + "echo '{$certificateContent}' > $caCertPath/coolify-ca.crt", + "chmod 644 $caCertPath/coolify-ca.crt", + ]); + + instant_remote_process($commands, $this, false); + + dispatch(new RegenerateSslCertJob( + server_id: $this->id, + force_regeneration: true + )); + } + } catch (\Throwable $e) { + return handleError($e); + } + } }