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 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 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 +18,28 @@ 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' , workDir: require('homedir')() + '/acme/var/lib'
, logsDir: require('homedir')() + '/letsencrypt/var/log' , 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 , 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 +48,7 @@ Example File Structure
---------------------- ----------------------
``` ```
~/letsencrypt/ ~/acme/
└── etc └── etc
├── accounts ├── accounts
│   └── acme-staging.api.letsencrypt.org │   └── acme-staging.api.letsencrypt.org
@ -53,19 +58,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
``` ```

View File

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

View File

@ -1,14 +1,14 @@
{ {
"name": "le-store-certbot", "name": "le-store-certbot",
"version": "2.0.5", "version": "2.1.0",
"description": "The \"certbot\" storage strategy for node-letsencrypt", "description": "The \"certbot\" storage strategy for Greenlock.js",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"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,11 +20,12 @@
"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",
"dependencies": { "dependencies": {
"bluebird": "^3.4.1", "bluebird": "^3.5.1",
"fs-symlink": "^1.2.1",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"pyconf": "^1.1.2", "pyconf": "^1.1.2",
"safe-replace": "^1.0.2" "safe-replace": "^1.0.2"

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 = True
[[webroot_map]] [[webroot_map]]
# :hostname = :webroot_path # :hostname = :webroot_path