Jamie Curnow преди 7 години
родител
ревизия
724e89d308

+ 6 - 6
src/backend/index.js

@@ -5,11 +5,11 @@
 const logger = require('./logger').global;
 
 function appStart () {
-    const migrate      = require('./migrate');
-    const setup        = require('./setup');
-    const app          = require('./app');
-    const apiValidator = require('./lib/validator/api');
-    const internalSsl  = require('./internal/ssl');
+    const migrate             = require('./migrate');
+    const setup               = require('./setup');
+    const app                 = require('./app');
+    const apiValidator        = require('./lib/validator/api');
+    const internalCertificate = require('./internal/certificate');
 
     return migrate.latest()
         .then(() => {
@@ -20,7 +20,7 @@ function appStart () {
         })
         .then(() => {
 
-            internalSsl.initTimer();
+            internalCertificate.initTimer();
 
             const server = app.listen(81, () => {
                 logger.info('PID ' + process.pid + ' listening on port 81 ...');

+ 49 - 3
src/backend/internal/certificate.js

@@ -18,7 +18,43 @@ function omissions () {
 
 const internalCertificate = {
 
-    allowed_ssl_files: ['certificate', 'certificate_key', 'intermediate_certificate'],
+    allowed_ssl_files:   ['certificate', 'certificate_key', 'intermediate_certificate'],
+    interval_timeout:    1000 * 60 * 60 * 12, // 12 hours
+    interval:            null,
+    interval_processing: false,
+
+    initTimer: () => {
+        logger.info('Let\'s Encrypt Renewal Timer initialized');
+        internalCertificate.interval = setInterval(internalCertificate.processExpiringHosts, internalCertificate.interval_timeout);
+    },
+
+    /**
+     * Triggered by a timer, this will check for expiring hosts and renew their ssl certs if required
+     */
+    processExpiringHosts: () => {
+        let internalNginx = require('./nginx');
+
+        if (!internalCertificate.interval_processing) {
+            internalCertificate.interval_processing = true;
+            logger.info('Renewing SSL certs close to expiry...');
+
+            return utils.exec(certbot_command + ' renew -q ' + (debug_mode ? '--staging' : ''))
+                .then(result => {
+                    logger.info(result);
+                    internalCertificate.interval_processing = false;
+
+                    return internalNginx.reload()
+                        .then(() => {
+                            logger.info('Renew Complete');
+                            return result;
+                        });
+                })
+                .catch(err => {
+                    logger.error(err);
+                    internalCertificate.interval_processing = false;
+                });
+        }
+    },
 
     /**
      * @param   {Access}  access
@@ -493,7 +529,7 @@ const internalCertificate = {
      * @returns {Promise}
      */
     requestLetsEncryptSsl: certificate => {
-        logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id  + ': ' + certificate.domain_names.join(', '));
+        logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
         return utils.exec(certbot_command + ' certonly --cert-name "npm-' + certificate.id + '" --agree-tos ' +
             '--email "' + certificate.meta.letsencrypt_email + '" ' +
@@ -511,7 +547,7 @@ const internalCertificate = {
      * @returns {Promise}
      */
     renewLetsEncryptSsl: certificate => {
-        logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id  + ': ' + certificate.domain_names.join(', '));
+        logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
         return utils.exec(certbot_command + ' renew -n --force-renewal --disable-hook-validation --cert-name "npm-' + certificate.id + '" ' + (debug_mode ? '--staging' : ''))
             .then(result => {
@@ -519,6 +555,16 @@ const internalCertificate = {
                 return result;
             });
     },
+
+    /**
+     * @param   {Object}  certificate
+     * @returns {Boolean}
+     */
+    hasLetsEncryptSslCerts: certificate => {
+        let le_path = '/etc/letsencrypt/live/npm-' + certificate.id;
+
+        return fs.existsSync(le_path + '/fullchain.pem') && fs.existsSync(le_path + '/privkey.pem');
+    }
 };
 
 module.exports = internalCertificate;

+ 8 - 14
src/backend/internal/nginx.js

@@ -1,13 +1,13 @@
 'use strict';
 
-const _           = require('lodash');
-const fs          = require('fs');
-const Liquid      = require('liquidjs');
-const logger      = require('../logger').nginx;
-const utils       = require('../lib/utils');
-const error       = require('../lib/error');
-const internalSsl = require('./ssl');
-const debug_mode  = process.env.NODE_ENV !== 'production';
+const _                   = require('lodash');
+const fs                  = require('fs');
+const Liquid              = require('liquidjs');
+const logger              = require('../logger').nginx;
+const utils               = require('../lib/utils');
+const error               = require('../lib/error');
+const internalCertificate = require('./certificate');
+const debug_mode          = process.env.NODE_ENV !== 'production';
 
 const internalNginx = {
 
@@ -32,11 +32,6 @@ const internalNginx = {
                 // We're deleting this config regardless.
                 return internalNginx.deleteConfig(host_type, host); // Don't throw errors, as the file may not exist at all
             })
-            .then(() => {
-                if (host.ssl && !internalSsl.hasValidSslCerts(host_type, host)) {
-                    return internalSsl.configureSsl(host_type, host);
-                }
-            })
             .then(() => {
                 return internalNginx.generateConfig(host_type, host);
             })
@@ -56,7 +51,6 @@ const internalNginx = {
                             });
                     })
                     .catch(err => {
-
                         if (debug_mode) {
                             logger.error('Nginx test failed:', err.message);
                         }

+ 0 - 164
src/backend/internal/ssl.js

@@ -1,164 +0,0 @@
-'use strict';
-
-const fs            = require('fs');
-const Liquid        = require('liquidjs');
-const timestamp     = require('unix-timestamp');
-const internalNginx = require('./nginx');
-const logger        = require('../logger').ssl;
-const utils         = require('../lib/utils');
-const error         = require('../lib/error');
-
-timestamp.round = true;
-
-const internalSsl = {
-
-    interval_timeout:    1000 * 60 * 60 * 12, // 12 hours
-    interval:            null,
-    interval_processing: false,
-
-    initTimer: () => {
-        logger.info('Let\'s Encrypt Renewal Timer initialized');
-        internalSsl.interval = setInterval(internalSsl.processExpiringHosts, internalSsl.interval_timeout);
-    },
-
-    /**
-     * Triggered by a timer, this will check for expiring hosts and renew their ssl certs if required
-     */
-    processExpiringHosts: () => {
-        if (!internalSsl.interval_processing) {
-            logger.info('Renewing SSL certs close to expiry...');
-            return utils.exec('/usr/bin/certbot renew -q')
-                .then(result => {
-                    logger.info(result);
-                    internalSsl.interval_processing = false;
-
-                    return internalNginx.reload()
-                        .then(() => {
-                            logger.info('Renew Complete');
-                            return result;
-                        });
-                })
-                .catch(err => {
-                    logger.error(err);
-                    internalSsl.interval_processing = false;
-                });
-        }
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Boolean}
-     */
-    hasValidSslCerts: (host_type, host) => {
-        host_type   = host_type.replace(new RegExp('-', 'g'), '_');
-        let le_path = '/etc/letsencrypt/live/' + host_type + '-' + host.id;
-
-        return fs.existsSync(le_path + '/fullchain.pem') && fs.existsSync(le_path + '/privkey.pem');
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Promise}
-     */
-    requestSsl: (host_type, host) => {
-        logger.info('Requesting SSL certificates for ' + host_type + ' #' + host.id);
-
-        // TODO
-
-        return utils.exec('/usr/bin/letsencrypt certonly --agree-tos --email "' + host.letsencrypt_email + '" -n -a webroot -d "' + host.hostname + '"')
-            .then(result => {
-                logger.info(result);
-                return result;
-            });
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Promise}
-     */
-    renewSsl: (host_type, host) => {
-        logger.info('Renewing SSL certificates for ' + host_type + ' #' + host.id);
-
-        // TODO
-
-        return utils.exec('/usr/bin/certbot renew --force-renewal --disable-hook-validation --cert-name "' + host.hostname + '"')
-            .then(result => {
-                logger.info(result);
-                return result;
-            });
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Promise}
-     */
-    deleteCerts: (host_type, host) => {
-        logger.info('Deleting SSL certificates for ' + host_type + ' #' + host.id);
-
-        // TODO
-
-        return utils.exec('/usr/bin/certbot delete -n --cert-name "' + host.hostname + '"')
-            .then(result => {
-                logger.info(result);
-            })
-            .catch(err => {
-                logger.error(err);
-            });
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Promise}
-     */
-    generateSslSetupConfig: (host_type, host) => {
-        host_type = host_type.replace(new RegExp('-', 'g'), '_');
-
-        let renderEngine = Liquid();
-        let template     = null;
-        let filename     = internalNginx.getConfigName(host_type, host);
-
-        return new Promise((resolve, reject) => {
-            try {
-                template = fs.readFileSync(__dirname + '/../templates/letsencrypt.conf', {encoding: 'utf8'});
-            } catch (err) {
-                reject(new error.ConfigurationError(err.message));
-                return;
-            }
-
-            return renderEngine
-                .parseAndRender(template, host)
-                .then(config_text => {
-                    fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
-                    return template_data;
-                })
-                .catch(err => {
-                    throw new error.ConfigurationError(err.message);
-                });
-        });
-    },
-
-    /**
-     * @param   {String}  host_type
-     * @param   {Object}  host
-     * @returns {Promise}
-     */
-    configureSsl: (host_type, host) => {
-
-        // TODO
-
-        return internalSsl.generateSslSetupConfig(host)
-            .then(data => {
-                return internalNginx.reload()
-                    .then(() => {
-                        return internalSsl.requestSsl(data);
-                    });
-            });
-    }
-};
-
-module.exports = internalSsl;

+ 4 - 0
src/backend/templates/_assets.conf

@@ -0,0 +1,4 @@
+{% if caching_enabled == 1 or caching_enabled == true -%}
+  # Asset Caching
+  include conf.d/include/assets.conf;
+{%- endif %}

+ 12 - 0
src/backend/templates/_certificates.conf

@@ -0,0 +1,12 @@
+{%- if certificate and certificate_id > 0 -%}
+{%- if certificate.provider == "letsencrypt" %}
+  # Let's Encrypt SSL
+  include conf.d/include/letsencrypt-acme-challenge.conf;
+  include conf.d/include/ssl-ciphers.conf;
+  ssl_certificate /etc/letsencrypt/live/npm-{{ certificate.id }}/fullchain.pem;
+  ssl_certificate_key /etc/letsencrypt/live/npm-{{ certificate.id }}/privkey.pem;
+{%- endif -%}
+
+  # TODO: Custom SSL paths
+
+{%- endif %}

+ 4 - 0
src/backend/templates/_exploits.conf

@@ -0,0 +1,4 @@
+{% if block_exploits == 1 or block_exploits == true -%}
+  # Block Exploits
+  include conf.d/include/block-exploits.conf;
+{%- endif -%}

+ 6 - 0
src/backend/templates/_forced_ssl.conf

@@ -0,0 +1,6 @@
+{%- if certificate and certificate_id > 0 -%}
+{%- if ssl_forced == 1 or ssl_forced == true -%}
+    # Force SSL
+    include conf.d/include/force-ssl.conf;
+{%- endif -%}
+{%- endif %}

+ 3 - 0
src/backend/templates/_header_comment.conf

@@ -0,0 +1,3 @@
+# ------------------------------------------------------------
+# {{ domain_names | join: ", " }}
+# ------------------------------------------------------------

+ 5 - 0
src/backend/templates/_listen.conf

@@ -0,0 +1,5 @@
+  listen 80;
+{%- if certificate -%}
+  listen 443 ssl;
+{%- endif %}
+  server_name {{ domain_names | join: " " }};

+ 5 - 16
src/backend/templates/dead_host.conf

@@ -1,21 +1,10 @@
-# {{ domain_names | join: ", " }}
+{% include "_header_comment.conf" %}
+
 server {
-  listen 80;
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  listen 443 ssl;
-  {%- endif %}
-  server_name {{ domain_names | join: " " }};
-  access_log /data/logs/proxy_host-{{ id }}.log proxy;
+  {% include "_listen.conf" %}
+  {% include "_certificates.conf" %}
 
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  {%- if ssl_provider == "letsencrypt" %}
-  # Let's Encrypt SSL
-  include conf.d/include/letsencrypt-acme-challenge.conf;
-  include conf.d/include/ssl-ciphers.conf;
-  ssl_certificate /etc/letsencrypt/live/proxy_host-{{ id }}/fullchain.pem;
-  ssl_certificate_key /etc/letsencrypt/live/proxy_host-{{ id }}/privkey.pem;
-  {%- endif -%}
-  {%- endif %}
+  access_log /data/logs/dead_host-{{ id }}.log proxy;
 
   # TODO: Advanced config options
 

+ 0 - 10
src/backend/templates/letsencrypt.conf

@@ -1,10 +0,0 @@
-# Letsencrypt Verification Temporary Host: {{ domain_names | join: ", " }}
-server {
-  listen 80;
-  server_name {{ domain_names | join: " " }};
-  access_log /data/logs/letsencrypt.log proxy;
-
-  location / {
-    root /data/letsencrypt-acme-challenge;
-  }
-}

+ 8 - 31
src/backend/templates/proxy_host.conf

@@ -1,33 +1,15 @@
-# {{ domain_names | join: ", " }}
-server {
-  listen 80;
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  listen 443 ssl;
-  {%- endif %}
-  server_name {{ domain_names | join: " " }};
-  access_log /data/logs/proxy_host-{{ id }}.log proxy;
+{% include "_header_comment.conf" %}
 
+server {
   set $server {{ forward_ip }};
   set $port   {{ forward_port }};
 
-  {% if caching_enabled == 1 or caching_enabled == true -%}
-  # Asset Caching
-  include conf.d/include/assets.conf;
-  {%- endif %}
-  {% if block_exploits == 1 or block_exploits == true -%}
-  # Block Exploits
-  include conf.d/include/block-exploits.conf;
-  {%- endif -%}
+  {% include "_listen.conf" %}
+  {% include "_certificates.conf" %}
+  {% include "_assets.conf" %}
+  {% include "_exploits.conf" %}
 
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  {%- if ssl_provider == "letsencrypt" %}
-  # Let's Encrypt SSL
-  include conf.d/include/letsencrypt-acme-challenge.conf;
-  include conf.d/include/ssl-ciphers.conf;
-  ssl_certificate /etc/letsencrypt/live/proxy_host-{{ id }}/fullchain.pem;
-  ssl_certificate_key /etc/letsencrypt/live/proxy_host-{{ id }}/privkey.pem;
-  {%- endif -%}
-  {%- endif %}
+  access_log /data/logs/proxy_host-{{ id }}.log proxy;
 
   # TODO: Advanced config options
 
@@ -38,12 +20,7 @@ server {
     auth_basic_user_file  /config/access/{{ access_list_id }};
     {%- endif %}
 
-    {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-    {%- if ssl_forced == 1 or ssl_forced == true -%}
-    # Force SSL
-    include conf.d/include/force-ssl.conf;
-    {%- endif -%}
-    {%- endif %}
+    {% include "_forced_ssl.conf" %}
 
     # Proxy!
     include conf.d/include/proxy.conf;

+ 12 - 26
src/backend/templates/redirection_host.conf

@@ -1,34 +1,20 @@
-# {{ domain_names | join: ", " }}
-server {
-  listen 80;
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  listen 443 ssl;
-  {%- endif %}
-  server_name {{ domain_names | join: " " }};
-  access_log /data/logs/proxy_host-{{ id }}.log proxy;
+{% include "_header_comment.conf" %}
 
-  {%- if caching_enabled == 1 or caching_enabled == true %}
-  # Asset Caching
-  include conf.d/include/assets.conf;
-  {%- endif %}
-  {%- if block_exploits == 1 or block_exploits == true %}
-  # Block Exploits
-  include conf.d/include/block-exploits.conf;
-  {%- endif -%}
+server {
+  {% include "_listen.conf" %}
+  {% include "_certificates.conf" %}
+  {% include "_assets.conf" %}
+  {% include "_exploits.conf" %}
 
-  {%- if ssl_enabled == 1 or ssl_enabled == true -%}
-  {%- if ssl_provider == "letsencrypt" %}
-  # Let's Encrypt SSL
-  include conf.d/include/letsencrypt-acme-challenge.conf;
-  include conf.d/include/ssl-ciphers.conf;
-  ssl_certificate /etc/letsencrypt/live/proxy_host-{{ id }}/fullchain.pem;
-  ssl_certificate_key /etc/letsencrypt/live/proxy_host-{{ id }}/privkey.pem;
-  {%- endif -%}
-  {%- endif %}
+  access_log /data/logs/redirection_host-{{ id }}.log proxy;
 
   # TODO: Advanced config options
 
   # TODO: Preserve Path Option
 
-  return 301 $scheme://{{ forward_domain_name }}$request_uri;
+  location / {
+    {% include "_forced_ssl.conf" %}
+
+    return 301 $scheme://{{ forward_domain_name }}$request_uri;
+  }
 }

+ 6 - 4
src/backend/templates/stream.conf

@@ -1,14 +1,16 @@
+# ------------------------------------------------------------
 # {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
+# ------------------------------------------------------------
 
 {% if tcp_forwarding == 1 or tcp_forwarding == true -%}
 server {
-    listen {{ incoming_port }};
-    proxy_pass {{ forward_ip }}:{{ forwarding_port }};
+  listen {{ incoming_port }};
+  proxy_pass {{ forward_ip }}:{{ forwarding_port }};
 }
 {% endif %}
 {% if udp_forwarding == 1 or udp_forwarding == true %}
 server {
-    listen {{ incoming_port }} udp;
-    proxy_pass {{ forward_ip }}:{{ forwarding_port }};
+  listen {{ incoming_port }} udp;
+  proxy_pass {{ forward_ip }}:{{ forwarding_port }};
 }
 {% endif %}