Compare commits

...

35 Commits

Author SHA1 Message Date
AJ ONeal
03fdbe157a
chore(release): bump to v2.2.4 2024-05-13 13:03:14 -06:00
AJ ONeal
0393b1ae3a
chore: add 'npm run bump' 2024-05-13 13:03:08 -06:00
AJ ONeal
16637c4f67
fix: skip (instead of fail) when pems.bundle is unavailable 2024-05-13 13:03:08 -06:00
c834d1603d v2.2.3: node v6 promisify fix, eliminate external deps 2019-04-16 00:29:18 -06:00
a19685734d v2.2.2: Deprecated 2019-04-04 23:02:41 -06:00
bba58351e4 v2.2.1: PR#3, improve logging 2018-11-06 00:58:43 -07:00
fa845c4e18 Merge branch 'master' of ceecko/le-store-certbot.js into master 2018-11-06 07:57:46 +00:00
ceecko
791cb03910 Consistent debug logging 2018-09-16 20:22:32 +00:00
d7313d932a v2.2.0: add bundle.pem and bugfix windows - nix symlinks and use full files 2018-07-11 22:44:23 -06:00
cf9890e387 v2.1.8 bugfix missing functions 2018-07-05 09:40:41 -06:00
dc1920e68a Merge branch 'fixes' of pkaske/le-store-certbot.js into master 2018-07-05 15:38:11 +00:00
Peter Kaske
7b4089ecb9 Fix some missing function errors. 2018-07-05 08:48:52 +02:00
89fa3d688c v2.1.7 2018-07-04 01:28:39 -06:00
ddd9faf76a v2.1.6 2018-07-04 01:24:56 -06:00
13ff4bd4dc v2.1.5 2018-07-04 01:00:34 -06:00
0db09589fd fix linebreak issue with certs (for the brazillionth time) 2018-07-04 00:59:48 -06:00
1db1d10adc use generic promises 2018-07-04 00:59:11 -06:00
9cf2126ddd v2.1.3 2018-06-14 20:04:57 -06:00
e418a56b68 use proper tmpdir, not homedir 2018-06-14 20:04:26 -06:00
AJ ONeal
cab8ae510f v2.1.2 2018-05-21 11:14:16 -06:00
80a93b467a Merge branch 'new-authzr-uri' of mrstegeman/le-store-certbot.js into master 2018-05-21 17:13:38 +00:00
Michael Stegeman
87853bc37b
Add missing field to regr.json.
When using generated configs with older certbot versions,
i.e. <0.11, certbot bombs out without new_authzr_uri.
2018-05-21 07:36:17 -06:00
04f93070dc Merge branch 'must-staple' of mrstegeman/le-store-certbot.js into master 2018-05-17 00:05:28 +00:00
Michael Stegeman
1db8aa20a6
Disable OCSP stapling by default. 2018-05-15 09:02:44 -06:00
AJ ONeal
7202706545 remove work dir, not needed 2018-05-12 22:37:18 -06:00
AJ ONeal
0a370238e5 remove work dir, not needed 2018-05-12 22:30:45 -06:00
AJ ONeal
48bcd7a103 update default tmp dirs 2018-05-12 22:03:06 -06:00
AJ ONeal
0990fd24fc v2.1.0 2018-05-12 18:49:48 -06:00
AJ ONeal
c81d965c71 v2.0.5 2018-05-12 18:35:28 -06:00
AJ ONeal
e064df8a38 v2.0.3 2016-08-09 20:08:03 -06:00
AJ ONeal
b25821ed8a overwrite falsey values 2016-08-09 22:07:55 -04:00
AJ ONeal
102ffdbe5f v2.0.2 2016-08-09 19:28:52 -06:00
AJ ONeal
c86cbd5edf fix #1 return null when keypath cannot be derived 2016-08-09 19:28:47 -06:00
AJ ONeal
9d4ad0b734 v2.0.1 2016-08-09 14:07:22 -06:00
AJ ONeal
996148b141 add missing deps 2016-08-09 14:07:19 -06:00
5 changed files with 196 additions and 60 deletions

View File

@ -1,7 +1,39 @@
le-store-certbot # Deprecated
================
The "certbot" storage strategy for node-letsencrypt. `le-store-certbot` has been replaced with [`le-store-fs`](https://git.coolaj86.com/coolaj86/le-store-fs.js).
The new storage strategy **keeps file system compatibility**, but **drops support** for Python config files.
Unless you're running `certbot` and Greenlock side-by-side, or interchangeably, you switch to `le-store-fs`.
## Migrating to `le-store-fs`
It's **painless** and all of your existing certificates will be **preserved**
(assuming you use the same `configDir` as before).
```js
Greenlock.create({
// Leave configDir as it, if you've been setting it yourself.
// Otherwise you should explicitly set it to the previous default:
configDir: '~/letsencrypt/etc'
// le-store-fs takes the same options as le-store-certbot,
// but ignores some of the ones that aren't important.
, store: require('le-store-fs').create({})
...
})
```
## Alternatives
* Search npm for ["le-store-"](https://www.npmjs.com/search?q=le-store-) to find many alternatives.
# le-store-certbot
The "certbot" storage strategy for
[Greenlock.js](https://git.coolaj86.com/coolaj86/le-store-certbot.js).
This le storage strategy aims to maintain compatibility with the This le storage strategy aims to maintain compatibility with the
configuration files and file structure of the official certbot client. configuration files and file structure of the official certbot client.
@ -17,24 +49,27 @@ npm install --save le-store-certbot@2.x
```bash ```bash
var leStore = require('le-store-certbot').create({ var leStore = require('le-store-certbot').create({
configDir: require('homedir')() + '/letsencrypt/etc' // or /etc/letsencrypt or wherever configDir: require('homedir')() + '/acme/etc' // or /etc/acme or wherever
, privkeyPath: ':configDir/live/:hostname/privkey.pem' // , privkeyPath: ':configDir/live/:hostname/privkey.pem' //
, fullchainPath: ':configDir/live/:hostname/fullchain.pem' // Note: both that :configDir and :hostname , fullchainPath: ':configDir/live/:hostname/fullchain.pem' // Note: both that :configDir and :hostname
, certPath: ':configDir/live/:hostname/cert.pem' // will be templated as expected by , certPath: ':configDir/live/:hostname/cert.pem' // will be templated as expected by
, chainPath: ':configDir/live/:hostname/chain.pem' // node-letsencrypt , chainPath: ':configDir/live/:hostname/chain.pem' // greenlock.js
, workDir: require('homedir')() + '/letsencrypt/var/lib' , logsDir: require('homedir')() + '/tmp/acme/log'
, logsDir: require('homedir')() + '/letsencrypt/var/log'
, webrootPath: '~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge' , webrootPath: '~/acme/srv/www/:hostname/.well-known/acme-challenge'
, debug: false , debug: false
}); });
```
var LE = require('letsencrypt'); The store module can be used globally with Greenlock like this:
LE.create({ ```
server: LE.stagingServerUrl // Change to LE.productionServerUrl in production var Greenlock = require('greenlock');
Greenlock.create({
...
, store: leStore , store: leStore
}); });
``` ```
@ -43,7 +78,7 @@ Example File Structure
---------------------- ----------------------
``` ```
~/letsencrypt/ ~/acme/
└── etc └── etc
├── accounts ├── accounts
│   └── acme-staging.api.letsencrypt.org │   └── acme-staging.api.letsencrypt.org
@ -53,19 +88,19 @@ Example File Structure
│   ├── private_key.json │   ├── private_key.json
│   └── regr.json │   └── regr.json
├── archive ├── archive
│   └── example.daplie.me │   └── example.com
│   ├── cert0.pem │   ├── cert0.pem
│   ├── chain0.pem │   ├── chain0.pem
│   ├── fullchain0.pem │   ├── fullchain0.pem
│   └── privkey0.pem │   └── privkey0.pem
├── live ├── live
│   └── example.daplie.me │   └── example.com
│   ├── cert.pem │   ├── cert.pem
│   ├── chain.pem │   ├── chain.pem
│   ├── fullchain.pem │   ├── fullchain.pem
│   ├── privkey.pem │   ├── privkey.pem
│   └── privkey.pem.bak │   └── privkey.pem.bak
└── renewal └── renewal
├── example.daplie.me.conf ├── example.com.conf
└── example.daplie.me.conf.bak └── example.com.conf.bak
``` ```

123
index.js
View File

@ -1,10 +1,32 @@
'use strict'; 'use strict';
/* global Promise */
var PromiseA = require('bluebird'); var PromiseA;
var mkdirpAsync = PromiseA.promisify(require('mkdirp')); try {
PromiseA = require('bluebird');
} catch(e) {
PromiseA = Promise;
}
var util = require('util');
if (!util.promisify) {
util.promisify = PromiseA.promisify;
}
function promisifyAll(obj) {
var aobj = {};
Object.keys(obj).forEach(function (key) {
aobj[key + 'Async'] = util.promisify(obj[key]);
});
return aobj;
}
var mkdirpAsync = util.promisify(require('@root/mkdirp'));
var path = require('path'); var path = require('path');
var fs = PromiseA.promisifyAll(require('fs')); var fs = require('fs');
var readFileAsync = util.promisify(fs.readFile);
var readdirAsync = util.promisify(fs.readdir);
var writeFileAsync = util.promisify(fs.writeFile);
var statAsync = util.promisify(fs.stat);
var sfs = require('safe-replace'); var sfs = require('safe-replace');
var os = require('os');
function log(debug) { function log(debug) {
if (debug) { if (debug) {
@ -19,7 +41,7 @@ function writeRenewalConfig(args) {
var pyobj = args.pyobj; var pyobj = args.pyobj;
pyobj.checkpoints = parseInt(pyobj.checkpoints, 10) || 0; pyobj.checkpoints = parseInt(pyobj.checkpoints, 10) || 0;
var pyconf = PromiseA.promisifyAll(require('pyconf')); var pyconf = promisifyAll(require('pyconf'));
var liveDir = args.liveDir || path.join(args.configDir, 'live', args.domains[0]); var liveDir = args.liveDir || path.join(args.configDir, 'live', args.domains[0]);
@ -99,10 +121,12 @@ function pyToJson(pyobj) {
return jsobj; return jsobj;
} }
var crypto = require('crypto');
var rnd = crypto.randomBytes(8).toString('hex');
var defaults = { var defaults = {
configDir: [ '~', 'letsencrypt', 'etc' ].join(path.sep) // /etc/letsencrypt/ configDir: [ os.homedir(), 'letsencrypt', 'etc' ].join(path.sep) // /etc/letsencrypt/
, logsDir: [ '~', 'letsencrypt', 'var', 'log' ].join(path.sep) // /var/log/letsencrypt/ , logsDir: [ os.tmpdir(), 'acme-' + rnd, 'log' ].join(path.sep) // /var/log/letsencrypt/
, workDir: [ '~', 'letsencrypt', 'var', 'lib' ].join(path.sep) // /var/lib/letsencrypt/ , webrootPath: [ os.tmpdir(), 'acme-' + rnd, 'acme-challenge' ].join(path.sep)
, accountsDir: [ ':configDir', 'accounts', ':serverDir' ].join(path.sep) , accountsDir: [ ':configDir', 'accounts', ':serverDir' ].join(path.sep)
, renewalPath: [ ':configDir', 'renewal', ':hostname.conf' ].join(path.sep) , renewalPath: [ ':configDir', 'renewal', ':hostname.conf' ].join(path.sep)
@ -111,13 +135,13 @@ var defaults = {
return (copy.server || '').replace('https://', '').replace(/(\/)$/, '').replace(/\//g, path.sep); return (copy.server || '').replace('https://', '').replace(/(\/)$/, '').replace(/\//g, path.sep);
} }
, privkeyPath: [ ':configDir', 'live', ':hostname', 'privkey.pem' ].join(path.sep) , privkeyPath: ':configDir/live/:hostname/privkey.pem'.split(/\//).join(path.sep)
, fullchainPath: [ ':configDir', 'live', ':hostname', 'fullchain.pem' ].join(path.sep) , fullchainPath: [ ':configDir', 'live', ':hostname', 'fullchain.pem' ].join(path.sep)
, certPath: [ ':configDir', 'live', ':hostname', 'cert.pem' ].join(path.sep) , certPath: [ ':configDir', 'live', ':hostname', 'cert.pem' ].join(path.sep)
, chainPath: [ ':configDir', 'live', ':hostname', 'chain.pem' ].join(path.sep) , chainPath: [ ':configDir', 'live', ':hostname', 'chain.pem' ].join(path.sep)
, bundlePath: [ ':configDir', 'live', ':hostname', 'bundle.pem' ].join(path.sep)
, rsaKeySize: 2048 , rsaKeySize: 2048
, webrootPath: [ ':workDir', 'acme-challenge' ].join(path.sep)
}; };
module.exports.create = function (configs) { module.exports.create = function (configs) {
@ -132,8 +156,9 @@ module.exports.create = function (configs) {
if (!configs.domainKeyPath) { if (!configs.domainKeyPath) {
configs.domainKeyPath = configs.privkeyPath || defaults.privkeyPath; configs.domainKeyPath = configs.privkeyPath || defaults.privkeyPath;
} }
Object.keys(defaults).forEach(function (key) { Object.keys(defaults).forEach(function (key) {
if (!(key in configs)) { if (!configs[key]) {
configs[key] = defaults[key]; configs[key] = defaults[key];
} }
}); });
@ -144,7 +169,10 @@ module.exports.create = function (configs) {
, keypairs: { , keypairs: {
checkAsync: function (keypath, format) { checkAsync: function (keypath, format) {
return fs.readFileAsync(keypath, 'ascii').then(function (key) { if (!keypath) {
return null;
}
return readFileAsync(keypath, 'ascii').then(function (key) {
if ('jwk' === format) { if ('jwk' === format) {
return { privateKeyJwk: JSON.parse(key) }; return { privateKeyJwk: JSON.parse(key) };
} }
@ -170,7 +198,7 @@ module.exports.create = function (configs) {
key = keypair.privateKeyPem; key = keypair.privateKeyPem;
} }
return fs.writeFileAsync(keypath, key, 'ascii').then(function () { return writeFileAsync(keypath, key, 'ascii').then(function () {
return keypair; return keypair;
}); });
}); });
@ -199,15 +227,15 @@ module.exports.create = function (configs) {
return PromiseA.reject(new Error("missing one or more of privkeyPath, fullchainPath, certPath, chainPath from options")); return PromiseA.reject(new Error("missing one or more of privkeyPath, fullchainPath, certPath, chainPath from options"));
} }
//, fs.readFileAsync(fullchainPath, 'ascii') //, readFileAsync(fullchainPath, 'ascii')
// note: if this ^^ gets added back in, the arrays below must change // note: if this ^^ gets added back in, the arrays below must change
return PromiseA.all([ return PromiseA.all([
fs.readFileAsync(args.privkeyPath, 'ascii') // 0 readFileAsync(args.privkeyPath, 'ascii') // 0
, fs.readFileAsync(args.certPath, 'ascii') // 1 , readFileAsync(args.certPath, 'ascii') // 1
, fs.readFileAsync(args.chainPath, 'ascii') // 2 , readFileAsync(args.chainPath, 'ascii') // 2
// stat the file, not the link // stat the file, not the link
, fs.statAsync(args.certPath) // 3 , statAsync(args.certPath) // 3
]).then(function (arr) { ]).then(function (arr) {
return { return {
privkey: arr[0] // privkey.pem privkey: arr[0] // privkey.pem
@ -221,8 +249,8 @@ module.exports.create = function (configs) {
}; };
}, function (err) { }, function (err) {
if (args.debug) { if (args.debug) {
console.error("[le-store-certbot] certificates.check"); log("certificates.check");
console.error(err.stack); log(err.stack);
} }
return null; return null;
}); });
@ -239,9 +267,8 @@ module.exports.create = function (configs) {
var certPath = args.certPath || pyobj.cert || path.join(liveDir, 'cert.pem'); var certPath = args.certPath || pyobj.cert || path.join(liveDir, 'cert.pem');
var fullchainPath = args.fullchainPath || pyobj.fullchain || path.join(liveDir, 'fullchain.pem'); var fullchainPath = args.fullchainPath || pyobj.fullchain || path.join(liveDir, 'fullchain.pem');
var chainPath = args.chainPath || pyobj.chain || path.join(liveDir, 'chain.pem'); var chainPath = args.chainPath || pyobj.chain || path.join(liveDir, 'chain.pem');
var privkeyPath = args.privkeyPath || pyobj.privkey var privkeyPath = args.privkeyPath || pyobj.privkey || args.domainKeyPath || path.join(liveDir, 'privkey.pem');
|| args.domainKeyPath var bundlePath = args.bundlePath || pyobj.bundle || path.join(liveDir, 'bundle.pem');
|| path.join(liveDir, 'privkey.pem');
var archiveDir = args.archiveDir || path.join(args.configDir, 'archive', args.domains[0]); var archiveDir = args.archiveDir || path.join(args.configDir, 'archive', args.domains[0]);
@ -250,22 +277,31 @@ module.exports.create = function (configs) {
var fullchainArchive = path.join(archiveDir, 'fullchain' + checkpoints + '.pem'); var fullchainArchive = path.join(archiveDir, 'fullchain' + checkpoints + '.pem');
var chainArchive = path.join(archiveDir, 'chain'+ checkpoints + '.pem'); var chainArchive = path.join(archiveDir, 'chain'+ checkpoints + '.pem');
var privkeyArchive = path.join(archiveDir, 'privkey' + checkpoints + '.pem'); var privkeyArchive = path.join(archiveDir, 'privkey' + checkpoints + '.pem');
var bundleArchive = path.join(archiveDir, 'bundle' + checkpoints + '.pem');
return mkdirpAsync(archiveDir).then(function () { return mkdirpAsync(archiveDir).then(function () {
return PromiseA.all([ var ps = [
sfs.writeFileAsync(certArchive, pems.cert, 'ascii') sfs.writeFileAsync(certArchive, pems.cert, 'ascii')
, sfs.writeFileAsync(chainArchive, pems.chain, 'ascii') , sfs.writeFileAsync(chainArchive, pems.chain, 'ascii')
, sfs.writeFileAsync(fullchainArchive, pems.cert + pems.chain, 'ascii') , sfs.writeFileAsync(fullchainArchive, [ pems.cert, pems.chain ].join('\n'), 'ascii')
, sfs.writeFileAsync(privkeyArchive, pems.privkey, 'ascii') , sfs.writeFileAsync(privkeyArchive, pems.privkey, 'ascii')
]); ];
if (pems.bundle) {
var bundleP = sfs.writeFileAsync(bundleArchive, pems.bundle, 'ascii');
ps.push(bundleP);
}
return PromiseA.all(ps);
}).then(function () { }).then(function () {
return mkdirpAsync(liveDir); return mkdirpAsync(liveDir);
}).then(function () { }).then(function () {
return PromiseA.all([ return PromiseA.all([
sfs.writeFileAsync(certPath, pems.cert, 'ascii') sfs.writeFileAsync(certPath, pems.cert, 'ascii')
, sfs.writeFileAsync(chainPath, pems.chain, 'ascii') , sfs.writeFileAsync(chainPath, pems.chain, 'ascii')
, sfs.writeFileAsync(fullchainPath, pems.cert + pems.chain, 'ascii') // Most platforms need these two
, sfs.writeFileAsync(fullchainPath, [ pems.cert, pems.chain ].join('\n'), 'ascii')
, sfs.writeFileAsync(privkeyPath, pems.privkey, 'ascii') , sfs.writeFileAsync(privkeyPath, pems.privkey, 'ascii')
// HAProxy needs "bundle.pem" aka "combined.pem"
, sfs.writeFileAsync(bundlePath, [ pems.privkey, pems.cert, pems.chain ].join('\n'), 'ascii')
]); ]);
}).then(function () { }).then(function () {
pyobj.checkpoints += 1; pyobj.checkpoints += 1;
@ -279,6 +315,8 @@ module.exports.create = function (configs) {
privkey: pems.privkey privkey: pems.privkey
, cert: pems.cert , cert: pems.cert
, chain: pems.chain , chain: pems.chain
, expires: pems.expires
, identifiers: pems.identifiers
/* /*
// TODO populate these only if they are actually known // TODO populate these only if they are actually known
@ -323,11 +361,11 @@ module.exports.create = function (configs) {
log(args.debug, "No email given"); log(args.debug, "No email given");
return PromiseA.resolve(null); return PromiseA.resolve(null);
} }
return fs.readdirAsync(args.accountsDir).then(function (nodes) { return readdirAsync(args.accountsDir).then(function (nodes) {
log(args.debug, "success reading arg.accountsDir"); log(args.debug, "success reading arg.accountsDir");
return PromiseA.all(nodes.map(function (node) { return PromiseA.all(nodes.map(function (node) {
return fs.readFileAsync(path.join(args.accountsDir, node, 'regr.json'), 'utf8').then(function (text) { return readFileAsync(path.join(args.accountsDir, node, 'regr.json'), 'utf8').then(function (text) {
var regr = JSON.parse(text); var regr = JSON.parse(text);
regr.__accountId = node; regr.__accountId = node;
@ -368,7 +406,8 @@ module.exports.create = function (configs) {
// Accounts // Accounts
, _getAccountIdByPublicKey: function (keypair) { , _getAccountIdByPublicKey: function (keypair) {
// we use insecure md5 - even though we know it's bad - because that's how the python client did // we use insecure md5 - even though we know it's bad - because that's how the python client did
return require('crypto').createHash('md5').update(keypair.publicKeyPem).digest('hex'); var pubkey = keypair.publicKeyPem.replace(/\r/g, '');
return crypto.createHash('md5').update(pubkey).digest('hex');
} }
// Accounts // Accounts
, checkKeypairAsync: function (args) { , checkKeypairAsync: function (args) {
@ -424,7 +463,7 @@ module.exports.create = function (configs) {
return PromiseA.all(configs.map(function (filename) { return PromiseA.all(configs.map(function (filename) {
var keyname = filename.slice(0, -5); var keyname = filename.slice(0, -5);
return fs.readFileAsync(path.join(accountDir, filename), 'utf8').then(function (text) { return readFileAsync(path.join(accountDir, filename), 'utf8').then(function (text) {
var data; var data;
try { try {
@ -476,15 +515,25 @@ module.exports.create = function (configs) {
creation_host: os.hostname() creation_host: os.hostname()
, creation_dt: new Date().toISOString() , creation_dt: new Date().toISOString()
}; };
var uri = args.server.replace(/\/directory.*/,
'/acme/reg/' + accountId);
return mkdirpAsync(accountDir).then(function () { return mkdirpAsync(accountDir).then(function () {
var regrBody = {
body: reg.receipt,
uri: uri,
};
if (typeof reg.newAuthzUrl !== 'undefined') {
regrBody.new_authzr_uri = reg.newAuthzUrl;
}
// TODO abstract file writing // TODO abstract file writing
return PromiseA.all([ return PromiseA.all([
// meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"} // 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') writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8')
// private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" } // private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" }
, fs.writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(reg.keypair.privateKeyJwk), 'utf8') , writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(reg.keypair.privateKeyJwk), 'utf8')
// regr.json: // regr.json:
/* /*
{ body: { contact: [ 'mailto:coolaj86@gmail.com' ], { body: { contact: [ 'mailto:coolaj86@gmail.com' ],
@ -494,7 +543,9 @@ module.exports.create = function (configs) {
new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz', 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' } 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: reg.receipt }), 'utf8') , writeFileAsync(path.join(accountDir, 'regr.json'),
JSON.stringify(regrBody),
'utf8')
]); ]);
}).then(function () { }).then(function () {
return { return {
@ -508,7 +559,7 @@ module.exports.create = function (configs) {
} }
// Accounts // Accounts
, getAccountIdAsync: function (args) { , getAccountIdAsync: function (args) {
var pyconf = PromiseA.promisifyAll(require('pyconf')); var pyconf = promisifyAll(require('pyconf'));
return pyconf.readFileAsync(args.renewalPath).then(function (renewal) { return pyconf.readFileAsync(args.renewalPath).then(function (renewal) {
var accountId = renewal.account; var accountId = renewal.account;
@ -544,7 +595,7 @@ module.exports.create = function (configs) {
} }
// Configs // Configs
, _checkHelperAsync: function (args) { , _checkHelperAsync: function (args) {
var pyconf = PromiseA.promisifyAll(require('pyconf')); var pyconf = promisifyAll(require('pyconf'));
return pyconf.readFileAsync(args.renewalPath).then(function (pyobj) { return pyconf.readFileAsync(args.renewalPath).then(function (pyobj) {
return pyobj; return pyobj;
@ -598,7 +649,7 @@ module.exports.create = function (configs) {
, allAsync: function (copy) { , allAsync: function (copy) {
copy.domains = []; copy.domains = [];
return fs.readdirAsync(copy.renewalDir).then(function (nodes) { return readdirAsync(copy.renewalDir).then(function (nodes) {
nodes = nodes.filter(function (node) { nodes = nodes.filter(function (node) {
return /^[a-z0-9]+.*\.conf$/.test(node); return /^[a-z0-9]+.*\.conf$/.test(node);
}); });

26
package-lock.json generated Normal file
View File

@ -0,0 +1,26 @@
{
"name": "le-store-certbot",
"version": "2.2.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@root/mkdirp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz",
"integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA=="
},
"pyconf": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/pyconf/-/pyconf-1.1.7.tgz",
"integrity": "sha512-v4clh33m68sjtMsh8XMpjhGWb/MQODAYZ1y7ORG5Qv58UK25OddoB+oXyexgDkK8ttFui/lZm2sQDgA2Ftjfkw==",
"requires": {
"safe-replace": "^1.0.2"
}
},
"safe-replace": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz",
"integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw=="
}
}
}

View File

@ -1,14 +1,15 @@
{ {
"name": "le-store-certbot", "name": "le-store-certbot",
"version": "2.0.0", "version": "2.2.4",
"description": "The \"certbot\" storage strategy for node-letsencrypt", "description": "The \"certbot\" storage strategy for Greenlock.js",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"bump": "npm version -m \"chore(release): bump to v%s\"",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/Daplie/le-store-certbot.git" "url": "https://git.coolaj86.com/coolaj86/le-store-certbot.js"
}, },
"keywords": [ "keywords": [
"le-store", "le-store",
@ -20,7 +21,15 @@
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"bugs": { "bugs": {
"url": "https://github.com/Daplie/le-store-certbot/issues" "url": "https://git.coolaj86.com/coolaj86/le-store-certbot.js/issues"
}, },
"homepage": "https://github.com/Daplie/le-store-certbot#readme" "homepage": "https://git.coolaj86.com/coolaj86/le-store-certbot.js",
"trulyOptionalDependencies": {
"bluebird": "^3.5.1"
},
"dependencies": {
"@root/mkdirp": "^1.0.0",
"pyconf": "^1.1.7",
"safe-replace": "^1.1.0"
}
} }

View File

@ -6,63 +6,78 @@ fullchain = :fullchain_path
# Options and defaults used in the renewal process # Options and defaults used in the renewal process
[renewalparams] [renewalparams]
no_self_upgrade = True
apache_enmod = a2enmod apache_enmod = a2enmod
no_verify_ssl = False no_verify_ssl = False
ifaces = None ifaces = None
apache_dismod = a2dismod apache_dismod = a2dismod
register_unsafely_without_email = False register_unsafely_without_email = False
apache_handle_modules = True
uir = None uir = None
installer = none installer = None
nginx_ctl = nginx
config_dir = :configDir config_dir = :configDir
text_mode = True text_mode = True
# junk? # junk?
# https://github.com/letsencrypt/letsencrypt/issues/1955 # https://github.com/letsencrypt/letsencrypt/issues/1955
func = <function obtain_cert at 0x30c9500> func = <function obtain_cert at 0x7f093a163c08>
staging = False
prepare = False prepare = False
work_dir = :work_dir work_dir = :work_dir
tos = :agree_tos tos = :agree_tos
init = False init = False
http01_port = :http_01_port http01_port = :http_01_port
duplicate = False duplicate = False
noninteractive_mode = True
# this is for the domain # this is for the domain
key_path = :privkey_path key_path = :privkey_path
nginx = False nginx = False
nginx_server_root = /etc/nginx
fullchain_path = :fullchain_path fullchain_path = :fullchain_path
email = :email email = :email
csr = None csr = None
agree_dev_preview = None agree_dev_preview = None
redirect = None redirect = None
verb = certonly
verbose_count = -3 verbose_count = -3
config_file = None config_file = None
renew_by_default = True renew_by_default = True
hsts = False hsts = False
apache_handle_sites = True
authenticator = webroot authenticator = webroot
domains = :hostnames #comma,delimited,list domains = :hostnames #comma,delimited,list
rsa_key_size = :rsa_key_size rsa_key_size = :rsa_key_size
apache_challenge_location = /etc/apache2
# starts at 0 and increments at every renewal # starts at 0 and increments at every renewal
checkpoints = -1 checkpoints = -1
manual_test_mode = False manual_test_mode = False
apache = False apache = False
cert_path = :cert_path cert_path = :cert_path
webroot_path = :webroot_paths # comma,delimited,list webroot_path = :webroot_paths # comma,delimited,list
reinstall = False
expand = False
strict_permissions = False strict_permissions = False
apache_server_root = /etc/apache2 apache_server_root = /etc/apache2
# https://github.com/letsencrypt/letsencrypt/issues/1948 # https://github.com/letsencrypt/letsencrypt/issues/1948
account = :account_id account = :account_id
dry_run = False
manual_public_ip_logging_ok = False manual_public_ip_logging_ok = False
chain_path = :chain_path chain_path = :chain_path
break_my_certs = False
standalone = False standalone = False
manual = False manual = False
server = :acme_discovery_url server = :acme_discovery_url
standalone_supported_challenges = "http-01,tls-sni-01" standalone_supported_challenges = "http-01,tls-sni-01"
webroot = True webroot = True
os_packages_only = False
apache_init_script = None apache_init_script = None
user_agent = None user_agent = None
apache_ctl = apache2ctl
apache_le_vhost_ext = -le-ssl.conf apache_le_vhost_ext = -le-ssl.conf
debug = False debug = False
tls_sni_01_port = 443 tls_sni_01_port = 443
logs_dir = :logs_dir logs_dir = :logs_dir
apache_vhost_root = /etc/apache2/sites-available
configurator = None configurator = None
must_staple = False
[[webroot_map]] [[webroot_map]]
# :hostname = :webroot_path # :hostname = :webroot_path