Implements backend changes to allow more dns challenges

This commit is contained in:
chaptergy 2020-10-06 14:52:06 +02:00
parent 05f6a55a0b
commit 093b48ad7b
2 changed files with 91 additions and 35 deletions

View File

@ -13,6 +13,7 @@ const internalNginx = require('./nginx');
const internalHost = require('./host'); const internalHost = require('./host');
const certbot_command = '/usr/bin/certbot'; const certbot_command = '/usr/bin/certbot';
const le_config = '/etc/letsencrypt.ini'; const le_config = '/etc/letsencrypt.ini';
const dns_plugins = require('../../utils/certbot-dns-plugins')
function omissions() { function omissions() {
return ['is_deleted']; return ['is_deleted'];
@ -141,11 +142,11 @@ const internalCertificate = {
}); });
}) })
.then((in_use_result) => { .then((in_use_result) => {
// Is CloudFlare, no config needed, so skip 3 and 5. // With DNS challenge no config is needed, so skip 3 and 5.
if (data.meta.cloudflare_use) { if (certificate.meta.dns_challenge) {
return internalNginx.reload().then(() => { return internalNginx.reload().then(() => {
// 4. Request cert // 4. Request cert
return internalCertificate.requestLetsEncryptCloudFlareDnsSsl(certificate, data.meta.cloudflare_token); return internalCertificate.requestLetsEncryptSslWithDnsChallenge(certificate);
}) })
.then(internalNginx.reload) .then(internalNginx.reload)
.then(() => { .then(() => {
@ -772,35 +773,58 @@ const internalCertificate = {
}, },
/** /**
* @param {Object} certificate the certificate row * @param {Object} certificate the certificate row
* @param {String} apiToken the cloudflare api token * @param {String} dns_provider the dns provider name (key used in `certbot-dns-plugins.js`)
* @param {String | null} credentials the content of this providers credentials file
* @param {String} propagation_seconds the cloudflare api token
* @returns {Promise} * @returns {Promise}
*/ */
requestLetsEncryptCloudFlareDnsSsl: (certificate, apiToken) => { requestLetsEncryptSslWithDnsChallenge: (certificate) => {
logger.info('Requesting Let\'sEncrypt certificates via Cloudflare DNS for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const dns_plugin = dns_plugins[certificate.meta.dns_provider];
let tokenLoc = '~/cloudflare-token'; if(!dns_plugin){
let storeKey = 'echo "dns_cloudflare_api_token = ' + apiToken + '" > ' + tokenLoc; throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
}
let cmd = logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
storeKey + ' && ' +
const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
const main_cmd =
certbot_command + ' certonly --non-interactive ' + certbot_command + ' certonly --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' + '--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' + '--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' + '--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' + '--domains "' + certificate.domain_names.join(',') + '" ' +
'--dns-cloudflare --dns-cloudflare-credentials ' + tokenLoc + '--authenticator ' + dns_plugin.full_plugin_name + ' ' +
(le_staging ? ' --staging' : '') '--' + dns_plugin.full_plugin_name + '-credentials "' + credentials_loc + '"' +
+ ' && rm ' + tokenLoc; (
certificate.meta.propagation_seconds !== undefined
? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
: ''
) +
(le_staging ? ' --staging' : '');
const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) { if (debug_mode) {
logger.info('Command:', cmd); logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
} }
return utils.exec(cmd).then((result) => { return utils.exec(credentials_cmd)
logger.info(result); .then(() => {
return result; return utils.exec(prepare_cmd)
}); .then(() => {
return utils.exec(main_cmd)
.then(async (result) => {
await utils.exec(teardown_cmd);
logger.info(result);
return result;
});
});
});
}, },
@ -817,7 +841,7 @@ const internalCertificate = {
}) })
.then((certificate) => { .then((certificate) => {
if (certificate.provider === 'letsencrypt') { if (certificate.provider === 'letsencrypt') {
let renewMethod = certificate.meta.cloudflare_use ? internalCertificate.renewLetsEncryptCloudFlareSsl : internalCertificate.renewLetsEncryptSsl; let renewMethod = certificate.meta.dns_challenge ? internalCertificate.renewLetsEncryptSslWithDnsChallenge : internalCertificate.renewLetsEncryptSsl;
return renewMethod(certificate) return renewMethod(certificate)
.then(() => { .then(() => {
@ -877,22 +901,42 @@ const internalCertificate = {
* @param {Object} certificate the certificate row * @param {Object} certificate the certificate row
* @returns {Promise} * @returns {Promise}
*/ */
renewLetsEncryptCloudFlareSsl: (certificate) => { renewLetsEncryptSslWithDnsChallenge: (certificate) => {
logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const dns_plugin = dns_plugins[certificate.meta.dns_provider];
let cmd = certbot_command + ' renew --non-interactive ' + if(!dns_plugin){
'--cert-name "npm-' + certificate.id + '" ' + throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
'--disable-hook-validation ' +
(le_staging ? '--staging' : '');
if (debug_mode) {
logger.info('Command:', cmd);
} }
return utils.exec(cmd) logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
.then((result) => {
logger.info(result); const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
return result; const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
const main_cmd =
certbot_command + ' renew --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--disable-hook-validation' +
(le_staging ? ' --staging' : '');
const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) {
logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
}
return utils.exec(credentials_cmd)
.then(() => {
return utils.exec(prepare_cmd)
.then(() => {
return utils.exec(main_cmd)
.then(async (result) => {
await utils.exec(teardown_cmd);
logger.info(result);
return result;
});
});
}); });
}, },

View File

@ -42,11 +42,23 @@
"letsencrypt_agree": { "letsencrypt_agree": {
"type": "boolean" "type": "boolean"
}, },
"cloudflare_use": { "dns_challenge": {
"type": "boolean" "type": "boolean"
}, },
"cloudflare_token": { "dns_provider": {
"type": "string" "type": "string"
},
"dns_provider_credentials": {
"type": "string"
},
"propagation_seconds": {
"anyOf": [
{
"type": "integer",
"minimum": 0
}
]
} }
} }
} }