2019-04-16 05:21:16 +00:00
|
|
|
# [greenlock-store-test](https://git.rootprojects.org/root/greenlock-store-test.js.git) | A [Root](https://rootprojects.org) Project
|
2019-04-08 07:27:04 +00:00
|
|
|
|
|
|
|
The test harness you should use when writing a certificate and keypair storage strategy
|
|
|
|
for [Greenlock](https://git.coolaj86.com/coolaj86/greenlock-express.js) v2.7+ (and v3).
|
|
|
|
|
|
|
|
All implementations MUST pass these tests, which is a very easy thing to do (just 3 getter/setter pairs to implement).
|
|
|
|
|
|
|
|
The tests account for single-domain certificates (`example.com`) as well as multiple domain certs (SAN / AltName),
|
|
|
|
wildcards (`*.example.com`), and valid private / localhost certificates. As someone creating a challenge strategy
|
|
|
|
that's not something you have to take special consideration for - just pass the tests.
|
|
|
|
|
|
|
|
## Install
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm install --save-dev greenlock-store-test@3.x
|
|
|
|
```
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
```js
|
|
|
|
var tester = require('greenlock-store-test');
|
|
|
|
|
|
|
|
//var store = require('greenlock-store-memory').create({});
|
|
|
|
//var store = require('greenlock-store-fs').create({});
|
|
|
|
var store = require('./YOUR-STORAGE-STRATEGY').create({});
|
|
|
|
|
|
|
|
// All of these tests can pass locally, standalone without any ACME integration.
|
|
|
|
tester.test(store).then(function () {
|
|
|
|
console.info("PASS");
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2019-04-16 05:21:16 +00:00
|
|
|
## Reference Implementations
|
|
|
|
|
|
|
|
These are plugins that use the v2.7+ (v3) API, and pass this test harness,
|
|
|
|
which you should use as a model for any plugins that you create.
|
|
|
|
|
|
|
|
* [`greenlock-store-memory`](https://git.rootprojects.org/root/greenlock-store-memory.js)
|
|
|
|
* [`greenlock-store-fs`](https://git.rootprojects.org/root/greenlock-store-fs.js)
|
|
|
|
|
|
|
|
## Example
|
|
|
|
|
|
|
|
See `example.js` (it works).
|
|
|
|
|
|
|
|
## Looking for the Easy Button?
|
|
|
|
|
|
|
|
[Contact Root](mailto:support@rootprojects.org)
|
|
|
|
|
|
|
|
If you're looking for fast and inexpensive plugin development,
|
|
|
|
we can deliver greater value in less time than most outsouring options.
|
|
|
|
We can also work with your in-house team to give a quick, inexpensive 10x
|
|
|
|
boost to internal development success.
|
|
|
|
|
|
|
|
We also offer commercial licenses for LTS (Long-Term Support) versions of Greenlock.
|
|
|
|
|
2019-04-08 07:27:04 +00:00
|
|
|
## Overview
|
|
|
|
|
|
|
|
The most generic implementation, with no special considerations or custom logic, ends up looking like this:
|
|
|
|
|
|
|
|
```js
|
|
|
|
tester.test({
|
|
|
|
|
|
|
|
|
|
|
|
// ACME user account
|
|
|
|
accounts: {
|
|
|
|
setKeypair: function (opts) {
|
|
|
|
// { account: { id: '...' } // you may or may not receive 'id'
|
|
|
|
// , email: 'jon.doe@example.com'
|
|
|
|
// , keypair: { privateKeyPem: '...', privateKeyJwk: {...} }
|
|
|
|
// }
|
|
|
|
|
|
|
|
var id = opts.account.id || opts.email;
|
|
|
|
return DB.Keypairs.save(id, JSON.stringify(opts.keypair));
|
|
|
|
}
|
|
|
|
, checkKeypair: function (opts) {
|
|
|
|
// you receive the same options as setKeypair() above
|
|
|
|
var id = opts.account.id || opts.email;
|
|
|
|
return DB.Keypairs.get(id).then(function (k) { return JSON.parse(k); });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Site Keys & Certificates
|
|
|
|
, certificates: {
|
|
|
|
|
|
|
|
// Site Keys (privkey.pem a.k.a. example.com.key)
|
|
|
|
setKeypair: function (opts) {
|
|
|
|
// { certificate: { kid: '...', id: '...' } // you may or may not receive 'kid' or 'id'
|
|
|
|
// , subject: 'foo.example.com'
|
|
|
|
// , keypair: { privateKeyPem: '...', privateKeyJwk: {...} }
|
|
|
|
// }
|
|
|
|
|
|
|
|
var id = opts.certificate.kid || opts.certificate.id || opts.subject;
|
|
|
|
return DB.Keypairs.save(id, JSON.stringify(opts.keypair));
|
|
|
|
}
|
|
|
|
, checkKeypair: function (opts) {
|
|
|
|
// you receive the same options as setKeypair() above
|
|
|
|
var id = opts.certificate.kid || opts.certificate.id || opts.subject;
|
|
|
|
return DB.Keypairs.get(id).then(function (x) { return JSON.parse(x); });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Certificates (fullchain.pem a.k.a. cert.pem a.k.a. example.com.crt)
|
|
|
|
, set: function (opts) {
|
|
|
|
// { certificate: { id: '...' } // you may or may not receive 'id'
|
|
|
|
// , subject: 'foo.example.com'
|
|
|
|
// , pems: { cert: '...', chain: '...', ... }
|
|
|
|
// }
|
|
|
|
|
|
|
|
var id = opts.certificate.id || opts.subject;
|
|
|
|
return DB.Certificates.save(id, JSON.stringify(opts.keypair));
|
|
|
|
}
|
|
|
|
, set: function (opts) {
|
|
|
|
// { certificate: { id: '...' } // you may or may not receive 'id'
|
|
|
|
// , subject: 'foo.example.com'
|
|
|
|
// , pems: { cert: '...', chain: '...', ... }
|
|
|
|
// }
|
|
|
|
|
|
|
|
var id = opts.certificate.id || opts.subject;
|
|
|
|
return DB.Certificates.save(id, JSON.stringify(opts.keypair));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).then(function () {
|
|
|
|
console.info("PASS");
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
Note: The `DB.x.y()` is where you do your magic up to connect to a database or API or whatever and keep stuff safe.
|