From 0c3bcb40a4061d99d5f6430e9a905bbdd02dacfc Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 10 May 2021 14:33:27 +0545 Subject: [PATCH 01/13] poc certificate auto generation --- app/http.php | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/app/http.php b/app/http.php index d144c2e54a..0e88757ab3 100644 --- a/app/http.php +++ b/app/http.php @@ -12,6 +12,7 @@ use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Utopia\App; use Utopia\CLI\Console; +use Utopia\Config\Config; // xdebug_start_trace('/tmp/trace'); @@ -65,22 +66,35 @@ Files::load(__DIR__ . '/../public'); include __DIR__ . '/controllers/general.php'; -$domain = App::getEnv('_APP_DOMAIN', ''); +function certificateSetup($domain) +{ + $domains = Config::getParam('domains', []); + if (!in_array($domain, $domains)) { + //schedule + Console::info('adding ' . $domain . ' to list of domains already checked'); + array_push($domains, $domain); + Config::setParam('domains', $domains); -Console::info('Issuing a TLS certificate for the master domain ('.$domain.') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script -ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, -]); + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain, + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + +} $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $request = new Request($swooleRequest); $response = new Response($swooleResponse); + $domain = $request->getHostname(); + certificateSetup($domain); + if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 75d8076ac95477208dd5ade1231f8bbdd4b9144d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 10 May 2021 16:23:05 +0545 Subject: [PATCH 02/13] skip certificate generation when localhost or hostname is IP --- app/http.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/http.php b/app/http.php index 0e88757ab3..d71db4a6a3 100644 --- a/app/http.php +++ b/app/http.php @@ -68,6 +68,7 @@ include __DIR__ . '/controllers/general.php'; function certificateSetup($domain) { + if($domain=='localhost' || (bool)ip2long($domain)) return; $domains = Config::getParam('domains', []); if (!in_array($domain, $domains)) { //schedule From c22dd1571f9b9d0f47b6cd83f9f26f686b6e210b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 11:41:11 +0545 Subject: [PATCH 03/13] implementing review suggestions --- app/http.php | 54 +++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/app/http.php b/app/http.php index d71db4a6a3..d38d33b7c8 100644 --- a/app/http.php +++ b/app/http.php @@ -13,6 +13,7 @@ use Swoole\Http\Response as SwooleResponse; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Domains\Domain; // xdebug_start_trace('/tmp/trace'); @@ -66,35 +67,40 @@ Files::load(__DIR__ . '/../public'); include __DIR__ . '/controllers/general.php'; -function certificateSetup($domain) -{ - if($domain=='localhost' || (bool)ip2long($domain)) return; - $domains = Config::getParam('domains', []); - if (!in_array($domain, $domains)) { - //schedule - Console::info('adding ' . $domain . ' to list of domains already checked'); - array_push($domains, $domain); - Config::setParam('domains', $domains); - - Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script - - ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, - ]); - } - -} - $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $request = new Request($swooleRequest); $response = new Response($swooleResponse); $domain = $request->getHostname(); - certificateSetup($domain); + $validDomains = Config::getParam('validDomains', []); + if (!array_key_exists($domain, $validDomains)) { + $domainCheck = new Domain(!empty($domain) ? $domain : ''); + if (empty($domainCheck->get()) || !$domainCheck->isKnown() || $domainCheck->isTest()()) { + $validDomains[$domain] = false; + } else { + $validDomains[$domain] = true; + } + Config::setParam('validDomains', $validDomains); + } + if ($validDomains[$domain]) { + $issuedDomains = Config::getParam('issuedDomains', []); + if (!array_key_exists($domain, $issuedDomains)) { + //schedule + Console::info('adding ' . $domain . ' to list of domains already checked'); + $issuedDomains[$domain] = true; + Config::setParam('issuedDomains', $issuedDomains); + + Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain, + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + } if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 35b76c1aee5f3fe3b87e9fa092e9e935bc3f14ae Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 16:32:02 +0545 Subject: [PATCH 04/13] refactoring moving ssl generation to init function --- app/controllers/general.php | 54 +++++++++++++++++++++++++++++++++++-- app/http.php | 31 --------------------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1f7d4ebaeb..9b0a6e7fde 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -23,15 +23,65 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $clients) { +App::init(function ($utopia, $request, $response, $console, $project, $consoleDB, $user, $locale, $clients) { /** @var Utopia\Swoole\Request $request */ /** @var Appwrite\Utopia\Response $response */ + /** @var Appwrite\Database\Database $consoleDB */ /** @var Appwrite\Database\Document $console */ /** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $user */ /** @var Utopia\Locale\Locale $locale */ /** @var bool $mode */ /** @var array $clients */ + + $domain = $request->getHostname(); + $checkedDomains = Config::getParam('checkedDomains', []); + if (!array_key_exists($domain, $checkedDomains)) { + $domain = new Domain(!empty($domain) ? $domain : ''); + + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()()) { + $checkedDomains[$domain->get()] = false; + Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); + } else { + Console::info($domain->get() . ' is a valid domain.'); + + $dbDomain = $consoleDB->getCollectionFirst([ + 'limit' => 1, + 'offset' => 0, + 'filters' => [ + '$collection=' . Database::SYSTEM_COLLECTION_CERTIFICATES, + 'domain=' . $domain->get(), + ], + ]); + + if (empty($dbDomain)) { + $dbDomain = [ + '$collection' => Database::SYSTEM_COLLECTION_CERTIFICATES, + '$permissions' => [ + 'read' => [], + 'write' => [], + ], + 'domain' => $domain->get(), + ]; + $dbDomain = $consoleDB->createDocument($dbDomain); + + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. + Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + + ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ + 'document' => [], + 'domain' => $domain->get(), + 'validateTarget' => false, + 'validateCNAME' => false, + ]); + } + + $checkedDomains[$domain] = true; + + } + Console::info('adding ' . $domain->get() . ' to list of domains already checked'); + Config::setParam('checkedDomains', $checkedDomains); + } $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); @@ -226,7 +276,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo throw new Exception('Password reset is required', 412); } -}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'clients']); +}, ['utopia', 'request', 'response', 'console', 'project', 'consoleDB', 'user', 'locale', 'clients']); App::options(function ($request, $response) { /** @var Utopia\Swoole\Request $request */ diff --git a/app/http.php b/app/http.php index d38d33b7c8..efa47ffbd1 100644 --- a/app/http.php +++ b/app/http.php @@ -71,37 +71,6 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $request = new Request($swooleRequest); $response = new Response($swooleResponse); - $domain = $request->getHostname(); - $validDomains = Config::getParam('validDomains', []); - if (!array_key_exists($domain, $validDomains)) { - $domainCheck = new Domain(!empty($domain) ? $domain : ''); - if (empty($domainCheck->get()) || !$domainCheck->isKnown() || $domainCheck->isTest()()) { - $validDomains[$domain] = false; - } else { - $validDomains[$domain] = true; - } - Config::setParam('validDomains', $validDomains); - } - if ($validDomains[$domain]) { - $issuedDomains = Config::getParam('issuedDomains', []); - if (!array_key_exists($domain, $issuedDomains)) { - //schedule - Console::info('adding ' . $domain . ' to list of domains already checked'); - $issuedDomains[$domain] = true; - Config::setParam('issuedDomains', $issuedDomains); - - Console::info('Issuing a TLS certificate for the master domain (' . $domain . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script - - ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], - 'domain' => $domain, - 'validateTarget' => false, - 'validateCNAME' => false, - ]); - } - } - if(Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache From 4170eaa45a729829d59f630a9cb2ce8d46ea8b83 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:00:26 +0545 Subject: [PATCH 05/13] fix error --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9b0a6e7fde..a7df8426fb 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -39,7 +39,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB if (!array_key_exists($domain, $checkedDomains)) { $domain = new Domain(!empty($domain) ? $domain : ''); - if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()()) { + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $checkedDomains[$domain->get()] = false; Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); } else { From dc92498d93e77c1f236ff2b86944ceb94337e1e1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:06:55 +0545 Subject: [PATCH 06/13] disable auth for writing --- app/controllers/general.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index a7df8426fb..559e3baab3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -63,7 +63,9 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ], 'domain' => $domain->get(), ]; + Authorization::disable(); $dbDomain = $consoleDB->createDocument($dbDomain); + Authorization::enable(); Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script From dc52c6975a8fbd4ce43a7eea2f56d651ca9eba6e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:09:23 +0545 Subject: [PATCH 07/13] fix error --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 559e3baab3..9323d0a219 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -78,7 +78,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ]); } - $checkedDomains[$domain] = true; + $checkedDomains[$domain->get()] = true; } Console::info('adding ' . $domain->get() . ' to list of domains already checked'); From f83ad43187e4634e5d50c14110114122a78d1ca8 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 11 May 2021 17:21:27 +0545 Subject: [PATCH 08/13] fix auth issue --- app/controllers/general.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9323d0a219..6ceca25e0f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -44,7 +44,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); } else { Console::info($domain->get() . ' is a valid domain.'); - + Authorization::disable(); $dbDomain = $consoleDB->getCollectionFirst([ 'limit' => 1, 'offset' => 0, @@ -63,7 +63,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB ], 'domain' => $domain->get(), ]; - Authorization::disable(); $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); From be5b882fe74071b3759021a91da1b685c9f0af32 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 11:02:34 +0545 Subject: [PATCH 09/13] Apply suggestions from code review Co-authored-by: Eldad A. Fux --- app/controllers/general.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 6ceca25e0f..695ac93d17 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -41,9 +41,8 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $checkedDomains[$domain->get()] = false; - Console::info($domain->get() . ' is not a valid domain. Skipping certificate generation.'); + Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); } else { - Console::info($domain->get() . ' is a valid domain.'); Authorization::disable(); $dbDomain = $consoleDB->getCollectionFirst([ 'limit' => 1, @@ -66,8 +65,8 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); - Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in 30 seconds. - Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds. +.'); // TODO move this to installation script ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ 'document' => [], @@ -475,4 +474,4 @@ include_once __DIR__ . '/shared/web.php'; foreach (Config::getParam('services', []) as $service) { include_once $service['controller']; -} \ No newline at end of file +} From 0e90c75a1226ba3c554abf38f9100bab4ccc329c Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 11:04:48 +0545 Subject: [PATCH 10/13] refactor based on review --- app/controllers/general.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 695ac93d17..8f1f75be81 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -14,8 +14,6 @@ use Appwrite\Database\Database; use Appwrite\Database\Document; use Appwrite\Database\Validator\Authorization; use Appwrite\Network\Validator\Origin; -use Utopia\Storage\Device\Local; -use Utopia\Storage\Storage; use Appwrite\Utopia\Response\Filters\V06; use Utopia\CLI\Console; @@ -35,12 +33,12 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB /** @var array $clients */ $domain = $request->getHostname(); - $checkedDomains = Config::getParam('checkedDomains', []); - if (!array_key_exists($domain, $checkedDomains)) { + $domains = Config::getParam('domains', []); + if (!array_key_exists($domain, $domains)) { $domain = new Domain(!empty($domain) ? $domain : ''); if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { - $checkedDomains[$domain->get()] = false; + $domains[$domain->get()] = false; Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); } else { Authorization::disable(); @@ -65,22 +63,21 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $dbDomain = $consoleDB->createDocument($dbDomain); Authorization::enable(); - Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds. -.'); // TODO move this to installation script + Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in ~30 seconds..'); // TODO move this to installation script ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [ - 'document' => [], + 'document' => $dbDomain, 'domain' => $domain->get(), 'validateTarget' => false, 'validateCNAME' => false, ]); } - $checkedDomains[$domain->get()] = true; + $domains[$domain->get()] = true; } Console::info('adding ' . $domain->get() . ' to list of domains already checked'); - Config::setParam('checkedDomains', $checkedDomains); + Config::setParam('domains', $domains); } $localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')); From 3330841b9e0c95cf7d25e07cdaa2d6a4a20f8c0a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 12:57:08 +0545 Subject: [PATCH 11/13] changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b8867b0e53..01e32bb79e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Version 0.8.0 (Not Released Yet) ## Features - +- Refactoring SSL generation to work on every request so no domain environment variable is required for SSL generation (#1133) - Added Anonymous Login ([RFC-010](https://github.com/appwrite/rfc/blob/main/010-anonymous-login.md), #914) - Added events for functions and executions (#971) - Added JWT support (#784) From 7a75c3558f7e67970d2c2e94e324671cff4c92e6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 16:10:57 +0545 Subject: [PATCH 12/13] remove log --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 8f1f75be81..98db96a58a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -76,7 +76,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB $domains[$domain->get()] = true; } - Console::info('adding ' . $domain->get() . ' to list of domains already checked'); Config::setParam('domains', $domains); } From e2000dbdf81e1639ab1f4e7d0bd8a3f2d0f90b53 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 12 May 2021 16:42:13 +0545 Subject: [PATCH 13/13] remove extra white space --- app/controllers/general.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 98db96a58a..9d360f8292 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -72,9 +72,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $consoleDB 'validateCNAME' => false, ]); } - $domains[$domain->get()] = true; - } Config::setParam('domains', $domains); }