export challenge underlay, and a few bugfixes in it
This commit is contained in:
parent
5a39d81ec8
commit
8fc805024b
|
@ -0,0 +1,96 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Greenlock = require('./');
|
||||||
|
|
||||||
|
module.exports.wrap = function(greenlock) {
|
||||||
|
greenlock.challenges.get = function(chall) {
|
||||||
|
// TODO pick one and warn on the others
|
||||||
|
// (just here due to some backwards compat issues with early v3 plugins)
|
||||||
|
var servername =
|
||||||
|
chall.servername ||
|
||||||
|
chall.altname ||
|
||||||
|
(chall.identifier && chall.identifier.value);
|
||||||
|
|
||||||
|
// TODO some sort of caching to prevent database hits?
|
||||||
|
return greenlock
|
||||||
|
._config({ servername: servername })
|
||||||
|
.then(function(site) {
|
||||||
|
if (!site) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hmm... this _should_ be impossible
|
||||||
|
if (!site.challenges || !site.challenges['http-01']) {
|
||||||
|
var copy = JSON.parse(JSON.stringify(site));
|
||||||
|
sanitizeCopiedConf(copy);
|
||||||
|
sanitizeCopiedConf(copy.store);
|
||||||
|
if (site.challenges) {
|
||||||
|
sanitizeCopiedConf(copy.challenges['http-01']);
|
||||||
|
sanitizeCopiedConf(copy.challenges['dns-01']);
|
||||||
|
sanitizeCopiedConf(copy.challenges['tls-alpn-01']);
|
||||||
|
}
|
||||||
|
console.warn('[Bug] Please report this error:');
|
||||||
|
console.warn(
|
||||||
|
'\terror: http-01 challenge requested, but not even a default http-01 config exists'
|
||||||
|
);
|
||||||
|
console.warn('\tservername:', JSON.stringify(servername));
|
||||||
|
console.warn('\tsite:', JSON.stringify(copy));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Greenlock._loadChallenge(site.challenges, 'http-01');
|
||||||
|
})
|
||||||
|
.then(function(plugin) {
|
||||||
|
if (!plugin) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return plugin
|
||||||
|
.get({
|
||||||
|
challenge: {
|
||||||
|
type: chall.type,
|
||||||
|
//hostname: chall.servername,
|
||||||
|
altname: chall.servername,
|
||||||
|
identifier: { value: chall.servername },
|
||||||
|
token: chall.token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(result) {
|
||||||
|
var keyAuth;
|
||||||
|
var keyAuthDigest;
|
||||||
|
if (result) {
|
||||||
|
// backwards compat that shouldn't be dropped
|
||||||
|
// because new v3 modules had to do this to be
|
||||||
|
// backwards compatible with Greenlock v2.7 at
|
||||||
|
// the time.
|
||||||
|
if (result.challenge) {
|
||||||
|
result = result.challenge;
|
||||||
|
}
|
||||||
|
keyAuth = result.keyAuthorization;
|
||||||
|
keyAuthDigest = result.keyAuthorizationDigest;
|
||||||
|
}
|
||||||
|
if (/dns/.test(chall.type)) {
|
||||||
|
return {
|
||||||
|
keyAuthorizationDigest: keyAuthDigest
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
keyAuthorization: keyAuth
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function sanitizeCopiedConf(copy) {
|
||||||
|
if (!copy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(copy).forEach(function(k) {
|
||||||
|
if (/(api|key|token)/i.test(k) && 'string' === typeof copy[k]) {
|
||||||
|
copy[k] = '**redacted**';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
194
greenlock.js
194
greenlock.js
|
@ -23,45 +23,114 @@ G.create = function(gconf) {
|
||||||
if (!gconf) {
|
if (!gconf) {
|
||||||
gconf = {};
|
gconf = {};
|
||||||
}
|
}
|
||||||
|
var manager;
|
||||||
|
|
||||||
if (!gconf.maintainerEmail) {
|
greenlock._create = function() {
|
||||||
throw E.NO_MAINTAINER('create');
|
if (!gconf.maintainerEmail) {
|
||||||
}
|
throw E.NO_MAINTAINER('create');
|
||||||
|
|
||||||
// TODO send welcome message with benefit info
|
|
||||||
U._validMx(gconf.maintainerEmail).catch(function() {
|
|
||||||
console.error(
|
|
||||||
'invalid maintainer contact info:',
|
|
||||||
gconf.maintainerEmail
|
|
||||||
);
|
|
||||||
|
|
||||||
// maybe move this to init and don't exit the process, just in case
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
if ('function' === typeof gconf.notify) {
|
|
||||||
gdefaults.notify = gconf.notify;
|
|
||||||
} else {
|
|
||||||
gdefaults.notify = _notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gconf.directoryUrl) {
|
|
||||||
gdefaults = gconf.directoryUrl;
|
|
||||||
if (gconf.staging) {
|
|
||||||
throw new Error('supply `directoryUrl` or `staging`, but not both');
|
|
||||||
}
|
}
|
||||||
} else if (gconf.staging) {
|
|
||||||
gdefaults.directoryUrl =
|
|
||||||
'https://acme-staging-v02.api.letsencrypt.org/directory';
|
|
||||||
} else {
|
|
||||||
gdefaults.directoryUrl =
|
|
||||||
'https://acme-v02.api.letsencrypt.org/directory';
|
|
||||||
}
|
|
||||||
console.info('ACME Directory URL:', gdefaults.directoryUrl);
|
|
||||||
|
|
||||||
var manager = normalizeManager(gconf);
|
// TODO send welcome message with benefit info
|
||||||
require('./manager-underlay.js').wrap(greenlock, manager, gconf);
|
U._validMx(gconf.maintainerEmail).catch(function() {
|
||||||
//console.log('debug greenlock.manager', Object.keys(greenlock.manager));
|
console.error(
|
||||||
|
'invalid maintainer contact info:',
|
||||||
|
gconf.maintainerEmail
|
||||||
|
);
|
||||||
|
|
||||||
|
// maybe move this to init and don't exit the process, just in case
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ('function' === typeof gconf.notify) {
|
||||||
|
gdefaults.notify = gconf.notify;
|
||||||
|
} else {
|
||||||
|
gdefaults.notify = _notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gconf.directoryUrl) {
|
||||||
|
gdefaults = gconf.directoryUrl;
|
||||||
|
if (gconf.staging) {
|
||||||
|
throw new Error(
|
||||||
|
'supply `directoryUrl` or `staging`, but not both'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (gconf.staging) {
|
||||||
|
gdefaults.directoryUrl =
|
||||||
|
'https://acme-staging-v02.api.letsencrypt.org/directory';
|
||||||
|
} else {
|
||||||
|
gdefaults.directoryUrl =
|
||||||
|
'https://acme-v02.api.letsencrypt.org/directory';
|
||||||
|
}
|
||||||
|
console.info('ACME Directory URL:', gdefaults.directoryUrl);
|
||||||
|
|
||||||
|
manager = normalizeManager(gconf);
|
||||||
|
|
||||||
|
// Wraps each of the following with appropriate error checking
|
||||||
|
// greenlock.manager.defaults
|
||||||
|
// greenlock.manager.add
|
||||||
|
// greenlock.manager.update
|
||||||
|
// greenlock.manager.remove
|
||||||
|
// greenlock.manager.find
|
||||||
|
require('./manager-underlay.js').wrap(greenlock, manager, gconf);
|
||||||
|
|
||||||
|
// Exports challenges.get for Greenlock Express HTTP-01,
|
||||||
|
// and whatever odd use case pops up, I suppose
|
||||||
|
// greenlock.challenges.get
|
||||||
|
require('./challenges-underlay.js').wrap(greenlock, manager, gconf);
|
||||||
|
|
||||||
|
greenlock._defaults = gdefaults;
|
||||||
|
greenlock._defaults.debug = gconf.debug;
|
||||||
|
|
||||||
|
// renew every 90-ish minutes (random for staggering)
|
||||||
|
// the weak setTimeout (unref) means that when run as a CLI process this
|
||||||
|
// will still finish as expected, and not wait on the timeout
|
||||||
|
(function renew() {
|
||||||
|
setTimeout(function() {
|
||||||
|
greenlock.renew({});
|
||||||
|
renew();
|
||||||
|
}, Math.PI * 30 * 60 * 1000).unref();
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
// The purpose of init is to make MCONF the source of truth
|
||||||
|
greenlock._init = function() {
|
||||||
|
var p;
|
||||||
|
greenlock._init = function() {
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (manager.init) {
|
||||||
|
// TODO punycode?
|
||||||
|
p = manager.init({
|
||||||
|
request: request
|
||||||
|
//punycode: require('punycode')
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
p = Promise.resolve();
|
||||||
|
}
|
||||||
|
p = p
|
||||||
|
.then(function() {
|
||||||
|
return manager.defaults().then(function(MCONF) {
|
||||||
|
mergeDefaults(MCONF, gconf);
|
||||||
|
if (true === MCONF.agreeToTerms) {
|
||||||
|
gdefaults.agreeToTerms = function(tos) {
|
||||||
|
return Promise.resolve(tos);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return manager.defaults(MCONF);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.error('Fatal error during greenlock init:');
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The goal here is to reduce boilerplate, such as error checking
|
||||||
|
// and duration parsing, that a manager must implement
|
||||||
|
greenlock.sites.add = greenlock.add = greenlock.manager.add;
|
||||||
|
|
||||||
greenlock.notify = greenlock._notify = function(ev, params) {
|
greenlock.notify = greenlock._notify = function(ev, params) {
|
||||||
var mng = greenlock.manager;
|
var mng = greenlock.manager;
|
||||||
|
@ -121,46 +190,6 @@ G.create = function(gconf) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The purpose of init is to make MCONF the source of truth
|
|
||||||
greenlock._init = function() {
|
|
||||||
var p;
|
|
||||||
greenlock._init = function() {
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (manager.init) {
|
|
||||||
// TODO punycode?
|
|
||||||
p = manager.init({
|
|
||||||
request: request
|
|
||||||
//punycode: require('punycode')
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
p = Promise.resolve();
|
|
||||||
}
|
|
||||||
p = p
|
|
||||||
.then(function() {
|
|
||||||
return manager.defaults().then(function(MCONF) {
|
|
||||||
mergeDefaults(MCONF, gconf);
|
|
||||||
if (true === MCONF.agreeToTerms) {
|
|
||||||
gdefaults.agreeToTerms = function(tos) {
|
|
||||||
return Promise.resolve(tos);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return manager.defaults(MCONF);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
console.error('Fatal error during greenlock init:');
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The goal here is to reduce boilerplate, such as error checking
|
|
||||||
// and duration parsing, that a manager must implement
|
|
||||||
greenlock.sites.add = greenlock.add = greenlock.manager.add;
|
|
||||||
|
|
||||||
// certs.get
|
// certs.get
|
||||||
greenlock.get = function(args) {
|
greenlock.get = function(args) {
|
||||||
return greenlock
|
return greenlock
|
||||||
|
@ -412,18 +441,7 @@ G.create = function(gconf) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
greenlock._defaults = gdefaults;
|
greenlock._create();
|
||||||
greenlock._defaults.debug = gconf.debug;
|
|
||||||
|
|
||||||
// renew every 90-ish minutes (random for staggering)
|
|
||||||
// the weak setTimeout (unref) means that when run as a CLI process this
|
|
||||||
// will still finish as expected, and not wait on the timeout
|
|
||||||
(function renew() {
|
|
||||||
setTimeout(function() {
|
|
||||||
greenlock.renew({});
|
|
||||||
renew();
|
|
||||||
}, Math.PI * 30 * 60 * 1000).unref();
|
|
||||||
})();
|
|
||||||
|
|
||||||
return greenlock;
|
return greenlock;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue