update docs
This commit is contained in:
parent
e0a9fff07d
commit
5490a194eb
263
README.md
263
README.md
|
@ -12,125 +12,180 @@ Works with all ACME (Let's Encrypt) SSL certificate sytles:
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
|
**Global** config:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var greenlock = require('greenlock');
|
greenlock.manager.defaults({
|
||||||
var gl = greenlock.create({
|
store: {
|
||||||
configDir: '~/.config/acme'
|
module: "greenlock-store-fs",
|
||||||
, store: require('greenlock-store-fs')
|
basePath: "~/.config/greenlock"
|
||||||
, approveDomains: approveDomains
|
}
|
||||||
, ...
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Per-site** config:
|
||||||
|
|
||||||
|
```js
|
||||||
|
greenlock.add({
|
||||||
|
subject: "example.com",
|
||||||
|
altnames: ["example.com", "www.example.com"],
|
||||||
|
store: {
|
||||||
|
module: "greenlock-store-fs",
|
||||||
|
basePath: "~/.config/greenlock"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
# File System
|
# File System
|
||||||
|
|
||||||
The default file system layout mirrors that of le-store-certbot in order to make transitioning effortless,
|
The default file system layout mirrors that of certbot (python Let's Encrypt implementation) and
|
||||||
in most situations:
|
the prior le-store-certbot in order to make transitioning effortless.
|
||||||
|
|
||||||
```
|
The default structure looks like this:
|
||||||
acme
|
|
||||||
├── accounts
|
```txt
|
||||||
│ └── acme-staging-v02.api.letsencrypt.org
|
.config
|
||||||
│ └── directory
|
└── greenlock
|
||||||
│ └── sites@example.com.json
|
├── accounts
|
||||||
└── live
|
│ └── acme-staging-v02.api.letsencrypt.org
|
||||||
├── example.com
|
│ └── directory
|
||||||
│ ├── bundle.pem
|
│ └── sites@example.com.json
|
||||||
│ ├── cert.pem
|
├── staging
|
||||||
│ ├── chain.pem
|
│ └── (same as live)
|
||||||
│ ├── fullchain.pem
|
└── live
|
||||||
│ └── privkey.pem
|
├── example.com
|
||||||
└── www.example.com
|
│ ├── bundle.pem
|
||||||
├── bundle.pem
|
│ ├── cert.pem
|
||||||
├── cert.pem
|
│ ├── chain.pem
|
||||||
├── chain.pem
|
│ ├── fullchain.pem
|
||||||
├── fullchain.pem
|
│ └── privkey.pem
|
||||||
└── privkey.pem
|
└── www.example.com
|
||||||
|
├── bundle.pem
|
||||||
|
├── cert.pem
|
||||||
|
├── chain.pem
|
||||||
|
├── fullchain.pem
|
||||||
|
└── privkey.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
# Wildcards & AltNames
|
# Internal Implementation Details
|
||||||
|
|
||||||
Working with wildcards and multiple altnames requires greenlock >= v2.7 (or v3).
|
You **DO NOT NEED TO KNOW** these details.
|
||||||
|
|
||||||
To do so you must return `{ subject: '...', altnames: ['...', ...] }` within the `approveDomains()` callback.
|
They're provided for the sake of understanding what happens "under the hood"
|
||||||
|
to help you make better choices "in the seat".
|
||||||
|
|
||||||
`subject` refers to "the subject of the ssl certificate" as opposed to `domain` which indicates "the domain servername
|
# Parameters
|
||||||
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).
|
|
||||||
|
|
||||||
`altnames` should be the list of SubjectAlternativeNames (SANs) on the certificate.
|
| parameters | example | notes |
|
||||||
The subject and the first altname must be an exact match: `subject === altnames[0]`.
|
| ----------------- | -------------------------------------------------------- | ---------------- |
|
||||||
|
| `env` | `staging` or `live` | - |
|
||||||
|
| `directoryUrl` | `https://acme-staging-v02.api.letsencrypt.org/directory` | - |
|
||||||
|
| `keypair` | `{ privateKeyPem, privateKeyJwk }` | |
|
||||||
|
| `account` | `{ id: "an-arbitrary-id" }` | account only |
|
||||||
|
| `subscriberEmail` | `webhost@example.com` | account only |
|
||||||
|
| `certificate` | `{ id: "an-arbitrary-id" }` | certificate only |
|
||||||
|
| `subject` | `example.com` | certificate only |
|
||||||
|
| `pems` | `{ privkey, cert, chain, issuedAt, expiresAt }` | certificate only |
|
||||||
|
|
||||||
## Simple Example
|
### Account Keypair
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function approveDomains(opts) {
|
accounts.setKeypair = async function({
|
||||||
// Allow only example.com and *.example.com (such as foo.example.com)
|
env,
|
||||||
|
basePath,
|
||||||
// foo.example.com => *.example.com
|
directoryUrl,
|
||||||
var wild =
|
email,
|
||||||
"*." +
|
account
|
||||||
opts.domain
|
}) {
|
||||||
.split(".")
|
var id = account.id || email;
|
||||||
.slice(1)
|
var serverDir = directoryUrl.replace("https://", "");
|
||||||
.join(".");
|
};
|
||||||
|
```
|
||||||
if ("example.com" !== opts.domain && "*.example.com" !== wild) {
|
|
||||||
cb(new Error(opts.domain + " is not allowed"));
|
```js
|
||||||
}
|
accounts.checkKeypair = async function({
|
||||||
|
env,
|
||||||
var result = {
|
basePath,
|
||||||
subject: "example.com",
|
directoryUrl,
|
||||||
altnames: ["example.com", "*.example.com"]
|
email,
|
||||||
};
|
account
|
||||||
return Promise.resolve(result);
|
}) {
|
||||||
}
|
var id = account.id || email;
|
||||||
```
|
var serverDir = directoryUrl.replace("https://", "");
|
||||||
|
|
||||||
## Realistic Example
|
return {
|
||||||
|
privateKeyPem,
|
||||||
```js
|
privateKeyJwk
|
||||||
function approveDomains(opts, certs, cb) {
|
};
|
||||||
var related = getRelated(opts.domain);
|
};
|
||||||
if (!related) {
|
```
|
||||||
cb(new Error(opts.domain + " is not allowed"));
|
|
||||||
}
|
### Certificate Keypair
|
||||||
|
|
||||||
opts.subject = related.subject;
|
```js
|
||||||
opts.domains = related.domains;
|
certificate.setKeypair = async function({
|
||||||
|
env,
|
||||||
cb({ options: opts, certs: certs });
|
basePath,
|
||||||
}
|
directoryUrl,
|
||||||
```
|
subject,
|
||||||
|
certificate
|
||||||
```js
|
}) {
|
||||||
function getRelated(domain) {
|
var id = account.id || email;
|
||||||
var related;
|
env = env || directoryUrl.replace("https://", "");
|
||||||
var wild =
|
};
|
||||||
"*." +
|
```
|
||||||
domain
|
|
||||||
.split(".")
|
```js
|
||||||
.slice(1)
|
certificate.checkKeypair = async function({
|
||||||
.join(".");
|
env,
|
||||||
if (
|
basePath,
|
||||||
Object.keys(allAllowedDomains).some(function(k) {
|
directoryUrl,
|
||||||
return allAllowedDomains[k].some(function(name) {
|
subject,
|
||||||
if (domain === name || wild === name) {
|
certificate
|
||||||
related = { subject: k, altnames: allAllowedDomains[k] };
|
}) {
|
||||||
return true;
|
var id = account.id || email;
|
||||||
}
|
env = env || directoryUrl.replace("https://", "");
|
||||||
});
|
|
||||||
})
|
return {
|
||||||
) {
|
privateKeyPem,
|
||||||
return related;
|
privateKeyJwk
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
### Certificate PEMs
|
||||||
var allAllowedDomains = {
|
|
||||||
"example.com": ["example.com", "*.example.com"],
|
```js
|
||||||
"example.net": ["example.net", "*.example.net"]
|
certificate.set = async function({
|
||||||
|
env,
|
||||||
|
basePath,
|
||||||
|
directoryUrl,
|
||||||
|
subject,
|
||||||
|
certificate,
|
||||||
|
pems
|
||||||
|
}) {
|
||||||
|
var id = account.id || email;
|
||||||
|
env = env || directoryUrl.replace("https://", "");
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
certificate.check = async function({
|
||||||
|
env,
|
||||||
|
basePath,
|
||||||
|
directoryUrl,
|
||||||
|
subject,
|
||||||
|
certificate
|
||||||
|
}) {
|
||||||
|
var id = account.id || email;
|
||||||
|
env = env || directoryUrl.replace("https://", "");
|
||||||
|
|
||||||
|
return {
|
||||||
|
privkey,
|
||||||
|
cert,
|
||||||
|
chain,
|
||||||
|
issuedAt,
|
||||||
|
expiresAt
|
||||||
|
};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
|
@ -17,7 +17,7 @@ var mkdirpAsync = PromiseA.promisify(require("@root/mkdirp"));
|
||||||
// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
|
// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
|
||||||
// Return an object with string PEMs for cert and chain (or null, not undefined)
|
// Return an object with string PEMs for cert and chain (or null, not undefined)
|
||||||
certificates.check = function(opts) {
|
certificates.check = function(opts) {
|
||||||
// { certificate.id, subject, ... }
|
// { directoryUrl, subject, certificate.id, ... }
|
||||||
var id = (opts.certificate && opts.certificate.id) || opts.subject;
|
var id = (opts.certificate && opts.certificate.id) || opts.subject;
|
||||||
//console.log('certificates.check for', opts);
|
//console.log('certificates.check for', opts);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "greenlock-store-fs",
|
"name": "greenlock-store-fs",
|
||||||
"version": "3.2.1",
|
"version": "3.2.2",
|
||||||
"description": "A file-based certificate store for greenlock that supports wildcards.",
|
"description": "A file-based certificate store for greenlock that supports wildcards.",
|
||||||
"homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
|
"homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
Loading…
Reference in New Issue