This commit is contained in:
AJ ONeal 2018-05-12 18:49:48 -06:00
parent c81d965c71
commit 0990fd24fc
4 changed files with 56 additions and 29 deletions

View File

@ -1,7 +1,8 @@
le-store-certbot
================
The "certbot" storage strategy for node-letsencrypt.
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
configuration files and file structure of the official certbot client.
@ -17,24 +18,28 @@ npm install --save le-store-certbot@2.x
```bash
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' //
, fullchainPath: ':configDir/live/:hostname/fullchain.pem' // Note: both that :configDir and :hostname
, 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')() + '/letsencrypt/var/log'
, workDir: require('homedir')() + '/acme/var/lib'
, logsDir: require('homedir')() + '/acme/var/log'
, webrootPath: '~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge'
, webrootPath: '~/acme/srv/www/:hostname/.well-known/acme-challenge'
, 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
});
```
@ -43,7 +48,7 @@ Example File Structure
----------------------
```
~/letsencrypt/
~/acme/
└── etc
├── accounts
│   └── acme-staging.api.letsencrypt.org
@ -53,19 +58,19 @@ Example File Structure
│   ├── private_key.json
│   └── regr.json
├── archive
│   └── example.daplie.me
│   └── example.com
│   ├── cert0.pem
│   ├── chain0.pem
│   ├── fullchain0.pem
│   └── privkey0.pem
├── live
│   └── example.daplie.me
│   └── example.com
│   ├── cert.pem
│   ├── chain.pem
│   ├── fullchain.pem
│   ├── privkey.pem
│   └── privkey.pem.bak
└── renewal
├── example.daplie.me.conf
└── example.daplie.me.conf.bak
├── example.com.conf
└── example.com.conf.bak
```

View File

@ -6,6 +6,7 @@ var path = require('path');
var fs = PromiseA.promisifyAll(require('fs'));
var sfs = require('safe-replace');
var os = require('os');
var symlink = require('fs-symlink');
function log(debug) {
if (debug) {
@ -267,10 +268,10 @@ module.exports.create = function (configs) {
return mkdirpAsync(liveDir);
}).then(function () {
return PromiseA.all([
sfs.writeFileAsync(certPath, pems.cert, 'ascii')
, sfs.writeFileAsync(chainPath, pems.chain, 'ascii')
, sfs.writeFileAsync(fullchainPath, pems.cert + pems.chain, 'ascii')
, sfs.writeFileAsync(privkeyPath, pems.privkey, 'ascii')
symlink(certArchive, certPath)
, symlink(chainArchive, chainPath)
, symlink(fullchainArchive, fullchainPath)
, symlink(privkeyArchive, privkeyPath)
]);
}).then(function () {
pyobj.checkpoints += 1;
@ -373,7 +374,8 @@ module.exports.create = function (configs) {
// Accounts
, _getAccountIdByPublicKey: function (keypair) {
// 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');
const pubkey = keypair.publicKeyPem.replace(/\r/g, '');
return require('crypto').createHash('md5').update(pubkey).digest('hex');
}
// Accounts
, checkKeypairAsync: function (args) {
@ -481,6 +483,8 @@ module.exports.create = function (configs) {
creation_host: os.hostname()
, creation_dt: new Date().toISOString()
};
var uri = args.server.replace(/\/directory.*/,
'/acme/reg/' + accountId);
return mkdirpAsync(accountDir).then(function () {
@ -499,7 +503,9 @@ module.exports.create = function (configs) {
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: reg.receipt }), 'utf8')
, fs.writeFileAsync(path.join(accountDir, 'regr.json'),
JSON.stringify({ body: reg.receipt, uri: uri }),
'utf8')
]);
}).then(function () {
return {

View File

@ -1,14 +1,14 @@
{
"name": "le-store-certbot",
"version": "2.0.5",
"description": "The \"certbot\" storage strategy for node-letsencrypt",
"version": "2.1.0",
"description": "The \"certbot\" storage strategy for Greenlock.js",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Daplie/le-store-certbot.git"
"url": "https://git.coolaj86.com/coolaj86/le-store-certbot.js"
},
"keywords": [
"le-store",
@ -20,11 +20,12 @@
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "(MIT OR Apache-2.0)",
"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",
"dependencies": {
"bluebird": "^3.4.1",
"bluebird": "^3.5.1",
"fs-symlink": "^1.2.1",
"mkdirp": "^0.5.1",
"pyconf": "^1.1.2",
"safe-replace": "^1.0.2"

View File

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