This commit is contained in:
shimon 2024-11-08 14:43:30 +02:00
parent a6e9d58f12
commit b5efbdbb0f

View file

@ -22,7 +22,6 @@ use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\ID;
use Utopia\Database\Query; use Utopia\Database\Query;
use Utopia\Domains\Domain; use Utopia\Domains\Domain;
use Utopia\Fetch\Client;
use Utopia\Locale\Locale; use Utopia\Locale\Locale;
use Utopia\Logger\Log; use Utopia\Logger\Log;
use Utopia\Platform\Action; use Utopia\Platform\Action;
@ -44,18 +43,16 @@ class Certificates extends Action
$this $this
->desc('Certificates worker') ->desc('Certificates worker')
->inject('message') ->inject('message')
->inject('project')
->inject('dbForConsole') ->inject('dbForConsole')
->inject('queueForMails') ->inject('queueForMails')
->inject('queueForEvents') ->inject('queueForEvents')
->inject('queueForFunctions') ->inject('queueForFunctions')
->inject('log') ->inject('log')
->callback(fn (Message $message, Document $project, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log) => $this->action($message, $project, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log)); ->callback(fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log) => $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log));
} }
/** /**
* @param Message $message * @param Message $message
* @param Document $project
* @param Database $dbForConsole * @param Database $dbForConsole
* @param Mail $queueForMails * @param Mail $queueForMails
* @param Event $queueForEvents * @param Event $queueForEvents
@ -65,7 +62,7 @@ class Certificates extends Action
* @throws Throwable * @throws Throwable
* @throws \Utopia\Database\Exception * @throws \Utopia\Database\Exception
*/ */
public function action(Message $message, Document $project, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log): void public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log): void
{ {
$payload = $message->getPayload() ?? []; $payload = $message->getPayload() ?? [];
@ -79,7 +76,7 @@ class Certificates extends Action
$log->addTag('domain', $domain->get()); $log->addTag('domain', $domain->get());
$this->execute($domain, $project, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $skipRenewCheck); $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $skipRenewCheck);
} }
/** /**
@ -93,7 +90,7 @@ class Certificates extends Action
* @throws Throwable * @throws Throwable
* @throws \Utopia\Database\Exception * @throws \Utopia\Database\Exception
*/ */
private function execute(Domain $domain, Document $project, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, bool $skipRenewCheck = false): void private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, bool $skipRenewCheck = false): void
{ {
/** /**
* 1. Read arguments and validate domain * 1. Read arguments and validate domain
@ -158,26 +155,16 @@ class Certificates extends Action
// Prepare folder name for certbot. Using this helps prevent miss-match in LetsEncrypt configuration when renewing certificate // Prepare folder name for certbot. Using this helps prevent miss-match in LetsEncrypt configuration when renewing certificate
$folder = ID::unique(); $folder = ID::unique();
try { // Generate certificate files using Let's Encrypt
// Generate certificate files using Let's Encrypt $letsEncryptData = $this->issueCertificate($folder, $domain->get(), $email);
$letsEncryptData = $this->issueCertificate($folder, $domain->get(), $email);
// Give certificates to Traefik
$this->applyCertificateFiles($folder, $domain->get(), $letsEncryptData);
} catch (\Throwable $th) {
Console::error('Failed to generate Lets Encrypt certificate');
}
// Command succeeded, store all data into document // Command succeeded, store all data into document
$logs = 'Certificate successfully generated.'; $logs = 'Certificate successfully generated.';
$certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB $certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB
try {
// TEMP: add custom hostnames to cloudflare // Give certificates to Traefik
$this->addCustomHostnameToRegistrar($project, $domain->get()); $this->applyCertificateFiles($folder, $domain->get(), $letsEncryptData);
} catch (\Throwable $th) {
Console::error('Failed to add custom hostname to registrar: ' . $th->getMessage());
}
// Update certificate info stored in database // Update certificate info stored in database
$certificate->setAttribute('renewDate', $this->getRenewDate($domain->get())); $certificate->setAttribute('renewDate', $this->getRenewDate($domain->get()));
@ -210,35 +197,6 @@ class Certificates extends Action
} }
} }
/**
* Add custom hostname to Cloudflare registrar
*
* @param Document $project
* @param string $hostname
* @return void
* @throws Exception
*/
private function addCustomHostnameToRegistrar(Document $project, string $hostname): void
{
$client = new Client();
$client
->addHeader('content-type', Client::CONTENT_TYPE_APPLICATION_JSON)
->addHeader('Authorization', 'Bearer ' . System::getEnv('_APP_SYSTEM_CLOUDFLARE_TOKEN'));
$response = $client->fetch("https://api.cloudflare.com/client/v4/zones/b2d0e62383d3c0f6299efab107af2c7a/custom_hostnames", Client::METHOD_POST, [
'hostname' => $hostname,
'ssl' => [
"method" => "http",
"type" => "dv",
"wildcard" => false
]
]);
if ($response->getStatusCode() !== 201) {
throw new Exception('Failed to add custom hostname to Cloudflare: ' . $response->getBody());
}
}
/** /**
* Save certificate data into database. * Save certificate data into database.
* *
@ -423,7 +381,7 @@ class Certificates extends Action
* @return void * @return void
* @throws Exception * @throws Exception
*/ */
protected function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void private function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void
{ {
// Prepare folder in storage for domain // Prepare folder in storage for domain