gutting python
This commit is contained in:
parent
c48de554c2
commit
3151ec3922
49
README.md
49
README.md
|
@ -263,52 +263,27 @@ and then make sure to set all of of the following to a directory that your user
|
||||||
|
|
||||||
* `webrootPath`
|
* `webrootPath`
|
||||||
* `configDir`
|
* `configDir`
|
||||||
* `workDir` (python backend only)
|
|
||||||
* `logsDir` (python backend only)
|
|
||||||
|
|
||||||
|
|
||||||
API
|
API
|
||||||
===
|
===
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
LetsEncrypt.create(backend, bkDefaults, handlers) // wraps a given "backend" (the python client)
|
LetsEncrypt.init(leConfig, handlers) // wraps a given
|
||||||
LetsEncrypt.stagingServer // string of staging server for testing
|
LetsEncrypt.create(backend, leConfig, handlers) // wraps a given "backend" (the python or node client)
|
||||||
|
LetsEncrypt.stagingServer // string of staging server for testing
|
||||||
|
|
||||||
le.middleware() // middleware for serving webrootPath to /.well-known/acme-challenge
|
le.middleware() // middleware for serving webrootPath to /.well-known/acme-challenge
|
||||||
le.sniCallback(hostname, function (err, tlsContext) {}) // uses fetch (below) and formats for https.SNICallback
|
le.sniCallback(hostname, function (err, tlsContext) {}) // uses fetch (below) and formats for https.SNICallback
|
||||||
le.register({ domains, email, agreeTos, ... }, cb) // registers or renews certs for a domain
|
le.register({ domains, email, agreeTos, ... }, cb) // registers or renews certs for a domain
|
||||||
le.fetch({domains, email, agreeTos, ... }, cb) // fetches certs from in-memory cache, occasionally refreshes from disk
|
le.fetch({domains, email, agreeTos, ... }, cb) // fetches certs from in-memory cache, occasionally refreshes from disk
|
||||||
le.validate(domains, cb) // do some sanity checks before attempting to register
|
le.validate(domains, cb) // do some sanity checks before attempting to register
|
||||||
le.registrationFailureCallback(err, args, certInfo, cb) // called when registration fails (not implemented yet)
|
le.registrationFailureCallback(err, args, certInfo, cb) // called when registration fails (not implemented yet)
|
||||||
```
|
```
|
||||||
|
|
||||||
### `LetsEncrypt.create(backend, bkDefaults, handlers)`
|
### `LetsEncrypt.create(backend, leConfig, handlers)`
|
||||||
|
|
||||||
#### backend
|
#### leConfig
|
||||||
|
|
||||||
Currently only `letsencrypt-python` is supported, but we plan to work on
|
|
||||||
native javascript support in February or so (when ECDSA keys are available).
|
|
||||||
|
|
||||||
If you'd like to help with that, see **how to write a backend** below and also
|
|
||||||
look at the wrapper `backend-python.js`.
|
|
||||||
|
|
||||||
**Example**:
|
|
||||||
```javascript
|
|
||||||
{ fetch: function (args, cb) {
|
|
||||||
// cb(err) when there is an actual error (db, fs, etc)
|
|
||||||
// cb(null, null) when the certificate was NOT available on disk
|
|
||||||
// cb(null, { cert: '<fullchain.pem>', key: '<privkey.pem>', renewedAt: 0, duration: 0 }) cert + meta
|
|
||||||
}
|
|
||||||
, register: function (args, setChallenge, cb) {
|
|
||||||
// setChallenge(hostnames, key, value, cb) when a challenge needs to be set
|
|
||||||
// cb(err) when there is an error
|
|
||||||
// cb(null, null) when the registration is successful, but fetch still needs to be called
|
|
||||||
// cb(null, cert /*see above*/) if registration can easily return the same as fetch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### bkDefaults
|
|
||||||
|
|
||||||
The arguments passed here (typically `webpathRoot`, `configDir`, etc) will be merged with
|
The arguments passed here (typically `webpathRoot`, `configDir`, etc) will be merged with
|
||||||
any `args` (typically `domains`, `email`, and `agreeTos`) and passed to the backend whenever
|
any `args` (typically `domains`, `email`, and `agreeTos`) and passed to the backend whenever
|
||||||
|
@ -326,7 +301,7 @@ Typically the backend wrapper will already merge any necessary backend-specific
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: `webrootPath` can be set as a default, semi-locally with `webrootPathTpl`, or per
|
Note: `webrootPath` can be set as a default, semi-locally with `webrootPathTpl`, or per
|
||||||
registration as `webrootPath` (which overwrites `defaults.webrootPath`).
|
registration as `webrootPath` (which overwrites `leConfig.webrootPath`).
|
||||||
|
|
||||||
#### handlers *optional*
|
#### handlers *optional*
|
||||||
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird');
|
|
||||||
var fs = PromiseA.promisifyAll(require('fs'));
|
|
||||||
|
|
||||||
module.exports.create = function (defaults, opts, extra) {
|
|
||||||
// v1.0.0 backwards compat
|
|
||||||
if (3 === arguments.length) {
|
|
||||||
opts.pythonClientPath = defaults;
|
|
||||||
defaults = opts;
|
|
||||||
opts = extra;
|
|
||||||
}
|
|
||||||
else if (2 !== arguments.length) {
|
|
||||||
throw new Error("Instead of creating the python backend yourself, just pass it to LE. See the README.md");
|
|
||||||
}
|
|
||||||
|
|
||||||
defaults.webroot = true;
|
|
||||||
defaults.renewByDefault = true;
|
|
||||||
defaults.text = true;
|
|
||||||
|
|
||||||
var leBinPath = defaults.pythonClientPath;
|
|
||||||
var LEP = require('letsencrypt-python');
|
|
||||||
var lep = PromiseA.promisifyAll(LEP.create(leBinPath, opts));
|
|
||||||
var wrapped = {
|
|
||||||
registerAsync: function (args) {
|
|
||||||
return lep.registerAsync('certonly', args);
|
|
||||||
}
|
|
||||||
, fetchAsync: function (args) {
|
|
||||||
require('./common').fetchFromDisk(args, defaults);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return wrapped;
|
|
||||||
};
|
|
|
@ -11,7 +11,7 @@ config.le.server = LE.stagingServer;
|
||||||
//
|
//
|
||||||
// Manual Registration
|
// Manual Registration
|
||||||
//
|
//
|
||||||
var le = LE.create(config.backend, config.le);
|
var le = LE.create(config.le);
|
||||||
le.register({
|
le.register({
|
||||||
agreeTos: true
|
agreeTos: true
|
||||||
, domains: ['example.com'] // CHANGE TO YOUR DOMAIN
|
, domains: ['example.com'] // CHANGE TO YOUR DOMAIN
|
||||||
|
|
|
@ -32,9 +32,7 @@ var bkDefaults = {
|
||||||
, pythonClientPath: require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt'
|
, pythonClientPath: require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt'
|
||||||
};
|
};
|
||||||
|
|
||||||
var LEP = require('../backends/python');
|
var le = LE.create(bkDefaults, {
|
||||||
|
|
||||||
var le = LE.create(LEP, bkDefaults, {
|
|
||||||
/*
|
/*
|
||||||
setChallenge: function (hostnames, key, value, cb) {
|
setChallenge: function (hostnames, key, value, cb) {
|
||||||
// the python backend needs fs.watch implemented
|
// the python backend needs fs.watch implemented
|
||||||
|
|
|
@ -26,7 +26,4 @@ var config = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//config.backend = require('letsencrypt/backends/python').create(binpath, config.le);
|
|
||||||
config.backend = require('../backends/python');
|
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|
|
@ -7,7 +7,7 @@ var config = require('./config-minimal');
|
||||||
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
||||||
config.le.server = LE.stagingServer;
|
config.le.server = LE.stagingServer;
|
||||||
|
|
||||||
var le = LE.create(config.backend, config.le, {
|
var le = LE.create(config.le, {
|
||||||
sniRegisterCallback: function (args, expiredCert, cb) {
|
sniRegisterCallback: function (args, expiredCert, cb) {
|
||||||
// In theory you should never get an expired certificate because
|
// In theory you should never get an expired certificate because
|
||||||
// the certificates automatically renew in the background starting
|
// the certificates automatically renew in the background starting
|
||||||
|
|
|
@ -24,15 +24,8 @@ var bkDefaults = {
|
||||||
, privkeyTpl: '/live/:hostname/privkey.pem'
|
, privkeyTpl: '/live/:hostname/privkey.pem'
|
||||||
, configDir: path.join(__dirname, '..', 'tests', 'letsencrypt.config')
|
, configDir: path.join(__dirname, '..', 'tests', 'letsencrypt.config')
|
||||||
, server: LE.stagingServer
|
, server: LE.stagingServer
|
||||||
|
|
||||||
// python-specific
|
|
||||||
, logsDir: path.join(__dirname, '..', 'tests', 'letsencrypt.logs')
|
|
||||||
, workDir: path.join(__dirname, '..', 'tests', 'letsencrypt.work')
|
|
||||||
, pythonClientPath: require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var LEP = require('../backends/python');
|
|
||||||
|
|
||||||
var le = LE.create(LEP, bkDefaults, {
|
var le = LE.create(LEP, bkDefaults, {
|
||||||
sniRegisterCallback: function (args, certInfo, cb) {
|
sniRegisterCallback: function (args, certInfo, cb) {
|
||||||
var allowedDomains = conf.domains; // require('../tests/config').allowedDomains;
|
var allowedDomains = conf.domains; // require('../tests/config').allowedDomains;
|
||||||
|
|
90
index.js
90
index.js
|
@ -6,14 +6,18 @@ var PromiseA = require('bluebird');
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
var tls = require('tls');
|
var tls = require('tls');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var leCore = require('./backends/letiny-core');
|
||||||
|
|
||||||
var LE = module.exports;
|
var LE = module.exports;
|
||||||
|
LE.productionServerUrl = leCore.productionServerUrl;
|
||||||
|
LE.stagingServer = leCore.stagingServerUrl;
|
||||||
|
LE.configDir = leCore.configDir;
|
||||||
|
LE.acmeChallengPrefix = leCore.acmeChallengPrefix;
|
||||||
|
LE.knownEndpoints = leCore.knownEndpoints;
|
||||||
|
|
||||||
LE.liveServer = "https://acme-v01.api.letsencrypt.org/directory";
|
// backwards compat
|
||||||
LE.stagingServer = "https://acme-staging.api.letsencrypt.org/directory";
|
LE.liveServer = leCore.productionServerUrl;
|
||||||
LE.configDir = "/etc/letsencrypt/";
|
LE.knownUrls = leCore.knownEndpoints;
|
||||||
LE.logsDir = "/var/log/letsencrypt/";
|
|
||||||
LE.workDir = "/var/lib/letsencrypt/";
|
|
||||||
|
|
||||||
LE.merge = function merge(defaults, args) {
|
LE.merge = function merge(defaults, args) {
|
||||||
var copy = {};
|
var copy = {};
|
||||||
|
@ -28,7 +32,48 @@ LE.merge = function merge(defaults, args) {
|
||||||
return copy;
|
return copy;
|
||||||
};
|
};
|
||||||
|
|
||||||
LE.create = function (backend, defaults, handlers) {
|
LE.cacheCertInfo = function (args, certInfo, ipc, handlers) {
|
||||||
|
// TODO IPC via process and worker to guarantee no races
|
||||||
|
// rather than just "really good odds"
|
||||||
|
|
||||||
|
var hostname = args.domains[0];
|
||||||
|
var now = Date.now();
|
||||||
|
|
||||||
|
// Stagger randomly by plus 0% to 25% to prevent all caches expiring at once
|
||||||
|
var rnd1 = (crypto.randomBytes(1)[0] / 255);
|
||||||
|
var memorizeFor = Math.floor(handlers.memorizeFor + ((handlers.memorizeFor / 4) * rnd1));
|
||||||
|
// Stagger randomly to renew between n and 2n days before renewal is due
|
||||||
|
// this *greatly* reduces the risk of multiple cluster processes renewing the same domain at once
|
||||||
|
var rnd2 = (crypto.randomBytes(1)[0] / 255);
|
||||||
|
var bestIfUsedBy = certInfo.expiresAt - (handlers.renewWithin + Math.floor(handlers.renewWithin * rnd2));
|
||||||
|
// Stagger randomly by plus 0 to 5 min to reduce risk of multiple cluster processes
|
||||||
|
// renewing at once on boot when the certs have expired
|
||||||
|
var rnd3 = (crypto.randomBytes(1)[0] / 255);
|
||||||
|
var renewTimeout = Math.floor((5 * 60 * 1000) * rnd3);
|
||||||
|
|
||||||
|
certInfo.context = tls.createSecureContext({
|
||||||
|
key: certInfo.key
|
||||||
|
, cert: certInfo.cert
|
||||||
|
//, ciphers // node's defaults are great
|
||||||
|
});
|
||||||
|
certInfo.loadedAt = now;
|
||||||
|
certInfo.memorizeFor = memorizeFor;
|
||||||
|
certInfo.bestIfUsedBy = bestIfUsedBy;
|
||||||
|
certInfo.renewTimeout = renewTimeout;
|
||||||
|
|
||||||
|
ipc[hostname] = certInfo;
|
||||||
|
return ipc[hostname];
|
||||||
|
};
|
||||||
|
|
||||||
|
// backend, defaults, handlers
|
||||||
|
LE.create = function (defaults, handlers, backend) {
|
||||||
|
var d, b, h;
|
||||||
|
// backwards compat for <= v1.0.2
|
||||||
|
if (defaults.registerAsync || defaults.create) {
|
||||||
|
b = defaults; d = handlers; h = backend;
|
||||||
|
defaults = d; handlers = h; backend = b;
|
||||||
|
}
|
||||||
|
if (!backend) { backend = require('./lib/letiny-core'); }
|
||||||
if (!handlers) { handlers = {}; }
|
if (!handlers) { handlers = {}; }
|
||||||
if (!handlers.lifetime) { handlers.lifetime = 90 * 24 * 60 * 60 * 1000; }
|
if (!handlers.lifetime) { handlers.lifetime = 90 * 24 * 60 * 60 * 1000; }
|
||||||
if (!handlers.renewWithin) { handlers.renewWithin = 3 * 24 * 60 * 60 * 1000; }
|
if (!handlers.renewWithin) { handlers.renewWithin = 3 * 24 * 60 * 60 * 1000; }
|
||||||
|
@ -324,36 +369,3 @@ LE.create = function (backend, defaults, handlers) {
|
||||||
|
|
||||||
return le;
|
return le;
|
||||||
};
|
};
|
||||||
|
|
||||||
LE.cacheCertInfo = function (args, certInfo, ipc, handlers) {
|
|
||||||
// TODO IPC via process and worker to guarantee no races
|
|
||||||
// rather than just "really good odds"
|
|
||||||
|
|
||||||
var hostname = args.domains[0];
|
|
||||||
var now = Date.now();
|
|
||||||
|
|
||||||
// Stagger randomly by plus 0% to 25% to prevent all caches expiring at once
|
|
||||||
var rnd1 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var memorizeFor = Math.floor(handlers.memorizeFor + ((handlers.memorizeFor / 4) * rnd1));
|
|
||||||
// Stagger randomly to renew between n and 2n days before renewal is due
|
|
||||||
// this *greatly* reduces the risk of multiple cluster processes renewing the same domain at once
|
|
||||||
var rnd2 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var bestIfUsedBy = certInfo.expiresAt - (handlers.renewWithin + Math.floor(handlers.renewWithin * rnd2));
|
|
||||||
// Stagger randomly by plus 0 to 5 min to reduce risk of multiple cluster processes
|
|
||||||
// renewing at once on boot when the certs have expired
|
|
||||||
var rnd3 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var renewTimeout = Math.floor((5 * 60 * 1000) * rnd3);
|
|
||||||
|
|
||||||
certInfo.context = tls.createSecureContext({
|
|
||||||
key: certInfo.key
|
|
||||||
, cert: certInfo.cert
|
|
||||||
//, ciphers // node's defaults are great
|
|
||||||
});
|
|
||||||
certInfo.loadedAt = now;
|
|
||||||
certInfo.memorizeFor = memorizeFor;
|
|
||||||
certInfo.bestIfUsedBy = bestIfUsedBy;
|
|
||||||
certInfo.renewTimeout = renewTimeout;
|
|
||||||
|
|
||||||
ipc[hostname] = certInfo;
|
|
||||||
return ipc[hostname];
|
|
||||||
};
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ var fs = PromiseA.promisifyAll(require('fs'));
|
||||||
var requestAsync = PromiseA.promisify(require('request'));
|
var requestAsync = PromiseA.promisify(require('request'));
|
||||||
|
|
||||||
var LE = require('../');
|
var LE = require('../');
|
||||||
var knownUrls = ['new-authz', 'new-cert', 'new-reg', 'revoke-cert'];
|
var LeCore = PromiseA.promisifyAll(require('letiny-core'));
|
||||||
var ucrypto = PromiseA.promisifyAll(require('../lib/crypto-utils-ursa'));
|
var ucrypto = PromiseA.promisifyAll(LeCore.leCrypto);
|
||||||
|
|
||||||
//var fcrypto = PromiseA.promisifyAll(require('../lib/crypto-utils-forge'));
|
//var fcrypto = PromiseA.promisifyAll(require('../lib/crypto-utils-forge'));
|
||||||
var lef = PromiseA.promisifyAll(require('letsencrypt-forge'));
|
|
||||||
var fetchFromConfigLiveDir = require('./common').fetchFromDisk;
|
var fetchFromConfigLiveDir = require('./common').fetchFromDisk;
|
||||||
|
|
||||||
var ipc = {}; // in-process cache
|
var ipc = {}; // in-process cache
|
||||||
|
@ -22,30 +22,7 @@ function getAcmeUrls(args) {
|
||||||
return PromiseA.resolve(ipc.acmeUrls);
|
return PromiseA.resolve(ipc.acmeUrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestAsync({
|
return LeCore.getAcmeUrlsAsync(args.server).then(function (data) {
|
||||||
url: args.server
|
|
||||||
}).then(function (resp) {
|
|
||||||
var data = resp.body;
|
|
||||||
|
|
||||||
if ('string' === typeof data) {
|
|
||||||
try {
|
|
||||||
data = JSON.parse(data);
|
|
||||||
} catch(e) {
|
|
||||||
return PromiseA.reject(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (4 !== Object.keys(data).length) {
|
|
||||||
console.warn("This Let's Encrypt / ACME server has been updated with urls that this client doesn't understand");
|
|
||||||
console.warn(data);
|
|
||||||
}
|
|
||||||
if (!knownUrls.every(function (url) {
|
|
||||||
return data[url];
|
|
||||||
})) {
|
|
||||||
console.warn("This Let's Encrypt / ACME server is missing urls that this client may need.");
|
|
||||||
console.warn(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc.acmeUrlsUpdatedAt = Date.now();
|
ipc.acmeUrlsUpdatedAt = Date.now();
|
||||||
ipc.acmeUrls = {
|
ipc.acmeUrls = {
|
||||||
newAuthz: data['new-authz']
|
newAuthz: data['new-authz']
|
||||||
|
@ -68,7 +45,7 @@ function createAccount(args, handlers) {
|
||||||
return ucrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (pems) {
|
return ucrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (pems) {
|
||||||
/* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } */
|
/* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } */
|
||||||
|
|
||||||
return lef.registerNewAccountAsync({
|
return LeCore.registerNewAccountAsync({
|
||||||
email: args.email
|
email: args.email
|
||||||
, newReg: args._acmeUrls.newReg
|
, newReg: args._acmeUrls.newReg
|
||||||
, debug: args.debug || handlers.debug
|
, debug: args.debug || handlers.debug
|
||||||
|
@ -79,17 +56,6 @@ function createAccount(args, handlers) {
|
||||||
}
|
}
|
||||||
, accountPrivateKeyPem: pems.privateKeyPem
|
, accountPrivateKeyPem: pems.privateKeyPem
|
||||||
}).then(function (body) {
|
}).then(function (body) {
|
||||||
if (body instanceof Buffer) {
|
|
||||||
body = body.toString('utf8');
|
|
||||||
}
|
|
||||||
if ('string' === typeof body) {
|
|
||||||
try {
|
|
||||||
body = JSON.parse(body);
|
|
||||||
} catch(e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var accountDir = path.join(args.accountsDir, pems.publicKeyMd5);
|
var accountDir = path.join(args.accountsDir, pems.publicKeyMd5);
|
||||||
|
|
||||||
return mkdirpAsync(accountDir).then(function () {
|
return mkdirpAsync(accountDir).then(function () {
|
||||||
|
@ -100,21 +66,20 @@ function createAccount(args, handlers) {
|
||||||
, creation_dt: isoDate
|
, creation_dt: isoDate
|
||||||
};
|
};
|
||||||
|
|
||||||
// meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"}
|
|
||||||
// private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" }
|
|
||||||
// regr.json:
|
|
||||||
/*
|
|
||||||
{ body:
|
|
||||||
{ contact: [ 'mailto:coolaj86@gmail.com' ],
|
|
||||||
agreement: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf',
|
|
||||||
key: { e: 'AQAB', kty: 'RSA', n: '...' } },
|
|
||||||
uri: 'https://acme-v01.api.letsencrypt.org/acme/reg/71272',
|
|
||||||
new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz',
|
|
||||||
terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' }
|
|
||||||
*/
|
|
||||||
return PromiseA.all([
|
return PromiseA.all([
|
||||||
|
// meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"}
|
||||||
fs.writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8')
|
fs.writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8')
|
||||||
|
// private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" }
|
||||||
, fs.writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(pems.privateKeyJwk), 'utf8')
|
, fs.writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(pems.privateKeyJwk), 'utf8')
|
||||||
|
// regr.json:
|
||||||
|
/*
|
||||||
|
{ body: { contact: [ 'mailto:coolaj86@gmail.com' ],
|
||||||
|
agreement: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf',
|
||||||
|
key: { e: 'AQAB', kty: 'RSA', n: '...' } },
|
||||||
|
uri: 'https://acme-v01.api.letsencrypt.org/acme/reg/71272',
|
||||||
|
new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz',
|
||||||
|
terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' }
|
||||||
|
*/
|
||||||
, fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify({ body: body }), 'utf8')
|
, fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify({ body: body }), 'utf8')
|
||||||
]).then(function () {
|
]).then(function () {
|
||||||
return pems;
|
return pems;
|
||||||
|
@ -180,15 +145,21 @@ function getCertificateAsync(account, args, defaults, handlers) {
|
||||||
var pyconf = PromiseA.promisifyAll(require('pyconf'));
|
var pyconf = PromiseA.promisifyAll(require('pyconf'));
|
||||||
|
|
||||||
return ucrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (domain) {
|
return ucrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (domain) {
|
||||||
return lef.getCertificateAsync({
|
return lef.getCertificateAsyncAsync({
|
||||||
domains: args.domains
|
newAuthorizationUrl: args._acmeUrls.newAuthz
|
||||||
|
, newCertificateUrl: args._acmeUrls.newCert
|
||||||
|
|
||||||
, accountPrivateKeyPem: account.privateKeyPem
|
, accountPrivateKeyPem: account.privateKeyPem
|
||||||
, domainPrivateKeyPem: domain.privateKeyPem
|
, domainPrivateKeyPem: domain.privateKeyPem
|
||||||
|
, domains: args.domains
|
||||||
|
|
||||||
|
/*
|
||||||
, getChallenge: function (domain, key, done) {
|
, getChallenge: function (domain, key, done) {
|
||||||
args.domains = [domain];
|
args.domains = [domain];
|
||||||
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
||||||
handlers.getChallenge(args, key, done);
|
handlers.getChallenge(args, key, done);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
, setChallenge: function (domain, key, value, done) {
|
, setChallenge: function (domain, key, value, done) {
|
||||||
args.domains = [domain];
|
args.domains = [domain];
|
||||||
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
||||||
|
@ -199,9 +170,27 @@ function getCertificateAsync(account, args, defaults, handlers) {
|
||||||
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
args.webrootPath = args.webrootPath || defaults.webrootPath;
|
||||||
handlers.removeChallenge(args, key, done);
|
handlers.removeChallenge(args, key, done);
|
||||||
}
|
}
|
||||||
, newAuthorizationUrl: args._acmeUrls.newAuthz
|
|
||||||
, newCertificateUrl: args._acmeUrls.newCert
|
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
|
// TODO write pems={ca,cert,key} to disk
|
||||||
|
var liveDir = path.join(args.configDir, 'live', args.domains[0]);
|
||||||
|
var certPath = path.join(liveDir, 'cert.pem');
|
||||||
|
var fullchainPath = path.join(liveDir, 'fullchain.pem');
|
||||||
|
var chainPath = path.join(liveDir, 'chain.pem');
|
||||||
|
var privkeyPath = path.join(liveDir, 'privkey.pem');
|
||||||
|
|
||||||
|
result.fullchain = result.cert + '\n' + result.ca;
|
||||||
|
|
||||||
|
// TODO write to archive first, then write to live
|
||||||
|
return mkdirpAsync(liveDir).then(function () {
|
||||||
|
return PromisA.all([
|
||||||
|
sfs.writeFileAsync(certPath, result.cert, 'ascii')
|
||||||
|
, sfs.writeFileAsync(chainPath, result.chain, 'ascii')
|
||||||
|
, sfs.writeFileAsync(fullchainPath, result.fullchain, 'ascii')
|
||||||
|
, sfs.writeFileAsync(privkeyPath, result.key, 'ascii')
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(liveDir);
|
||||||
console.log(result);
|
console.log(result);
|
||||||
throw new Error("IMPLEMENTATION NOT COMPLETE");
|
throw new Error("IMPLEMENTATION NOT COMPLETE");
|
||||||
});
|
});
|
|
@ -34,16 +34,13 @@
|
||||||
"localhost.daplie.com-certificates": "^1.1.2"
|
"localhost.daplie.com-certificates": "^1.1.2"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"letsencrypt-python": "^1.0.3",
|
|
||||||
"letsencrypt-forge": "file:letsencrypt-forge",
|
|
||||||
"letsencrypt-ursa": "file:letsencrypt-ursa",
|
|
||||||
"node-forge": "^0.6.38",
|
|
||||||
"letiny": "0.0.4-beta",
|
|
||||||
"ursa": "^0.9.1"
|
"ursa": "^0.9.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"node-forge": "^0.6.38",
|
||||||
"bluebird": "^3.0.6",
|
"bluebird": "^3.0.6",
|
||||||
"homedir": "^0.6.0",
|
"homedir": "^0.6.0",
|
||||||
|
"letiny-core": "^1.0.1",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"pyconf": "^1.0.0",
|
"pyconf": "^1.0.0",
|
||||||
"request": "^2.67.0",
|
"request": "^2.67.0",
|
||||||
|
|
Loading…
Reference in New Issue