Compare commits
20 Commits
Author | SHA1 | Date |
---|---|---|
AJ ONeal | 7cdb42db7a | |
CaptEmulation | 37a7fd55b7 | |
AJ ONeal | e96ab294b6 | |
AJ ONeal | 7bdf8804a3 | |
AJ ONeal | 718e081495 | |
AJ ONeal | 258ad19f77 | |
AJ ONeal | 861872499e | |
AJ ONeal | 03a4db1034 | |
AJ ONeal | b0eff828bb | |
AJ ONeal | b3102ded8d | |
AJ ONeal | 8f13081270 | |
AJ ONeal | 00157ab870 | |
AJ ONeal | a0bda23683 | |
AJ ONeal | e120d2dcc2 | |
AJ ONeal | f8f7a75c99 | |
AJ ONeal | dfa5f79e0d | |
AJ ONeal | 5af14f1147 | |
AJ ONeal | bbf5168fb7 | |
AJ ONeal | 5a5848614b | |
AJ ONeal | ee294fce8c |
|
@ -0,0 +1,37 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules
|
||||||
|
jspm_packages
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Daplie, Inc
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,99 @@
|
||||||
|
# le-store-SPEC
|
||||||
|
|
||||||
|
The reference implementation, specification, template, and tests for creating an le-store- strategy.
|
||||||
|
|
||||||
|
The reference implementation is completely in-memory.
|
||||||
|
|
||||||
|
See [Help Wanted: Database Plugins (for saving certs)](https://github.com/Daplie/node-letsencrypt/issues/39)
|
||||||
|
|
||||||
|
How to create a custom strategy
|
||||||
|
===============================
|
||||||
|
|
||||||
|
READ THIS README:
|
||||||
|
Believe it or not, most of your answers are either right here
|
||||||
|
or in the comments in the sample code in `index.js`.
|
||||||
|
|
||||||
|
Now, let's say there's some new database AwesomeDB that
|
||||||
|
we want to make a plugin for, here's how we'd start:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# First create you repo on github or wherever
|
||||||
|
# Then clone it
|
||||||
|
git clone git@github.com:AwesomeDB/le-store-awesome.git
|
||||||
|
|
||||||
|
pushd le-store-awesome
|
||||||
|
|
||||||
|
# IMPORTANT: we pull in the 'template' branch, which has the skeleton code
|
||||||
|
git pull https://github.com/Daplie/le-store-SPEC.git template
|
||||||
|
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you already have some code and just need to merge in the tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull https://github.com/Daplie/le-store-SPEC.git tests
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, Just run the tests
|
||||||
|
|
||||||
|
```
|
||||||
|
node tests/basic.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: you should not modify the tests that come from the tests branch,
|
||||||
|
but rather create separate files for your own tests.
|
||||||
|
|
||||||
|
API
|
||||||
|
===
|
||||||
|
|
||||||
|
```
|
||||||
|
* getOptions()
|
||||||
|
* accounts.
|
||||||
|
* checkKeypair(opts, cb)
|
||||||
|
* setKeypair(opts, keypair, cb)
|
||||||
|
* check(opts, cb)
|
||||||
|
* set(opts, reg, cb)
|
||||||
|
* certificates.
|
||||||
|
* checkKeypair(opts, cb)
|
||||||
|
* setKeypair(opts, keypair, cb)
|
||||||
|
* check(opts, cb)
|
||||||
|
* set(opts, certs, cb)
|
||||||
|
```
|
||||||
|
|
||||||
|
Keypairs
|
||||||
|
--------
|
||||||
|
|
||||||
|
For convenience, the keypair object will always contain **both** PEM and JWK
|
||||||
|
versions of the private and/or public keys when being passed to the `*Keypair` functions.
|
||||||
|
|
||||||
|
**set**
|
||||||
|
|
||||||
|
`setKeypair` will always be called with `email` and **all three** forms of the keypair:
|
||||||
|
`privateKeyPem`, `publicKeyPem`, and `privateKeyJwk`. It's easy to generate `publicKeyJwk`
|
||||||
|
from `privateKeyJwk` because it is just a copy of the public fields `e` and `n`.
|
||||||
|
|
||||||
|
```
|
||||||
|
// keypair looks like this
|
||||||
|
{ privateKeyPem: '...'
|
||||||
|
, publicKeyPem: '...'
|
||||||
|
, privateKeyJwk: { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**check**
|
||||||
|
|
||||||
|
`checkKeypair` may be called with any of `email`, `accountId`, and `keypair` - which will
|
||||||
|
contain only `publicKeyPem` and `publicKeyJwk`.
|
||||||
|
|
||||||
|
```
|
||||||
|
// opts looks like this
|
||||||
|
{
|
||||||
|
email: '...@...'
|
||||||
|
, accountId: '...'
|
||||||
|
, keypair: {
|
||||||
|
publicKeyPem: '...'
|
||||||
|
, publicKeyJwk: { ... }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,126 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports.create = function (options) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var defaults = {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var accounts = {
|
||||||
|
|
||||||
|
// Accounts
|
||||||
|
setKeypair: function (opts, keypair, cb) {
|
||||||
|
// opts.email // optional
|
||||||
|
// opts.accountId // optional - same as returned from acounts.set(opts, reg)
|
||||||
|
|
||||||
|
|
||||||
|
// SAVE to db (as PEM and/or JWK) and index each domain in domains to this keypair
|
||||||
|
// keypair = { privateKeyPem: '...', privateKeyJwk: { ... } }
|
||||||
|
cb(null, keypair);
|
||||||
|
}
|
||||||
|
// Accounts
|
||||||
|
, checkKeypair: function (opts, cb) {
|
||||||
|
// opts.email // optional
|
||||||
|
// opts.accountId // optional - same as returned from acounts.set(opts, reg)
|
||||||
|
|
||||||
|
|
||||||
|
// check db and return null or keypair object with one
|
||||||
|
// (or both) of privateKeyPem or privateKeyJwk
|
||||||
|
cb(null, { privateKeyPem: '...', privateKeyJwk: {} });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Accounts
|
||||||
|
, check: function (opts, cb) {
|
||||||
|
// opts.email // optional
|
||||||
|
// opts.accountId // optional - same as returned from acounts.set(opts, reg)
|
||||||
|
// opts.domains // optional - same as set in certificates.set(opts, certs)
|
||||||
|
|
||||||
|
// return account from db if it exists, otherwise null
|
||||||
|
cb(null, { id: '...', keypair: { privateKeyJwk: {} }/*, domains: []*/ });
|
||||||
|
}
|
||||||
|
// Accounts
|
||||||
|
, set: function (opts, reg, cb) {
|
||||||
|
// opts.email
|
||||||
|
// reg.keypair
|
||||||
|
// reg.receipt // response from acme server
|
||||||
|
|
||||||
|
|
||||||
|
// You must implement a method to deterministically generate 'id'
|
||||||
|
// For example, you could do this:
|
||||||
|
// var id = crypto.createHash('sha256').update(reg.keypair.publicKeyPem).digest('hex');
|
||||||
|
cb(null, { id: '...', email: opts.email, keypair: reg.keypair, receipt: reg.receipt });
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var certificates = {
|
||||||
|
|
||||||
|
// Certificates
|
||||||
|
setKeypair: function (opts, keypair, cb) {
|
||||||
|
// opts.domains - this is an array, but you nly need the first (or any) of them
|
||||||
|
|
||||||
|
|
||||||
|
// SAVE to db (as PEM and/or JWK) and index each domain in domains to this keypair
|
||||||
|
cb(null, keypair);
|
||||||
|
}
|
||||||
|
// Certificates
|
||||||
|
, checkKeypair: function (opts, cb) {
|
||||||
|
// opts.domains - this is an array, but you only need the first (or any) of them
|
||||||
|
|
||||||
|
|
||||||
|
// check db and return null or keypair object with one of privateKeyPem or privateKeyJwk
|
||||||
|
cb(null, { privateKeyPem: '...', privateKeyJwk: {} });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Certificates
|
||||||
|
, check: function (opts, cb) {
|
||||||
|
// You will be provided one of these (which should be tried in this order)
|
||||||
|
// opts.domains
|
||||||
|
// opts.email // optional
|
||||||
|
// opts.accountId // optional
|
||||||
|
|
||||||
|
|
||||||
|
// return certificate PEMs from db if they exist, otherwise null
|
||||||
|
// optionally include expiresAt and issuedAt, if they are known exactly
|
||||||
|
// (otherwise they will be read from the cert itself later)
|
||||||
|
cb(null, { privkey: 'PEM', cert: 'PEM', chain: 'PEM', domains: [], accountId: '...' });
|
||||||
|
}
|
||||||
|
// Certificates
|
||||||
|
, set: function (opts, cb) {
|
||||||
|
// opts.domains // each of these must be indexed
|
||||||
|
// opts.email // optional, should be indexed
|
||||||
|
// opts.accountId // optional - same as set by you in accounts.set(opts, keypair) above
|
||||||
|
|
||||||
|
// opts.certs.privkey
|
||||||
|
// opts.certs.cert
|
||||||
|
// opts.certs.chain
|
||||||
|
|
||||||
|
|
||||||
|
// SAVE to the database, index the email address, the accountId, and alias the domains
|
||||||
|
cb(null, { privkey: 'PEM', cert: 'PEM', chain: 'PEM' });
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
getOptions: function () {
|
||||||
|
// merge options with default settings and then return them
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
, accounts: accounts
|
||||||
|
, certificates: certificates
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
Loading…
Reference in New Issue