Skip to content

Make auto-renew use built-in renew function #3392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 46 additions & 55 deletions backend/internal/certificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const config = require('../lib/config');
const error = require('../lib/error');
const utils = require('../lib/utils');
const certificateModel = require('../models/certificate');
const tokenModel = require('../models/token');
const dnsPlugins = require('../global/certbot-dns-plugins');
const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx');
Expand All @@ -26,10 +27,11 @@ function omissions() {

const internalCertificate = {

allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
intervalTimeout: 1000 * 60 * 60, // 1 hour
interval: null,
intervalProcessing: false,
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
intervalTimeout: 1000 * 60 * 60, // 1 hour
interval: null,
intervalProcessing: false,
renewBeforeExpirationBy: [30, 'days'],

initTimer: () => {
logger.info('Let\'s Encrypt Renewal Timer initialized');
Expand All @@ -44,62 +46,51 @@ const internalCertificate = {
processExpiringHosts: () => {
if (!internalCertificate.intervalProcessing) {
internalCertificate.intervalProcessing = true;
logger.info('Renewing SSL certs close to expiry...');

const cmd = certbotCommand + ' renew --non-interactive --quiet ' +
'--config "' + letsencryptConfig + '" ' +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--preferred-challenges "dns,http" ' +
'--disable-hook-validation ' +
(letsencryptStaging ? '--staging' : '');

return utils.exec(cmd)
.then((result) => {
if (result) {
logger.info('Renew Result: ' + result);
logger.info('Renewing SSL certs expiring within ' + internalCertificate.renewBeforeExpirationBy[0] + ' ' + internalCertificate.renewBeforeExpirationBy[1] + ' ...');

const expirationThreshold = moment().add(internalCertificate.renewBeforeExpirationBy[0], internalCertificate.renewBeforeExpirationBy[1]).format('YYYY-MM-DD HH:mm:ss');

// Fetch all the letsencrypt certs from the db that will expire within the configured threshold
certificateModel
.query()
.where('is_deleted', 0)
.andWhere('provider', 'letsencrypt')
.andWhere('expires_on', '<', expirationThreshold)
.then((certificates) => {
if (!certificates || !certificates.length) {
return null;
}

return internalNginx.reload()
.then(() => {
logger.info('Renew Complete');
return result;
});
})
.then(() => {
// Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times
return certificateModel
.query()
.where('is_deleted', 0)
.andWhere('provider', 'letsencrypt')
.then((certificates) => {
if (certificates && certificates.length) {
let promises = [];

certificates.map(function (certificate) {
promises.push(
internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
.then((cert_info) => {
return certificateModel
.query()
.where('id', certificate.id)
.andWhere('provider', 'letsencrypt')
.patch({
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
});
})
.catch((err) => {
// Don't want to stop the train here, just log the error
logger.error(err.message);
})
);
});
/**
* Renews must be run sequentially or we'll get an error 'Another
* instance of Certbot is already running.'
*/
let sequence = Promise.resolve();

certificates.forEach(function (certificate) {
sequence = sequence.then(() =>
internalCertificate
.renew(
{
can: () =>
Promise.resolve({
permission_visibility: 'all',
}),
token: new tokenModel(),
},
{ id: certificate.id },
)
.catch((err) => {
// Don't want to stop the train here, just log the error
logger.error(err.message);
}),
);
});

return Promise.all(promises);
}
});
return sequence;
})
.then(() => {
logger.info('Completed SSL cert renew process');
internalCertificate.intervalProcessing = false;
})
.catch((err) => {
Expand Down