AJ ONeal 9f61e34a8a | ||
---|---|---|
.gitignore | ||
LICENSE | ||
README.md | ||
index.js | ||
package-lock.json | ||
package.json |
README.md
le-store-fs
A greenlock keypair and certificate storage strategy with wildcard support (simpler successor to le-store-certbot).
Usage
var greenlock = require('greenlock');
var gl = greenlock.create({
configDir: '~/.config/acme'
, store: require('le-store-fs')
, approveDomains: approveDomains
, ...
});
File System
The default file system layout mirrors that of le-store-certbot in order to make transitioning effortless, in most situations:
acme
├── accounts
│ └── acme-staging-v02.api.letsencrypt.org
│ └── directory
│ └── sites@example.com.json
└── live
├── example.com
│ ├── bundle.pem
│ ├── cert.pem
│ ├── chain.pem
│ ├── fullchain.pem
│ └── privkey.pem
└── www.example.com
├── bundle.pem
├── cert.pem
├── chain.pem
├── fullchain.pem
└── privkey.pem
Wildcards & AltNames
Working with wildcards and multiple altnames requires greenlock >= v2.7.
To do so you must set opts.subject
and opts.domains
within the approvedomains()
callback.
subject
refers to "the subject of the ssl certificate" as opposed to domain
which indicates "the domain servername
used in the current request". For single-domain certificates they're always the same, but for multiple-domain
certificates subject
must be the name no matter what domain
is receiving a request. subject
is used as
part of the name of the file storage path where the certificate will be saved (or retrieved).
domains
should be the list of "altnames" on the certificate, which should include the subject
.
Simple Example
function approveDomains(opts, certs, cb) {
// foo.example.com => *.example.com
var wild = '*.' + opts.domain.split('.').slice(1).join('.');
if ('*.example.com' !== wild) { cb(new Error(opts.domain + " is not allowed")); }
opts.subject = '*.example.com';
opts.domains = ['*.example.com'];
cb({ options: opts, certs: certs });
}
Realistic Example
function approveDomains(opts, certs, cb) {
var related = getRelated(opts.domain);
if (!related) { cb(new Error(opts.domain + " is not allowed")); };
opts.subject = related.subject;
opts.domains = related.domains;
cb({ options: opts, certs: certs });
}
function getRelated(domain) {
var related;
var wild = '*.' + domain.split('.').slice(1).join('.');
if (Object.keys(allAllowedDomains).some(function (k) {
return allAllowedDomains[k].some(function (name) {
if (domain === name || wild === name) {
related = { subject: k, altnames: allAllowedDomains[k] };
return true;
}
});
})) {
return related;
}
}
var allAllowedDomains = {
'example.com': ['example.com', '*.example.com']
, 'example.net': ['example.net', '*.example.net']
}