From 213215bffa17f3d4ef4bedd8bf195ae791088358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 13:31:35 +0000 Subject: [PATCH 1/9] Allow same certificate with multiple projects (same domain) --- app/workers/certificates.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 9f9ce33dbd..b9f8ec26a0 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -98,6 +98,23 @@ class CertificatesV1 extends Worker && isset($certificate['issueDate']) && (($certificate['issueDate'] + ($expiry)) > \time()) ) { // Check last issue time + + // Update document anyway, if needed + // This occurs when a cert is already generated because a different project is using the domain + // By updating here we ensure all domains has certificateId assigned (share same certificate document) + if(!isset($document['certificateId'])) { + $certificate = new Document(\array_merge($document, [ + 'updated' => \time(), + 'certificateId' => $certificate->getId(), + ])); + + $certificate = $dbForConsole->updateDocument('domains', $certificate->getId(), $certificate); + + if(!$certificate) { + throw new Exception('Failed saving domain to DB'); + } + } + throw new Exception('Renew isn\'t required'); } From 41cc8bd38de27314c22728f3e98e20594d0843ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 14:40:19 +0000 Subject: [PATCH 2/9] CertificateId update fix --- app/workers/certificates.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/workers/certificates.php b/app/workers/certificates.php index b9f8ec26a0..183427fede 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -103,12 +103,14 @@ class CertificatesV1 extends Worker // This occurs when a cert is already generated because a different project is using the domain // By updating here we ensure all domains has certificateId assigned (share same certificate document) if(!isset($document['certificateId'])) { - $certificate = new Document(\array_merge($document, [ + $certificate = new Document($certificate); + + $domain = new Document(\array_merge($document, [ 'updated' => \time(), 'certificateId' => $certificate->getId(), ])); - $certificate = $dbForConsole->updateDocument('domains', $certificate->getId(), $certificate); + $domain = $dbForConsole->updateDocument('domains', $domain->getId(), $domain); if(!$certificate) { throw new Exception('Failed saving domain to DB'); From 7f7b23181f340988f6cd149473bfa35476447c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 14:46:59 +0000 Subject: [PATCH 3/9] Added global auth disable in cert worker --- app/workers/certificates.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 183427fede..35409f3caf 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -11,6 +11,8 @@ use Utopia\Domains\Domain; require_once __DIR__.'/../init.php'; +Authorization::disable(); + Console::title('Certificates V1 Worker'); Console::success(APP_NAME . ' certificates worker v1 has started'); @@ -40,8 +42,6 @@ class CertificatesV1 extends Worker * 3.5. Schedule to renew certificate in 60 days */ - Authorization::disable(); - // Args $document = $this->args['document']; $domain = $this->args['domain']; @@ -206,8 +206,6 @@ class CertificatesV1 extends Worker 'validateTarget' => $validateTarget, 'validateCNAME' => $validateCNAME, ]); // Async task rescheduale - - Authorization::reset(); } public function shutdown(): void From 7f7a2c7dfbea8cc3cf29ec64136a4fff34c99ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 14:47:50 +0000 Subject: [PATCH 4/9] Revert auth changes --- app/workers/certificates.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 35409f3caf..183427fede 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -11,8 +11,6 @@ use Utopia\Domains\Domain; require_once __DIR__.'/../init.php'; -Authorization::disable(); - Console::title('Certificates V1 Worker'); Console::success(APP_NAME . ' certificates worker v1 has started'); @@ -42,6 +40,8 @@ class CertificatesV1 extends Worker * 3.5. Schedule to renew certificate in 60 days */ + Authorization::disable(); + // Args $document = $this->args['document']; $domain = $this->args['domain']; @@ -206,6 +206,8 @@ class CertificatesV1 extends Worker 'validateTarget' => $validateTarget, 'validateCNAME' => $validateCNAME, ]); // Async task rescheduale + + Authorization::reset(); } public function shutdown(): void From 2bc6d7c41b6965b317f4c4333b4d931b503a42aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 14:54:25 +0000 Subject: [PATCH 5/9] Delete certificate document alongside certificate directory --- app/workers/deletes.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 963488a00a..372f38dc6c 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -18,8 +18,6 @@ use Utopia\Audit\Audit; require_once __DIR__ . '/../init.php'; -Authorization::disable(); - Console::title('Deletes V1 Worker'); Console::success(APP_NAME . ' deletes worker v1 has started' . "\n"); @@ -40,6 +38,8 @@ class DeletesV1 extends Worker public function run(): void { + Authorization::disable(); + $projectId = $this->args['projectId'] ?? ''; $type = $this->args['type'] ?? ''; @@ -113,6 +113,8 @@ class DeletesV1 extends Worker Console::error('No delete operation for type: ' . $type); break; } + + Authorization::reset(); } public function shutdown(): void @@ -531,6 +533,13 @@ class DeletesV1 extends Worker $checkTraversal = realpath($directory) === $directory; if ($domain && $checkTraversal && is_dir($directory)) { + // Delete certificate document, so Appwrite is aware of change + if(isset($document['certificateId'])) { + $consoleDB = $this->getConsoleDB(); + $consoleDB->deleteDocument('certificates', $document['certificateId']); + } + + // Delete files, so Traefik is aware of change array_map('unlink', glob($directory . '/*.*')); rmdir($directory); Console::info("Deleted certificate files for {$domain}"); From 8fe5a47a3597f6eefad1f8ab33227004a7e36da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 15:05:50 +0000 Subject: [PATCH 6/9] Skip certificate deletion if its already used by other project --- app/workers/deletes.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 372f38dc6c..ec920f6943 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -528,6 +528,22 @@ class DeletesV1 extends Worker */ protected function deleteCertificates(Document $document): void { + $consoleDB = $this->getConsoleDB(); + + // If domain has certificate generated + if(isset($document['certificateId'])) { + $domainUsingCertificate = $consoleDB->findOne('domains', [ + new Query('certificateId', Query::TYPE_EQUAL, [$document['certificateId']]) + ]); + + // If certificate is still used by some domain, mark we can't delete. + // Current domain should not be found, because we only have copy. Original domain is already deleted from database. + if($domainUsingCertificate) { + Console::warning("Skipping certificate deletion, because a domain is still using it."); + return; + } + } + $domain = $document->getAttribute('domain'); $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; $checkTraversal = realpath($directory) === $directory; @@ -535,7 +551,6 @@ class DeletesV1 extends Worker if ($domain && $checkTraversal && is_dir($directory)) { // Delete certificate document, so Appwrite is aware of change if(isset($document['certificateId'])) { - $consoleDB = $this->getConsoleDB(); $consoleDB->deleteDocument('certificates', $document['certificateId']); } From 5897a705365f65f11bd5d4acfb84d4521552c264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 23 Mar 2022 15:07:16 +0000 Subject: [PATCH 7/9] Update comment --- app/workers/certificates.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 183427fede..1df77f9827 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -99,8 +99,8 @@ class CertificatesV1 extends Worker && (($certificate['issueDate'] + ($expiry)) > \time()) ) { // Check last issue time - // Update document anyway, if needed - // This occurs when a cert is already generated because a different project is using the domain + // Update document anyway, if needed. + // This occurs when a cert is already generated because a different project is using the domain. // By updating here we ensure all domains has certificateId assigned (share same certificate document) if(!isset($document['certificateId'])) { $certificate = new Document($certificate); From 933f3372fe32369ee7698897871338385cc87491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 30 Mar 2022 13:31:46 +0000 Subject: [PATCH 8/9] Prevent certificate deletion for main domain --- app/workers/deletes.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index ec920f6943..cf62089165 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -536,6 +536,13 @@ class DeletesV1 extends Worker new Query('certificateId', Query::TYPE_EQUAL, [$document['certificateId']]) ]); + if(!$domainUsingCertificate) { + $mainDomain = App::getEnv('_APP_DOMAIN_TARGET', ''); + if($mainDomain === $document->getAttribute('domain')) { + $domainUsingCertificate = $mainDomain; + } + } + // If certificate is still used by some domain, mark we can't delete. // Current domain should not be found, because we only have copy. Original domain is already deleted from database. if($domainUsingCertificate) { From 911aefaa7aadff454cd4f1b10bb23e10edba5674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 27 Apr 2022 13:20:08 +0000 Subject: [PATCH 9/9] Code quality improvement --- app/workers/deletes.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index cf62089165..1748060b2c 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -18,6 +18,9 @@ use Utopia\Audit\Audit; require_once __DIR__ . '/../init.php'; +Authorization::disable(); +Authorization::setDefaultStatus(false); + Console::title('Deletes V1 Worker'); Console::success(APP_NAME . ' deletes worker v1 has started' . "\n"); @@ -38,7 +41,6 @@ class DeletesV1 extends Worker public function run(): void { - Authorization::disable(); $projectId = $this->args['projectId'] ?? ''; $type = $this->args['type'] ?? ''; @@ -113,8 +115,6 @@ class DeletesV1 extends Worker Console::error('No delete operation for type: ' . $type); break; } - - Authorization::reset(); } public function shutdown(): void