1
0
Fork 0
mirror of synced 2024-06-29 11:40:45 +12:00
appwrite/app/workers/certificates.php

156 lines
5.2 KiB
PHP
Raw Normal View History

2020-02-23 21:58:11 +13:00
<?php
use Database\Database;
use Database\Document;
use Database\Validator\Authorization;
use Network\Validators\CNAME;
2020-02-24 06:45:51 +13:00
use Utopia\App;
2020-02-23 21:58:11 +13:00
use Utopia\Domains\Domain;
require_once __DIR__.'/../init.php';
cli_set_process_title('Certificates V1 Worker');
echo APP_NAME.' certificates worker v1 has started';
class CertificatesV1
{
public $args = [];
public function setUp()
{
}
public function perform()
{
2020-02-24 06:45:51 +13:00
global $request, $consoleDB, $env;
2020-02-23 21:58:11 +13:00
/**
2020-02-24 06:05:42 +13:00
* 1. Get new domain document - DONE
* 1.1. Validate domain is valid, public suffix is known and CNAME records are verified - DONE
* 2. Check if a certificate already exists - DONE
2020-02-23 21:58:11 +13:00
* 3. Check if certificate is not about to expire skip
* 3.1. Create / renew certificate
* 3.2. Update loadblancer
* 3.3. Update database (domains, change date, expiry)
* 3.4. Set retry on failure
*/
Authorization::disable();
$document = $this->args['document'];
$domain = new Domain((isset($document['domain'])) ? $document['domain'] : '');
$expiry = 60 * 60 * 24 * 30 * 2; // 60 days
if(empty($domain->get())) {
throw new Exception('Missing domain');
}
if(!$domain->isKnown() || $domain->isTest()) {
throw new Exception('Unkown public suffix for domain');
}
$target = new Domain($request->getServer('_APP_DOMAINS_TARGET', ''));
if(!$target->isKnown() || $target->isTest()) {
throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500);
}
$validator = new CNAME($target->get()); // Verify Domain with DNS records
if(!$validator->isValid($domain->get())) {
throw new Exception('Failed to verify domain DNS records');
}
$certificate = $consoleDB->getCollection([
'limit' => 1,
'offset' => 0,
'orderField' => 'id',
'orderType' => 'ASC',
'orderCast' => 'string',
'filters' => [
'$collection='.Database::SYSTEM_COLLECTION_CERTIFICATES,
'domain='.$domain->get(),
],
'first' => true,
]);
$certificate = (!empty($certificate) && $certificate instanceof $certificate) ? $certificate->getArrayCopy() : [];
if($certificate
&& $certificate instanceof Document
&& isset($certificate['issueDate'])
&& ($certificate['issueDate'] + $expiry > time())) { // Check last issue time
throw new Exception('Renew isn\'t required. Domain issued at '.date('d.m.Y H:i', (isset($certificate['issueDate']) ? $certificate['issueDate'] : 0)));
}
2020-02-24 06:45:51 +13:00
$staging = ($env === App::ENV_TYPE_PRODUCTION) ? '' : ' --dry-run';
$response = shell_exec("certbot certonly --webroot --noninteractive --agree-tos{$staging} --email security@appwrite.io \
2020-02-23 21:58:11 +13:00
-w ".APP_STORAGE_CERTIFICATES." \
-d {$domain->get()} 2>&1"); // cert2.tests.appwrite.org
if(!$response) {
throw new Exception('Failed to issue a certificate');
}
2020-02-24 06:05:42 +13:00
2020-02-25 05:47:45 +13:00
if(!@rename('/etc/letsencrypt/live/'.$domain->get(), APP_STORAGE_CERTIFICATES.'/'.$domain->get())) {
2020-02-25 01:55:24 +13:00
throw new Exception('Failed to copy certificate: '.json_encode($response));
2020-02-24 06:05:42 +13:00
}
2020-02-23 21:58:11 +13:00
2020-02-25 05:47:45 +13:00
// // ls cert.pem chain.pem fullchain.pem privkey.pem
// if(!@rename('/etc/letsencrypt/live/test.appwrite.org/cert.pem', APP_STORAGE_CERTIFICATES.'/cert.pem')) {
// throw new Exception('Failed to copy certificate cert.pem');
// }
// if(!@rename('/etc/letsencrypt/live/test.appwrite.org/chain.pem', APP_STORAGE_CERTIFICATES.'/chain.pem')) {
// throw new Exception('Failed to copy certificate chain.pem');
// }
// if(!@rename('/etc/letsencrypt/live/test.appwrite.org/fullchain.pem', APP_STORAGE_CERTIFICATES.'/fullchain.pem')) {
// throw new Exception('Failed to copy certificate fullchain.pem');
// }
// if(!@rename('/etc/letsencrypt/live/test.appwrite.org/privkey.pem', APP_STORAGE_CERTIFICATES.'/privkey.pem')) {
// throw new Exception('Failed to copy certificate privkey.pem');
// }
2020-02-23 21:58:11 +13:00
$certificate = array_merge($certificate, [
'$collection' => Database::SYSTEM_COLLECTION_CERTIFICATES,
'$permissions' => [
'read' => [],
'write' => [],
],
'domain' => $domain->get(),
'issueDate' => time(),
'attempts' => 0,
2020-02-25 01:55:24 +13:00
'log' => json_encode($response),
2020-02-23 21:58:11 +13:00
]);
$certificate = $consoleDB->createDocument($certificate);
if(!$certificate) {
throw new Exception('Failed saving certificate to DB');
}
$document = array_merge($document, [
'updated' => time(),
'certificateId' => $certificate->getId(),
]);
$document = $consoleDB->updateDocument($document);
if(!$document) {
throw new Exception('Failed saving domain to DB');
}
Authorization::reset();
}
public function tearDown()
{
// ... Remove environment for this job
}
}