Add logs to rules

This commit is contained in:
Matej Baco 2023-03-13 13:35:34 +00:00
parent 08e4bb5e18
commit e7351f4eec
5 changed files with 42 additions and 16 deletions

View file

@ -3064,10 +3064,10 @@ $collections = [
'filters' => [],
],
[
'$id' => ID::custom('log'),
'$id' => ID::custom('logs'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'size' => 1000000,
'signed' => true,
'required' => false,
'default' => null,

View file

@ -106,6 +106,8 @@ App::post('/v1/proxy/rules')
$events->setParam('ruleId', $rule->getId());
$rule->setAttribute('logs', '');
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($rule, Response::MODEL_PROXY_RULE);
@ -154,8 +156,14 @@ App::get('/v1/proxy/rules')
$filterQueries = Query::groupByType($queries)['filters'];
$rules = $dbForConsole->find('rules', $queries);
foreach ($rules as $rule) {
$certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', ''));
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
}
$response->dynamic(new Document([
'rules' => $dbForConsole->find('rules', $queries),
'rules' => $rules,
'total' => $dbForConsole->count('rules', $filterQueries, APP_LIMIT_COUNT),
]), Response::MODEL_PROXY_RULE_LIST);
});
@ -182,6 +190,9 @@ App::get('/v1/proxy/rules/:ruleId')
throw new Exception(Exception::RULE_NOT_FOUND);
}
$certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', ''));
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
});
@ -278,5 +289,8 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
$events->setParam('ruleId', $rule->getId());
$certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', ''));
$rule->setAttribute('logs', $certificate->getAttribute('logs', ''));
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
});

View file

@ -43,7 +43,9 @@ Config::setParam('domainVerification', false);
Config::setParam('cookieDomain', 'localhost');
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
function router(Database $dbForConsole, string $host, SwooleRequest $swooleRequest, Response $response) {
function router(Database $dbForConsole, SwooleRequest $swooleRequest, Response $response) {
$host = $swooleRequest->header['host'] ?? '';
$route = Authorization::skip(
fn() => $dbForConsole->find('rules', [
Query::equal('domain', [$host]),
@ -66,6 +68,12 @@ function router(Database $dbForConsole, string $host, SwooleRequest $swooleReque
}
}
// Skip Appwrite Router for ACME challenge. Nessessary for certificate generation
$path = ($swooleRequest->server['request_uri'] ?? '');
if(\str_starts_with($path, '/.well-known/acme-challenge')) {
return false;
}
$type = $route->getAttribute('resourceType');
if($type === 'function') {
@ -164,7 +172,7 @@ App::init()
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if($host !== $mainDomain && $host !== 'localhost') {
if(router($dbForConsole, $host, $swooleRequest, $response)) {
if(router($dbForConsole, $swooleRequest, $response)) {
return;
}
}
@ -454,7 +462,7 @@ App::options()
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if($host !== $mainDomain && $host !== 'localhost') {
if(router($dbForConsole, $host, $swooleRequest, $response)) {
if(router($dbForConsole, $swooleRequest, $response)) {
return;
}
}
@ -660,7 +668,6 @@ App::get('/humans.txt')
$response->text($template->render(false));
});
// TODO: @Meldiron this must run before Appwrite Router. Router makes it NOT get here. But it needs to. This must be endpoint reserved by Appwrite for certificate generation and re-generation
App::get('/.well-known/acme-challenge')
->desc('SSL Verification')
->label('scope', 'public')

View file

@ -47,7 +47,7 @@ class CertificatesV1 extends Worker
* 4. Validate security email. Cannot be empty, required by LetsEncrypt
* 5. Validate renew date with certificate file, unless requested to skip by parameter
* 6. Issue a certificate using certbot CLI
* 7. Update 'log' attribute on certificate document with Certbot message
* 7. Update 'logs' attribute on certificate document with Certbot message
* 8. Create storage folder for certificate, if not ready already
* 9. Move certificates from Certbot location to our Storage
* 10. Create/Update our Storage with new Traefik config with new certificate paths
@ -57,7 +57,7 @@ class CertificatesV1 extends Worker
* If at any point unexpected error occurs, program stops without applying changes to document, and error is thrown into worker
*
* If code stops with expected error:
* 1. 'log' attribute on document is updated with error message
* 1. 'logs' attribute on document is updated with error message
* 2. 'attempts' amount is increased
* 3. Console log is shown
* 4. Email is sent to security email
@ -113,11 +113,8 @@ class CertificatesV1 extends Worker
$letsEncryptData = $this->issueCertificate($folder, $domain->get(), $email);
// Command succeeded, store all data into document
// We store stderr too, because it may include warnings
$certificate->setAttribute('log', \json_encode([
'stdout' => $letsEncryptData['stdout'],
'stderr' => $letsEncryptData['stderr'],
]));
$logs = 'Certificate successfully generated.';
$certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB
// Give certificates to Traefik
$this->applyCertificateFiles($folder, $domain->get(), $letsEncryptData);
@ -129,8 +126,10 @@ class CertificatesV1 extends Worker
$success = true;
} catch (Throwable $e) {
$logs = $e->getMessage();
// Set exception as log in certificate document
$certificate->setAttribute('log', $e->getMessage());
$certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB
// Increase attempts count
$attempts = $certificate->getAttribute('attempts', 0) + 1;
@ -280,7 +279,7 @@ class CertificatesV1 extends Worker
$stderr = '';
$staging = (App::isProduction()) ? '' : ' --dry-run';
$exit = Console::execute("certbot certonly --webroot --noninteractive --agree-tos{$staging}"
$exit = Console::execute("certbot certonly -v --webroot --noninteractive --agree-tos{$staging}"
. " --email " . $email
. " --cert-name " . $folder
. " -w " . APP_STORAGE_CERTIFICATES

View file

@ -54,6 +54,12 @@ class Rule extends Model
'default' => false,
'example' => 'verified',
])
->addRule('logs', [
'type' => self::TYPE_STRING,
'description' => 'Certificate generation logs. This will return an empty string if generation did not run, or succeeded.',
'default' => '',
'example' => 'HTTP challegne failed.',
])
;
}