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
|
||||
|
||||
**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
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue