ssl.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. 'use strict';
  2. const fs = require('fs');
  3. const ejs = require('ejs');
  4. const timestamp = require('unix-timestamp');
  5. const internalNginx = require('./nginx');
  6. const logger = require('../logger');
  7. const utils = require('../lib/utils');
  8. const error = require('../lib/error');
  9. timestamp.round = true;
  10. const internalSsl = {
  11. interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
  12. interval: null,
  13. interval_processing: false,
  14. initTimer: () => {
  15. internalSsl.interval = setInterval(internalSsl.processExpiringHosts, internalSsl.interval_timeout);
  16. },
  17. /**
  18. * Triggered by a timer, this will check for expiring hosts and renew their ssl certs if required
  19. */
  20. processExpiringHosts: () => {
  21. if (!internalSsl.interval_processing) {
  22. logger.info('Renewing SSL certs close to expiry...');
  23. return utils.exec('/usr/bin/certbot renew --webroot=/config/letsencrypt-acme-challenge')
  24. .then(result => {
  25. logger.info(result);
  26. internalSsl.interval_processing = false;
  27. return internalNginx.reload()
  28. .then(() => {
  29. return result;
  30. });
  31. })
  32. .catch(err => {
  33. logger.error(err);
  34. internalSsl.interval_processing = false;
  35. });
  36. }
  37. },
  38. /**
  39. * @param {Object} host
  40. * @returns {Boolean}
  41. */
  42. hasValidSslCerts: host => {
  43. return fs.existsSync('/etc/letsencrypt/live/' + host.hostname + '/fullchain.pem') &&
  44. fs.existsSync('/etc/letsencrypt/live/' + host.hostname + '/privkey.pem');
  45. },
  46. /**
  47. * @param {Object} host
  48. * @returns {Promise}
  49. */
  50. requestSsl: host => {
  51. logger.info('Requesting SSL certificates for ' + host.hostname);
  52. return utils.exec('/usr/bin/letsencrypt certonly --agree-tos --email "' + host.letsencrypt_email + '" -n -a webroot --webroot-path=/config/letsencrypt-acme-challenge -d "' + host.hostname + '"')
  53. .then(result => {
  54. logger.info(result);
  55. return result;
  56. });
  57. },
  58. /**
  59. * @param {Object} host
  60. * @returns {Promise}
  61. */
  62. renewSsl: host => {
  63. logger.info('Renewing SSL certificates for ' + host.hostname);
  64. return utils.exec('/usr/bin/certbot renew --force-renewal --disable-hook-validation --webroot-path=/config/letsencrypt-acme-challenge --cert-name "' + host.hostname + '"')
  65. .then(result => {
  66. logger.info(result);
  67. return result;
  68. });
  69. },
  70. /**
  71. * @param {Object} host
  72. * @returns {Promise}
  73. */
  74. deleteCerts: host => {
  75. logger.info('Deleting SSL certificates for ' + host.hostname);
  76. return utils.exec('/usr/bin/certbot delete -n --cert-name "' + host.hostname + '"')
  77. .then(result => {
  78. logger.info(result);
  79. })
  80. .catch(err => {
  81. logger.error(err);
  82. });
  83. },
  84. /**
  85. * @param {Object} host
  86. * @returns {Promise}
  87. */
  88. generateSslSetupConfig: host => {
  89. let template = null;
  90. let filename = internalNginx.getConfigName(host);
  91. let template_data = host;
  92. return new Promise((resolve, reject) => {
  93. try {
  94. template = fs.readFileSync(__dirname + '/../templates/letsencrypt.conf.ejs', {encoding: 'utf8'});
  95. let config_text = ejs.render(template, template_data);
  96. fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
  97. resolve(template_data);
  98. } catch (err) {
  99. reject(new error.ConfigurationError(err.message));
  100. }
  101. });
  102. },
  103. /**
  104. * @param {Object} host
  105. * @returns {Promise}
  106. */
  107. configureSsl: host => {
  108. return internalSsl.generateSslSetupConfig(host)
  109. .then(data => {
  110. return internalNginx.reload()
  111. .then(() => {
  112. return internalSsl.requestSsl(data);
  113. });
  114. });
  115. }
  116. };
  117. module.exports = internalSsl;