Эх сурвалжийг харах

Adds certbot plugin installation check on startup

chaptergy 5 жил өмнө
parent
commit
1028de8158

+ 20 - 30
backend/internal/certificate.js

@@ -788,7 +788,7 @@ const internalCertificate = {
 
 		logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
 
-		const credentials_loc = '/etc/letsencrypt/credentials-' + certificate.id;
+		const credentials_loc = '/etc/letsencrypt/credentials/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;
 
@@ -818,11 +818,9 @@ const internalCertificate = {
 		if (certificate.meta.dns_provider === 'route53') {
 			main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
 		}
-		
-		const teardown_cmd = `rm '${credentials_loc}'`;
 
 		if (debug_mode) {
-			logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
+			logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd}`);
 		}
 
 		return utils.exec(credentials_cmd)
@@ -831,11 +829,15 @@ const internalCertificate = {
 					.then(() => {
 						return utils.exec(main_cmd)
 							.then(async (result) => {
-								await utils.exec(teardown_cmd);
 								logger.info(result);
 								return result;
 							});
 					});
+			}).catch(async (err) => {
+				// Don't fail if file does not exist
+				const delete_credentials_cmd = `rm -f '${credentials_loc}' || true`;
+				await utils.exec(delete_credentials_cmd);
+				throw err;
 			});
 	},
 
@@ -922,10 +924,6 @@ const internalCertificate = {
 
 		logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
 
-		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;
-
 		let main_cmd = 
 			certbot_command + ' renew --non-interactive ' +
 			'--cert-name "npm-' + certificate.id + '" ' +
@@ -937,23 +935,14 @@ const internalCertificate = {
 			main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
 		}
 
-		const teardown_cmd = `rm '${credentials_loc}'`;
-
 		if (debug_mode) {
-			logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
+			logger.info('Command:', main_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;
-							});
-					});
+		return utils.exec(main_cmd)
+			.then(async (result) => {
+				logger.info(result);
+				return result;
 			});
 	},
 
@@ -965,20 +954,21 @@ const internalCertificate = {
 	revokeLetsEncryptSsl: (certificate, throw_errors) => {
 		logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
-		let cmd = certbot_command + ' revoke --non-interactive ' +
+		const main_cmd = certbot_command + ' revoke --non-interactive ' +
 			'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
 			'--delete-after-revoke ' +
 			(le_staging ? '--staging' : '');
 
+		// Don't fail command if file does not exist
+		const delete_credentials_cmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;
+
 		if (debug_mode) {
-			logger.info('Command:', cmd);
+			logger.info('Command:', main_cmd + '; ' + delete_credentials_cmd);
 		}
 
-		return utils.exec(cmd)
-			.then((result) => {
-				if (debug_mode) {
-					logger.info('Command:', cmd);
-				}
+		return utils.exec(main_cmd)
+			.then(async (result) => {
+				await utils.exec(delete_credentials_cmd);
 				logger.info(result);
 				return result;
 			})

+ 42 - 1
backend/setup.js

@@ -2,10 +2,13 @@ const fs                  = require('fs');
 const NodeRSA             = require('node-rsa');
 const config              = require('config');
 const logger              = require('./logger').setup;
+const certificateModel 		= require('./models/certificate');
 const userModel           = require('./models/user');
 const userPermissionModel = require('./models/user_permission');
+const utils            		= require('./lib/utils');
 const authModel           = require('./models/auth');
 const settingModel        = require('./models/setting');
+const dns_plugins         = require('./global/certbot-dns-plugins');
 const debug_mode          = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
 
 /**
@@ -155,8 +158,46 @@ const setupDefaultSettings = () => {
 		});
 };
 
+/**
+ * Installs all Certbot plugins which are required for an installed certificate
+ *
+ * @returns {Promise}
+ */
+const setupCertbotPlugins = () => {
+	return certificateModel
+	.query()
+	.where('is_deleted', 0)
+	.andWhere('provider', 'letsencrypt')
+	.then((certificates) => {
+		if (certificates && certificates.length) {
+			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 package = `${dns_plugin.package_name}==${dns_plugin.package_version}`;
+					if (plugins.indexOf(package) === -1) plugins.push(package);
+
+					// Make sure credentials file exists
+					const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id; 
+					const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir /etc/letsencrypt/credentials; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
+					promises.push(utils.exec(credentials_cmd));
+				}
+			});
+
+			const install_cmd = 'pip3 install ' + plugins.join(' ');
+			promises.push(utils.exec(install_cmd));
+			return Promise.all(promises).then(() => { 
+				logger.info('Added Certbot plugins ' + plugins.join(', ')); 
+			});
+		}
+	});
+};
+
 module.exports = function () {
 	return setupJwt()
 		.then(setupDefaultUser)
-		.then(setupDefaultSettings);
+		.then(setupDefaultSettings)
+		.then(setupCertbotPlugins);
 };

+ 1 - 1
frontend/js/i18n/messages.json

@@ -109,7 +109,7 @@
       "please-choose": "Please Choose...",
       "credentials-file-content": "Credentials File Content",
       "credentials-file-content-info": "This plugin requires a configuration file containing an API token or other credentials to your provider",
-      "stored-as-plaintext-info": "This data will be stored as plaintext in the database!",
+      "stored-as-plaintext-info": "This data will be stored as plaintext in the database and in a file!",
       "propagation-seconds": "Propagation Seconds",
       "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",
       "processing-info": "Processing... This might take a few minutes."

+ 1 - 1
global/certbot-dns-plugins.js

@@ -181,7 +181,7 @@ dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
 	njalla: {
 		display_name:     'Njalla',
 		package_name:     'certbot-dns-njalla',
-		package_version:  '0.0.4',
+		package_version:  '1.0.0',
 		credentials:      'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
 		full_plugin_name: 'certbot-dns-njalla:dns-njalla',
 	},