forked from coolaj86/goldilocks.js
		
	added support for different ACME config for different domains
This commit is contained in:
		
							parent
							
								
									21a77ad10a
								
							
						
					
					
						commit
						3633c7570b
					
				@ -10,18 +10,40 @@ tcp:
 | 
			
		||||
      address: '127.0.0.1:8022'
 | 
			
		||||
 | 
			
		||||
tls:
 | 
			
		||||
  acme:
 | 
			
		||||
    email: 'joe.shmoe@example.com'
 | 
			
		||||
    server: 'https://acme-staging.api.letsencrypt.org/directory'
 | 
			
		||||
    challenge_type: 'http-01'
 | 
			
		||||
    approved_domains:
 | 
			
		||||
      - localhost.baz.daplie.me
 | 
			
		||||
      - localhost.beta.daplie.me
 | 
			
		||||
  domains:
 | 
			
		||||
    - names:
 | 
			
		||||
        - localhost.gamma.daplie.me
 | 
			
		||||
      modules:
 | 
			
		||||
        - name: proxy
 | 
			
		||||
          address: '127.0.0.1:6443'
 | 
			
		||||
    - names:
 | 
			
		||||
        - beta.localhost.daplie.me
 | 
			
		||||
        - baz.localhost.daplie.me
 | 
			
		||||
      modules:
 | 
			
		||||
        - name: acme
 | 
			
		||||
          email: 'owner@example.com'
 | 
			
		||||
          challenge_type: 'tls-sni-01'
 | 
			
		||||
          # default server is 'https://acme-v01.api.letsencrypt.org/directory'
 | 
			
		||||
  modules:
 | 
			
		||||
    - name: proxy
 | 
			
		||||
      domains:
 | 
			
		||||
        - localhost.bar.daplie.me
 | 
			
		||||
        - localhost.foo.daplie.me
 | 
			
		||||
      address: '127.0.0.1:5443'
 | 
			
		||||
    - name: acme
 | 
			
		||||
      email: 'guest@example.com'
 | 
			
		||||
      challenge_type: 'http-01'
 | 
			
		||||
      domains:
 | 
			
		||||
        - foo.localhost.daplie.me
 | 
			
		||||
        - gamma.localhost.daplie.me
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
http:
 | 
			
		||||
  trust_proxy: true
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,12 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
    return value || '';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function nameMatchesDomains(name, domains) {
 | 
			
		||||
    return domains.some(function (pattern) {
 | 
			
		||||
      return domainMatches(pattern, name);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var addressNames = [
 | 
			
		||||
    'remoteAddress'
 | 
			
		||||
  , 'remotePort'
 | 
			
		||||
@ -67,17 +73,17 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var le = greenlock.create({
 | 
			
		||||
    // server: 'staging'
 | 
			
		||||
    server: 'https://acme-v01.api.letsencrypt.org/directory'
 | 
			
		||||
 | 
			
		||||
  , challenges: {
 | 
			
		||||
      'http-01': require('le-challenge-fs').create({ webrootPath: '/tmp/acme-challenges', debug: config.debug })
 | 
			
		||||
      'http-01': require('le-challenge-fs').create({ debug: config.debug })
 | 
			
		||||
    , 'tls-sni-01': require('le-challenge-sni').create({ debug: config.debug })
 | 
			
		||||
      // TODO dns-01
 | 
			
		||||
      //, 'dns-01': require('le-challenge-ddns').create()
 | 
			
		||||
      //, 'dns-01': require('le-challenge-ddns').create({ debug: config.debug })
 | 
			
		||||
    }
 | 
			
		||||
  , challengeType: 'http-01'
 | 
			
		||||
 | 
			
		||||
  , store: require('le-store-certbot').create({ webrootPath: '/tmp/acme-challenges' })
 | 
			
		||||
  , store: require('le-store-certbot').create({ debug: config.debug })
 | 
			
		||||
 | 
			
		||||
  , approveDomains: function (opts, certs, cb) {
 | 
			
		||||
      // This is where you check your database and associated
 | 
			
		||||
@ -88,60 +94,87 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
      if (certs) {
 | 
			
		||||
        // TODO make sure the same options are used for renewal as for registration?
 | 
			
		||||
        opts.domains = certs.altnames;
 | 
			
		||||
 | 
			
		||||
        cb(null, { options: opts, certs: certs });
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function complete(optsOverride) {
 | 
			
		||||
        Object.keys(optsOverride).forEach(function (key) {
 | 
			
		||||
          opts[key] = optsOverride[key];
 | 
			
		||||
        });
 | 
			
		||||
      function complete(optsOverride, domains) {
 | 
			
		||||
        if (!cb) {
 | 
			
		||||
          console.warn('tried to complete domain approval multiple times');
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We can't request certificates for wildcard domains, so filter any of those
 | 
			
		||||
        // out of this list and put the domain that triggered this in the list if needed.
 | 
			
		||||
        domains = (domains || []).filter(function (dom) { return dom[0] !== '*'; });
 | 
			
		||||
        if (domains.indexOf(opts.domain) < 0) {
 | 
			
		||||
          domains.push(opts.domain);
 | 
			
		||||
        }
 | 
			
		||||
        // TODO: allow user to specify options for challenges or storage.
 | 
			
		||||
 | 
			
		||||
        Object.assign(opts, optsOverride, { domains: domains, agreeTos: true });
 | 
			
		||||
        cb(null, { options: opts, certs: certs });
 | 
			
		||||
        cb = null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var handled = false;
 | 
			
		||||
      if (Array.isArray(config.tls.domains)) {
 | 
			
		||||
        handled = config.tls.domains.some(function (dom) {
 | 
			
		||||
          if (!nameMatchesDomains(opts.domain, dom.names)) {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
      // check config for domain name
 | 
			
		||||
      if (-1 !== (config.tls.servernames || []).indexOf(opts.domain)) {
 | 
			
		||||
        // TODO how to handle SANs?
 | 
			
		||||
        // TODO fetch domain-specific email
 | 
			
		||||
        // TODO fetch domain-specific acmeDirectory
 | 
			
		||||
        // NOTE: you can also change other options such as `challengeType` and `challenge`
 | 
			
		||||
        // opts.challengeType = 'http-01';
 | 
			
		||||
        // opts.challenge = require('le-challenge-fs').create({}); // TODO this doesn't actually work yet
 | 
			
		||||
        complete({
 | 
			
		||||
          return dom.modules.some(function (mod) {
 | 
			
		||||
            if (mod.name !== 'acme') {
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            complete(mod, dom.names);
 | 
			
		||||
            return true;
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      if (handled) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (Array.isArray(config.tls.modules)) {
 | 
			
		||||
        handled = config.tls.modules.some(function (mod) {
 | 
			
		||||
          if (mod.name !== 'acme') {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
          if (!nameMatchesDomains(opts.domain, mod.domains)) {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          complete(mod, mod.domains);
 | 
			
		||||
          return true;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      if (handled) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var defAcmeConf;
 | 
			
		||||
      if (config.tls.acme) {
 | 
			
		||||
        defAcmeConf = config.tls.acme;
 | 
			
		||||
      } else {
 | 
			
		||||
        defAcmeConf = {
 | 
			
		||||
          email: config.tls.email
 | 
			
		||||
        , agreeTos: true
 | 
			
		||||
        , server: config.tls.acmeDirectoryUrl || le.server
 | 
			
		||||
        , challengeType: config.tls.challengeType || 'http-01'
 | 
			
		||||
        });
 | 
			
		||||
        , challengeType: config.tls.challengeType || le.challengeType
 | 
			
		||||
        , approvedDomains: config.tls.servernames
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Check config for domain name
 | 
			
		||||
      // TODO: if `approvedDomains` isn't defined check all other modules to see if they can
 | 
			
		||||
      // handle this domain (and what other domains it's grouped with).
 | 
			
		||||
      if (-1 !== (defAcmeConf.approvedDomains || []).indexOf(opts.domain)) {
 | 
			
		||||
        complete(defAcmeConf, defAcmeConf.approvedDomains);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // TODO ask http module (and potentially all other modules) about what domains it can
 | 
			
		||||
      // handle. We can allow any domains that other modules will handle after we terminate TLS.
 | 
			
		||||
      cb(new Error('domain is not allowed'));
 | 
			
		||||
      // if (!modules.http) {
 | 
			
		||||
      //   modules.http = require('./modules/http.js').create(deps, config);
 | 
			
		||||
      // }
 | 
			
		||||
      // modules.http.checkServername(opts.domain).then(function (stuff) {
 | 
			
		||||
      //   if (!stuff || !stuff.domains) {
 | 
			
		||||
      //     // TODO once precheck is implemented we can just let it pass if it passes, yknow?
 | 
			
		||||
      //     cb(new Error('domain is not allowed'));
 | 
			
		||||
      //     return;
 | 
			
		||||
      //   }
 | 
			
		||||
 | 
			
		||||
      //   complete({
 | 
			
		||||
      //     domain: stuff.domain || stuff.domains[0]
 | 
			
		||||
      //   , domains: stuff.domains
 | 
			
		||||
      //   , email: stuff.email || program.email
 | 
			
		||||
      //   , server: stuff.acmeDirectoryUrl || program.acmeDirectoryUrl
 | 
			
		||||
      //   , challengeType: stuff.challengeType || program.challengeType
 | 
			
		||||
      //   , challenge: stuff.challenge
 | 
			
		||||
      //   });
 | 
			
		||||
      //   return;
 | 
			
		||||
      // }, cb);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  le.tlsOptions = le.tlsOptions || le.httpsOptions;
 | 
			
		||||
@ -257,10 +290,7 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var handled = (config.tls.domains || []).some(function (dom) {
 | 
			
		||||
      var relevant = dom.names.some(function (pattern) {
 | 
			
		||||
        return domainMatches(pattern, opts.servername);
 | 
			
		||||
      });
 | 
			
		||||
      if (!relevant) {
 | 
			
		||||
      if (!nameMatchesDomains(opts.servername, dom.names)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -271,10 +301,7 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handled = (config.tls.modules || []).some(function (mod) {
 | 
			
		||||
      var relevant = mod.domains.some(function (pattern) {
 | 
			
		||||
        return domainMatches(pattern, opts.servername);
 | 
			
		||||
      });
 | 
			
		||||
      if (!relevant) {
 | 
			
		||||
      if (!nameMatchesDomains(opts.servername, mod.domains)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      return checkModule(mod);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user