From 6252b5d0df6f5794be7d4482ef6b064e284efd51 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 22 Sep 2021 16:13:41 +0100 Subject: [PATCH 1/4] Use Swoole Table for activeFunctions list --- app/executor.php | 85 +++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/app/executor.php b/app/executor.php index 99b35c42e9..48d56793c0 100644 --- a/app/executor.php +++ b/app/executor.php @@ -45,21 +45,21 @@ $runtimes = Config::getParam('runtimes'); Swoole\Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_CURL); // Warmup: make sure images are ready to run fast 🚀 -Co\run(function () use ($runtimes, $orchestration) { - foreach ($runtimes as $runtime) { - go(function () use ($runtime, $orchestration) { - Console::info('Warming up ' . $runtime['name'] . ' ' . $runtime['version'] . ' environment...'); +// Co\run(function () use ($runtimes, $orchestration) { +// foreach ($runtimes as $runtime) { +// go(function () use ($runtime, $orchestration) { +// Console::info('Warming up ' . $runtime['name'] . ' ' . $runtime['version'] . ' environment...'); - $response = $orchestration->pull($runtime['image']); +// $response = $orchestration->pull($runtime['image']); - if ($response) { - Console::success("Successfully Warmed up {$runtime['name']} {$runtime['version']}!"); - } else { - Console::error("Failed to Warmup {$runtime['name']} {$runtime['version']}!"); - } - }); - } -}); +// if ($response) { +// Console::success("Successfully Warmed up {$runtime['name']} {$runtime['version']}!"); +// } else { +// Console::error("Failed to Warmup {$runtime['name']} {$runtime['version']}!"); +// } +// }); +// } +// }); /** * List function servers @@ -68,10 +68,21 @@ $executionStart = \microtime(true); $response = $orchestration->list(['label' => 'appwrite-type=function']); -$activeFunctions = []; +$activeFunctions = new Swoole\Table(1024); +$activeFunctions->column('id', Swoole\Table::TYPE_STRING, 512); +$activeFunctions->column('name', Swoole\Table::TYPE_STRING, 512); +$activeFunctions->column('status', Swoole\Table::TYPE_STRING, 512); +$activeFunctions->column('private-key', Swoole\Table::TYPE_STRING, 4096); +$activeFunctions->create(); + foreach ($response as $value) { - $activeFunctions[$value->getName()] = $value; + $activeFunctions->set($value->getName(), [ + 'id' => $value->getId(), + 'name' => $value->getName(), + 'status' => $value->getStatus(), + 'private-key' => '' + ]); } $executionEnd = \microtime(true); @@ -505,6 +516,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta $privateKey = openssl_pkey_new(array('private_key_bits' => 2048)); $details = openssl_pkey_get_details($privateKey); $publicKey = $details['key']; + openssl_pkey_export($privateKey, $privateKey); // Turn private key into a string so we can place it into a swoole table // Check if runtime is active $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) @@ -532,7 +544,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta $container = 'appwrite-function-' . $tag->getId(); - if (isset($activeFunctions[$container]) && !(\substr($activeFunctions[$container]->getStatus(), 0, 2) === 'Up')) { // Remove container if not online + if ($activeFunctions->exists($container) && !(\substr($activeFunctions->get($container)['status'], 0, 2) === 'Up')) { // Remove container if not online // If container is online then stop and remove it try { $orchestration->remove($container); @@ -540,7 +552,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta Console::warning('Failed to remove container: ' . $e->getMessage()); } - unset($activeFunctions[$container]); + $activeFunctions->del($container); } // Check if tag is built yet. @@ -580,7 +592,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta * Make sure no access to NFS server / storage volumes * Access Appwrite REST from internal network for improved performance */ - if (!isset($activeFunctions[$container])) { // Create contianer if not ready + if (!$activeFunctions->exists($container)) { // Create contianer if not ready $executionStart = \microtime(true); $executionTime = \time(); @@ -609,17 +621,24 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta $executionEnd = \microtime(true); - $activeFunctions[$container] = new Container( - $container, - $id, - 'Up', - [ - 'appwrite-type' => 'function', - 'appwrite-created' => strval($executionTime), - 'appwrite-runtime' => $function->getAttribute('runtime', ''), - 'security-key' => $privateKey, - ] - ); + $activeFunctions->set($container, [ + 'id' => $id, + 'name' => $container, + 'status' => 'Up ' . \round($executionEnd - $executionStart, 2) . 's', + 'private-key' => $privateKey, + ]); + + // $activeFunctions[$container] = new Container( + // $container, + // $id, + // 'Up', + // [ + // 'appwrite-type' => 'function', + // 'appwrite-created' => strval($executionTime), + // 'appwrite-runtime' => $function->getAttribute('runtime', ''), + // 'security-key' => $privateKey, + // ] + // ); Console::info('Runtime Server created in ' . ($executionEnd - $executionStart) . ' seconds'); } else { @@ -700,9 +719,9 @@ function execute(string $trigger, string $projectId, string $executionId, string } try { - if (!isset($activeFunctions[$container])) { // Create contianer if not ready + if (!$activeFunctions->exists($container)) { // Create contianer if not ready createRuntimeServer($functionId, $projectId, $tag, $database); - } else if ($activeFunctions[$container]->getStatus() === 'Down') { + } else if ($activeFunctions->get($container)['status'] === 'Down') { sleep(1); } else { Console::info('Container is ready to run'); @@ -721,8 +740,8 @@ function execute(string $trigger, string $projectId, string $executionId, string } // Generate Signed Challenge - $internalFunction = $activeFunctions['appwrite-function-' . $tag->getId()]; - $privateKey = $internalFunction->getLabels()['security-key']; + $internalFunction = $activeFunctions->get('appwrite-function-' . $tag->getId()); + $privateKey = openssl_pkey_get_private($internalFunction['private-key']); // Convert PEM formatted key from swoole table into resource $signedChallenge = ''; From 73722b517f46244693138b03fdfbddb3d063c1a5 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 22 Sep 2021 16:23:31 +0100 Subject: [PATCH 2/4] Update executor.php --- app/executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/executor.php b/app/executor.php index 48d56793c0..28ca43fe04 100644 --- a/app/executor.php +++ b/app/executor.php @@ -539,7 +539,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'], 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'], 'APPWRITE_FUNCTION_PROJECT_ID' => $projectId, - 'APPWRITE_INTERNAL_RUNTIME_SECRET' => $publicKey, + 'APPWRITE_INTERNAL_RUNTIME_PUBLIC' => $publicKey, ]); $container = 'appwrite-function-' . $tag->getId(); From e4a8f96ce57509d5b5b54fa4f7758b0b6e0120e9 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Fri, 24 Sep 2021 11:46:41 +0100 Subject: [PATCH 3/4] Change authentication method --- app/executor.php | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/app/executor.php b/app/executor.php index 8c108d9c64..6fe8db4176 100644 --- a/app/executor.php +++ b/app/executor.php @@ -513,10 +513,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta } // Generate random secret key - $privateKey = openssl_pkey_new(array('private_key_bits' => 2048)); - $details = openssl_pkey_get_details($privateKey); - $publicKey = $details['key']; - openssl_pkey_export($privateKey, $privateKey); // Turn private key into a string so we can place it into a swoole table + $secret = \bin2hex(\random_bytes(16)); // Check if runtime is active $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) @@ -539,7 +536,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'], 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'], 'APPWRITE_FUNCTION_PROJECT_ID' => $projectId, - 'APPWRITE_INTERNAL_RUNTIME_PUBLIC' => $publicKey, + 'APPWRITE_INTERNAL_RUNTIME_KEY' => $secret, ]); $container = 'appwrite-function-' . $tag->getId(); @@ -742,14 +739,8 @@ function execute(string $trigger, string $projectId, string $executionId, string Authorization::enable(); } - // Generate Signed Challenge $internalFunction = $activeFunctions->get('appwrite-function-' . $tag->getId()); - $privateKey = openssl_pkey_get_private($internalFunction['private-key']); // Convert PEM formatted key from swoole table into resource - - $signedChallenge = ''; - - \openssl_sign($function->getId(), $signedChallenge, $privateKey, OPENSSL_ALGO_SHA256); - $signedChallenge = \base64_encode($signedChallenge); + $key = $internalFunction['key']; // Process environment variables $vars = \array_merge($function->getAttribute('vars', []), [ @@ -803,7 +794,8 @@ function execute(string $trigger, string $projectId, string $executionId, string \curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', - 'Content-Length: ' . \strlen($body) + 'Content-Length: ' . \strlen($body), + 'x-internal-challenge: ' . $key ]); $executorResponse = \curl_exec($ch); From 23355cd681001f82c8abef322ea1d6266f6d25ad Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Fri, 24 Sep 2021 11:53:04 +0100 Subject: [PATCH 4/4] Update executor.php --- app/executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/executor.php b/app/executor.php index 6fe8db4176..a83dde495c 100644 --- a/app/executor.php +++ b/app/executor.php @@ -72,7 +72,7 @@ $activeFunctions = new Swoole\Table(1024); $activeFunctions->column('id', Swoole\Table::TYPE_STRING, 512); $activeFunctions->column('name', Swoole\Table::TYPE_STRING, 512); $activeFunctions->column('status', Swoole\Table::TYPE_STRING, 512); -$activeFunctions->column('private-key', Swoole\Table::TYPE_STRING, 4096); +$activeFunctions->column('key', Swoole\Table::TYPE_STRING, 4096); $activeFunctions->create(); @@ -622,7 +622,7 @@ function createRuntimeServer(string $functionId, string $projectId, Document $ta 'id' => $id, 'name' => $container, 'status' => 'Up ' . \round($executionEnd - $executionStart, 2) . 's', - 'private-key' => $privateKey, + 'key' => $secret, ]); Console::info('Runtime Server created in ' . ($executionEnd - $executionStart) . ' seconds');