greenlock-store-memory.js/index.js

145 lines
4.0 KiB
JavaScript

'use strict';
module.exports.create = function (opts) {
// pass in database url, connection string, filepath,
// or whatever it is you need to get your job done well
// This is our in-memory storage.
// We take it from the outside to make testing the dummy module easier.
var cache = opts.cache || {};
if (!cache.accounts) { cache.accounts = {}; }
if (!cache.certificates) { cache.certificates = {}; }
// Although we could have two collections of keypairs,
// it's also fine to store both types together.
if (!cache.keypairs) { cache.keypairs = {}; }
var store = {};
// any options you need per instance
// (probably okay to leave empty)
store.options = {};
store.accounts = {};
store.certificates = {};
// Whenever a new keypair is used to successfully create an account, we need to save its keypair
store.accounts.setKeypair = function (opts) {
console.log('accounts.setKeypair:', opts);
var id = opts.account.id || opts.email || 'default';
var keypair = opts.keypair;
cache.keypairs[id] = JSON.stringify({
privateKeyPem: keypair.privateKeyPem
, privateKeyJwk: keypair.privateKeyJwk
});
return null; // or Promise.resolve(null);
};
// We need a way to retrieve a prior account's keypair for renewals and additional ACME certificate "orders"
store.accounts.checkKeypair = function (opts) {
console.log('accounts.checkKeypair:', opts);
var id = opts.account.id || opts.email || 'default';
var keyblob = cache.keypairs[id];
if (!keyblob) { return null; }
return JSON.parse(keyblob);
};
// We can optionally implement ACME account storage and retrieval
// (to reduce API calls), but it's really not necessary.
/*
store.accounts.set = function (opts) {
console.log('accounts.set:', opts);
return null;
};
store.accounts.check = function (opts) {
var id = opts.account.id || opts.email || 'default';
console.log('accounts.check:', opts);
return null;
};
*/
// The certificate keypairs must not be the same as any account keypair
store.certificates.setKeypair = function (opts) {
console.log('certificates.setKeypair:', opts);
var id = opts.certificate.kid || opts.certificate.id || opts.subject;
var keypair = opts.keypair;
cache.keypairs[id] = JSON.stringify({
privateKeyPem: keypair.privateKeyPem
, privateKeyJwk: keypair.privateKeyJwk
});
// Note: you can use the "keypairs" package to convert between
// public and private for jwk and pem, as well as convert JWK <-> PEM
return null;
};
// You won't be able to use a certificate without it's private key, gotta save it
store.certificates.checkKeypair = function (opts) {
console.log('certificates.checkKeypair:', opts);
var id = opts.certificate.kid || opts.certificate.id || opts.subject;
var keyblob = cache.keypairs[id];
if (!keyblob) { return null; }
return JSON.parse(keyblob);
};
// And you'll also need to save certificates. You may find the metadata useful to save
// (perhaps to delete expired keys), but the same information can also be redireved from
// the key using the "cert-info" package.
store.certificates.set = function (opts) {
console.log('certificates.set:', opts);
var id = opts.certificate.id || opts.subject;
var pems = opts.pems;
cache.certificates[id] = JSON.stringify({
cert: pems.cert
, chain: pems.chain
, subject: pems.subject
, altnames: pems.altnames
, issuedAt: pems.issuedAt // a.k.a. NotBefore
, expiresAt: pems.expiresAt // a.k.a. NotAfter
});
return null;
};
// This is actually the first thing to be called after approveDomins(),
// but it's easiest to implement last since it's not useful until there
// are certs that can actually be loaded from storage.
store.certificates.check = function (opts) {
console.log('certificates.check:', opts);
var id = opts.certificate.id || opts.subject;
var certblob = cache.certificates[id];
if (!certblob) { return null; }
return JSON.parse(certblob);
};
};