changes on ssl

Signed-off-by: Zoey <zoey@z0ey.de>
This commit is contained in:
Zoey
2022-12-27 12:35:02 +01:00
parent 920bce627a
commit d7db5527d9
36 changed files with 201 additions and 251 deletions

View File

@@ -1,2 +0,0 @@
*
!.gitignore

1
backend/config/.gitkeep Normal file
View File

@@ -0,0 +1 @@

View File

@@ -467,7 +467,7 @@ const internalAccessList = {
* @returns {String}
*/
getFilename: (list) => {
return '/data/access/' + list.id;
return '/data/nginx/access/' + list.id;
},
/**

View File

@@ -11,12 +11,11 @@ const dnsPlugins = require('../global/certbot-dns-plugins');
const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx');
const internalHost = require('./host');
const letsencryptStaging = process.env.NODE_ENV !== 'production';
const letsencryptConfig = '/usr/local/nginx/conf/letsencrypt.ini';
const certbotCommand = 'certbot --config-dir /data/letsencrypt';
const archiver = require('archiver');
const path = require('path');
const { isArray } = require('lodash');
const certbotConfig = '/data/ssl/certbot/config.ini';
const certbotCommand = 'certbot --config-dir /data/ssl/certbot';
function omissions() {
return ['is_deleted'];
@@ -45,10 +44,9 @@ const internalCertificate = {
logger.info('Renewing SSL certs close to expiry...');
const cmd = certbotCommand + ' renew --non-interactive --quiet ' +
'--config "' + letsencryptConfig + '" ' +
'--config "' + certbotConfig + '" ' +
'--preferred-challenges "dns,http" ' +
'--disable-hook-validation ' +
(letsencryptStaging ? '--staging' : '');
'--disable-hook-validation';
return utils.exec(cmd)
.then((result) => {
@@ -63,7 +61,7 @@ const internalCertificate = {
});
})
.then(() => {
// Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times
// Now go and fetch all the certbot certs from the db and query the files and update expiry times
return certificateModel
.query()
.where('is_deleted', 0)
@@ -74,7 +72,7 @@ const internalCertificate = {
certificates.map(function (certificate) {
promises.push(
internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem')
.then((cert_info) => {
return certificateModel
.query()
@@ -202,9 +200,9 @@ const internalCertificate = {
}
})
.then(() => {
// At this point, the letsencrypt cert should exist on disk.
// At this point, the certbot cert should exist on disk.
// Lets get the expiry date from the file and update the row silently
return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
return internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem')
.then((cert_info) => {
return certificateModel
.query()
@@ -354,7 +352,7 @@ const internalCertificate = {
})
.then((certificate) => {
if (certificate.provider === 'letsencrypt') {
const zipDirectory = '/data/letsencrypt/live/npm-' + data.id;
const zipDirectory = '/data/ssl/certbot/live/npm-' + data.id;
if (!fs.existsSync(zipDirectory)) {
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
@@ -523,7 +521,7 @@ const internalCertificate = {
return new Promise((resolve, reject) => {
if (certificate.provider === 'letsencrypt') {
reject(new Error('Refusing to write letsencrypt certs here'));
reject(new Error('Refusing to write certbot certs here'));
return;
}
@@ -844,14 +842,12 @@ const internalCertificate = {
logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const cmd = certbotCommand + ' certonly ' +
'--config "' + letsencryptConfig + '" ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' +
'--authenticator webroot ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--preferred-challenges "dns,http" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
(letsencryptStaging ? '--staging' : '');
'--domains "' + certificate.domain_names.join(',') + '"';
logger.info('Command:', cmd);
@@ -878,24 +874,18 @@ const internalCertificate = {
logger.info(`Requesting Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id;
const credentialsLocation = '/data/ssl/certbot/credentials/credentials-' + certificate.id;
// Escape single quotes and backslashes
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
const credentialsCmd = 'mkdir -p /data/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
const credentialsCmd = 'mkdir -p /data/ssl/certbot/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
let prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
// Special case for cloudflare
if (dns_plugin.package_name === 'certbot-dns-cloudflare') {
prepareCmd = 'pip install certbot-dns-cloudflare --index-url https://www.piwheels.org/simple --prefer-binary';
}
// Whether the plugin has a --<name>-credentials argument
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
let mainCmd = certbotCommand + ' certonly ' +
'--config "' + letsencryptConfig + '" ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
'--authenticator ' + dns_plugin.full_plugin_name + ' ' +
@@ -908,8 +898,7 @@ const internalCertificate = {
certificate.meta.propagation_seconds !== undefined
? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
: ''
) +
(letsencryptStaging ? ' --staging' : '');
);
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
@@ -954,7 +943,7 @@ const internalCertificate = {
return renewMethod(certificate)
.then(() => {
return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem');
return internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem');
})
.then((cert_info) => {
return certificateModel
@@ -989,12 +978,11 @@ const internalCertificate = {
logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const cmd = certbotCommand + ' renew --force-renewal ' +
'--config "' + letsencryptConfig + '" ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--preferred-challenges "dns,http" ' +
'--no-random-sleep-on-renew ' +
'--disable-hook-validation ' +
(letsencryptStaging ? '--staging' : '');
'--disable-hook-validation ';
logger.info('Command:', cmd);
@@ -1019,15 +1007,14 @@ const internalCertificate = {
logger.info(`Renewing Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
let mainCmd = certbotCommand + ' renew ' +
'--config "' + letsencryptConfig + '" ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--disable-hook-validation ' +
'--no-random-sleep-on-renew ' +
(letsencryptStaging ? ' --staging' : '');
'--no-random-sleep-on-renew';
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id;
const credentialsLocation = '/data/ssl/certbot/credentials/credentials-' + certificate.id;
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
}
@@ -1049,13 +1036,12 @@ const internalCertificate = {
logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const mainCmd = certbotCommand + ' revoke ' +
'--config "' + letsencryptConfig + '" ' +
'--cert-path "/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
'--delete-after-revoke ' +
(letsencryptStaging ? '--staging' : '');
'--config "' + certbotConfig + '" ' +
'--cert-path "/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem" ' +
'--delete-after-revoke';
// Don't fail command if file does not exist
const delete_credentialsCmd = `rm -f '/data/letsencrypt/credentials/credentials-${certificate.id}' || true`;
const delete_credentialsCmd = `rm -f '/data/ssl/certbot/credentials/credentials-${certificate.id}' || true`;
logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd);
@@ -1079,7 +1065,7 @@ const internalCertificate = {
* @returns {Boolean}
*/
hasLetsEncryptSslCerts: (certificate) => {
const letsencryptPath = '/data/letsencrypt/live/npm-' + certificate.id;
const letsencryptPath = '/data/ssl/certbot/live/npm-' + certificate.id;
return fs.existsSync(letsencryptPath + '/fullchain.pem') && fs.existsSync(letsencryptPath + '/privkey.pem');
},
@@ -1155,7 +1141,7 @@ const internalCertificate = {
}
// Create a test challenge file
const testChallengeDir = '/tmp/letsencrypt-acme-challenge/.well-known/acme-challenge';
const testChallengeDir = '/tmp/acme-challenge/.well-known/acme-challenge';
const testChallengeFile = testChallengeDir + '/test-challenge';
fs.mkdirSync(testChallengeDir, {recursive: true});
fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'});

View File

@@ -270,7 +270,7 @@ const internalNginx = {
/**
* This generates a temporary nginx config listening on port 80 for the domain names listed
* in the certificate setup. It allows the letsencrypt acme challenge to be requested by letsencrypt
* in the certificate setup. It allows the certbot acme challenge to be requested by certbot
* when requesting a certificate without having a hostname set up already.
*
* @param {Object} certificate
@@ -278,7 +278,7 @@ const internalNginx = {
*/
generateLetsEncryptRequestConfig: (certificate) => {
if (debug_mode) {
logger.info('Generating LetsEncrypt Request Config:', certificate);
logger.info('Generating certbot Request Config:', certificate);
}
let renderEngine = new Liquid({
@@ -287,10 +287,10 @@ const internalNginx = {
return new Promise((resolve, reject) => {
let template = null;
let filename = '/usr/local/nginx/conf/conf.d/letsencrypt_' + certificate.id + '.conf';
let filename = '/usr/local/nginx/conf/conf.d/certbot_' + certificate.id + '.conf';
try {
template = fs.readFileSync(__dirname + '/../templates/letsencrypt-request.conf', {encoding: 'utf8'});
template = fs.readFileSync(__dirname + '/../templates/certbot-request.conf', {encoding: 'utf8'});
} catch (err) {
reject(new error.ConfigurationError(err.message));
return;

View File

@@ -172,7 +172,7 @@
"description": "Domain Names separated by a comma",
"example": "*.jc21.com,blog.jc21.com",
"type": "array",
"maxItems": 15,
"maxItems": 64,
"uniqueItems": true,
"items": {
"type": "string",

View File

@@ -169,26 +169,21 @@ const setupCertbotPlugins = () => {
.andWhere('provider', 'letsencrypt')
.then((certificates) => {
if (certificates && certificates.length) {
let plugins = [];
let promises = [];
let install_cloudflare_plugin = false;
let plugins = [];
let promises = [];
certificates.map(function (certificate) {
if (certificate.meta && certificate.meta.dns_challenge === true) {
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
if (dns_plugin.package_name === 'certbot-dns-cloudflare') {
install_cloudflare_plugin = true;
} else {
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
}
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
// Make sure credentials file exists
const credentials_loc = '/data/letsencrypt/credentials/credentials-' + certificate.id;
const credentials_loc = '/data/ssl/certbot/credentials/credentials-' + certificate.id;
// Escape single quotes and backslashes
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /data/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /data/ssl/certbot/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
promises.push(utils.exec(credentials_cmd));
}
});
@@ -198,10 +193,6 @@ const setupCertbotPlugins = () => {
promises.push(utils.exec(install_cmd));
}
if (install_cloudflare_plugin) {
promises.push(utils.exec('pip install certbot-dns-cloudflare --index-url https://www.piwheels.org/simple --prefer-binary'));
}
if (promises.length) {
return Promise.all(promises)
.then(() => {

View File

@@ -2,17 +2,17 @@
{% if certificate.provider == "letsencrypt" %}
# Let's Encrypt SSL
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem;
ssl_trusted_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/chain.pem;
ssl_certificate /data/ssl/certbot/live/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/ssl/certbot/live/npm-{{ certificate_id }}/privkey.pem;
ssl_trusted_certificate /data/ssl/certbot/live/npm-{{ certificate_id }}/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
{% else %}
# Custom SSL
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /data/custom_ssl/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem;
ssl_trusted_certificate /data/custom_ssl/npm-{{ certificate_id }}/chain.pem;
ssl_certificate /data/ssl/custom/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/ssl/custom/npm-{{ certificate_id }}/privkey.pem;
ssl_trusted_certificate /data/ssl/custom/npm-{{ certificate_id }}/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
{% endif %}

View File

@@ -6,11 +6,11 @@ server {
server_name {{ domain_names | join: " " }};
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
include conf.d/include/block-exploits.conf;
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
return 404;
}
}

View File

@@ -8,13 +8,17 @@ server {
{% include "_forced_ssl.conf" %}
{{ advanced_config }}
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
include conf.d/include/block-exploits.conf;
{% if use_default_location %}
location / {
alias /html/404/;
include conf.d/include/acme-challenge.conf;
}
{% endif %}
# Custom
include /data/nginx/custom/server_dead.conf;
}
{% endif %}

View File

@@ -15,7 +15,7 @@ server {
include conf.d/include/force-ssl.conf;
include conf.d/include/ssl-ciphers.conf;
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
include conf.d/include/block-exploits.conf;
add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400';
@@ -30,21 +30,21 @@ server {
{%- if value == "redirect" %}
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
return 307 {{ meta.redirect }};
}
{%- endif %}
{%- if value == "congratulations" %}
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
alias /html/default/;
}
{%- endif %}
{%- if value == "html" %}
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
alias /data/nginx/html/;
}
{%- endif %}

View File

@@ -11,14 +11,14 @@ server {
{% include "_hsts.conf" %}
{% include "_forced_ssl.conf" %}
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
include conf.d/include/block-exploits.conf;
{{ advanced_config }}
{% if use_default_location %}
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
{% if access_list_id > 0 %}
{% if access_list.items.length > 0 %}
@@ -40,7 +40,7 @@ server {
{% if access_list.items.length > 0 %}
# Authorization
auth_basic "Authorization required";
auth_basic_user_file /data/access/{{ access_list_id }};
auth_basic_user_file /data/nginx/access/{{ access_list_id }};
{{ access_list.passauth }}
{% endif %}

View File

@@ -8,11 +8,11 @@ server {
{% include "_forced_ssl.conf" %}
{{ advanced_config }}
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
include conf.d/include/block-exploits.conf;
{% if use_default_location %}
location / {
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/acme-challenge.conf;
{% if preserve_path == 1 or preserve_path == true %}
return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri;
{% else %}