update docs

This commit is contained in:
AJ ONeal 2019-11-02 13:26:08 -06:00
parent e0a9fff07d
commit 5490a194eb
3 changed files with 161 additions and 106 deletions

263
README.md
View File

@ -12,125 +12,180 @@ Works with all ACME (Let's Encrypt) SSL certificate sytles:
# Usage
**Global** config:
```js
var greenlock = require('greenlock');
var gl = greenlock.create({
configDir: '~/.config/acme'
, store: require('greenlock-store-fs')
, approveDomains: approveDomains
, ...
greenlock.manager.defaults({
store: {
module: "greenlock-store-fs",
basePath: "~/.config/greenlock"
}
});
```
**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
The default file system layout mirrors that of le-store-certbot in order to make transitioning effortless,
in most situations:
The default file system layout mirrors that of certbot (python Let's Encrypt implementation) and
the prior le-store-certbot in order to make transitioning effortless.
```
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
The default structure looks like this:
```txt
.config
└── greenlock
├── accounts
│   └── acme-staging-v02.api.letsencrypt.org
│   └── directory
│   └── sites@example.com.json
├── staging
│ └── (same as live)
└── 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
# 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
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).
# Parameters
`altnames` should be the list of SubjectAlternativeNames (SANs) on the certificate.
The subject and the first altname must be an exact match: `subject === altnames[0]`.
| parameters | example | notes |
| ----------------- | -------------------------------------------------------- | ---------------- |
| `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
function approveDomains(opts) {
// Allow only example.com and *.example.com (such as foo.example.com)
// foo.example.com => *.example.com
var wild =
"*." +
opts.domain
.split(".")
.slice(1)
.join(".");
if ("example.com" !== opts.domain && "*.example.com" !== wild) {
cb(new Error(opts.domain + " is not allowed"));
}
var result = {
subject: "example.com",
altnames: ["example.com", "*.example.com"]
};
return Promise.resolve(result);
}
```
## Realistic Example
```js
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 });
}
```
```js
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;
}
}
```
```js
var allAllowedDomains = {
"example.com": ["example.com", "*.example.com"],
"example.net": ["example.net", "*.example.net"]
accounts.setKeypair = async function({
env,
basePath,
directoryUrl,
email,
account
}) {
var id = account.id || email;
var serverDir = directoryUrl.replace("https://", "");
};
```
```js
accounts.checkKeypair = async function({
env,
basePath,
directoryUrl,
email,
account
}) {
var id = account.id || email;
var serverDir = directoryUrl.replace("https://", "");
return {
privateKeyPem,
privateKeyJwk
};
};
```
### Certificate Keypair
```js
certificate.setKeypair = async function({
env,
basePath,
directoryUrl,
subject,
certificate
}) {
var id = account.id || email;
env = env || directoryUrl.replace("https://", "");
};
```
```js
certificate.checkKeypair = async function({
env,
basePath,
directoryUrl,
subject,
certificate
}) {
var id = account.id || email;
env = env || directoryUrl.replace("https://", "");
return {
privateKeyPem,
privateKeyJwk
};
};
```
### Certificate PEMs
```js
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
};
};
```

View File

@ -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.
// Return an object with string PEMs for cert and chain (or null, not undefined)
certificates.check = function(opts) {
// { certificate.id, subject, ... }
// { directoryUrl, subject, certificate.id, ... }
var id = (opts.certificate && opts.certificate.id) || opts.subject;
//console.log('certificates.check for', opts);

View File

@ -1,6 +1,6 @@
{
"name": "greenlock-store-fs",
"version": "3.2.1",
"version": "3.2.2",
"description": "A file-based certificate store for greenlock that supports wildcards.",
"homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
"main": "index.js",