le-store-SPEC.js/index.js

367 lines
9.1 KiB
JavaScript

'use strict';
module.exports.create = function (options) {
var crypto = require('crypto');
var defaults = {};
var memDb = {
accountKeypairs: {}
, certificateKeypairs: {}
, accountIndices: {}
, certIndices: {}
, certificates: {}
, accounts: {}
, accountCerts: {}
};
var accounts = {
// Accounts
setKeypair: function (opts, keypair, cb) {
// opts.email // non-optional
// opts.keypair // non-optional
if (!opts.email) {
cb(new Error("MUST use email when setting Keypair"));
return;
}
if (!keypair.privateKeyJwk) {
cb(new Error("MUST use privateKeyJwk when setting Keypair"));
return;
}
if (!keypair.privateKeyPem) {
cb(new Error("MUST use privateKeyPem when setting Keypair"));
return;
}
if (!keypair.publicKeyPem) {
cb(new Error("MUST use publicKeyPem when setting Keypair"));
return;
}
var accountId = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex');
memDb.accountIndices[accountId] = accountId;
memDb.accountIndices[opts.email] = accountId;
memDb.accountKeypairs[accountId] = keypair;
/*
{
id: accountId
// TODO nix accountId
, accountId: accountId
, email: opts.email
, keypair: keypair
};
*/
cb(null, memDb.accountKeypairs[accountId]);
}
// Accounts
, checkKeypair: function (opts, cb) {
// opts.email // optional
// opts.accountId // optional
var keypair = opts.keypair || {};
var index;
if (keypair.publicKeyPem) {
index = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex');
index = memDb.accountIndices[index];
}
else if (keypair.publicKeyJwk) {
// TODO RSA.exportPublicPem(keypair);
cb(new Error("id from publicKeyJwk not yet implemented"));
return;
}
else if (opts.email) {
index = memDb.accountIndices[opts.email];
}
else {
cb(new Error("MUST supply email or keypair.publicKeyPem or keypair.publicKeyJwk"));
return;
}
cb(null, memDb.accountKeypairs[index] || null);
}
// Accounts
, set: function (opts, reg, cb) {
// opts.email
// reg.keypair
// reg.receipt // response from acme server
var keypair = reg.keypair || opts.keypair || {};
var accountId;
var index;
if (keypair.publicKeyPem) {
index = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex');
index = memDb.accountIndices[index];
}
else if (keypair.publicKeyJwk) {
// TODO RSA.exportPublicPem(keypair);
cb(new Error("id from publicKeyJwk not yet implemented"));
return;
}
else if (opts.email) {
index = memDb.accountIndices[opts.email];
}
else {
cb(new Error("MUST supply email or keypair.publicKeyPem or keypair.publicKeyJwk"));
return;
}
accountId = memDb.accountIndices[index];
if (!accountId) {
cb(new Error("keypair was not previously set with email and keypair.publicKeyPem"));
return;
}
memDb.accounts[accountId] = {
id: accountId
// TODO nix accountId
, accountId: accountId
, email: opts.email
, keypair: keypair
, agreeTos: opts.agreeTos || reg.agreeTos
//, receipt: reg.receipt || opts.receipt
};
Object.keys(reg).forEach(function (key) {
memDb.accounts[accountId][key] = reg[key];
});
cb(null, memDb.accounts[accountId]);
}
// Accounts
, check: function (opts, cb) {
// opts.email // optional
// opts.accountId // optional
// opts.domains // optional
var keypair = opts.keypair || {};
var index;
var accountId;
var account;
if (opts.accountId) {
index = memDb.accountIndices[opts.accountId];
}
else if (keypair.publicKeyPem) {
index = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex');
index = memDb.accountIndices[index];
}
else if (keypair.publicKeyJwk) {
// TODO RSA.exportPublicPem(keypair);
cb(new Error("id from publicKeyJwk not yet implemented"));
return;
}
else if (opts.email) {
index = memDb.accountIndices[opts.email];
}
else if (opts.domains && opts.domains[0]) {
index = memDb.accountIndices[opts.domains[0]];
}
else {
console.error(opts);
cb(new Error("MUST supply email or keypair.publicKeyPem or keypair.publicKeyJwk"));
return;
}
accountId = memDb.accountIndices[index];
if (!accountId) {
cb(null, null);
return;
}
account = JSON.parse(JSON.stringify(memDb.accounts[accountId] || null));
account.keypair = memDb.accountKeypairs[accountId] || null;
cb(null, account);
}
};
var certificates = {
// Certificates
setKeypair: function (opts, keypair, cb) {
// opts.domains
if (!opts.domains || !opts.domains.length) {
cb(new Error("MUST use domains when setting Keypair"));
return;
}
if (!opts.email) {
cb(new Error("MUST use email when setting Keypair"));
return;
}
if (!opts.accountId) {
cb(new Error("MUST use accountId when setting Keypair"));
return;
}
if (!keypair.privateKeyJwk) {
cb(new Error("MUST use privateKeyJwk when setting Keypair"));
return;
}
if (!keypair.privateKeyPem) {
cb(new Error("MUST use privateKeyPem when setting Keypair"));
return;
}
if (!keypair.publicKeyPem) {
cb(new Error("MUST use publicKeyPem when setting Keypair"));
return;
}
var subject = opts.domains[0];
opts.domains.forEach(function (domain) {
memDb.certIndices[domain] = subject;
});
memDb.certKeypairs[subject] = keypair;
/*
{
subject: subject
, keypair: keypair
};
*/
cb(null, memDb.certKeypairs[subject]);
}
// Certificates
, checkKeypair: function (opts, cb) {
// opts.domains
if (!opts.domains || !opts.domains.length) {
cb(new Error("MUST use domains when checking Keypair"));
return;
}
var domain = opts.domains[0];
var subject = memDb.certIndices[domain];
cb(null, memDb.certKeypairs[subject]);
}
// Certificates
, set: function (opts, cb) {
// opts.domains
// opts.email // optional
// opts.accountId // optional
// opts.certs.privkey
// opts.certs.cert
// opts.certs.chain
var index;
var accountId;
var account;
var certs = opts.certs;
var subject = certs.subject || opts.domains[0];
var altnames = certs.altnames || opts.domains;
var accountCerts;
if (opts.accountId) {
index = opts.accountId;
}
else if (opts.email) {
index = opts.email;
}
else {
cb(new Error("MUST supply email or accountId"));
return;
}
accountId = memDb.accountIndices[index];
account = memDb.accounts[accountId];
if (!account) {
cb(new Error("account must exist"));
}
accountId = memDb.accountIndices[index];
if (!accountId) {
cb(new Error("keypair was not previously set with email and keypair.publicKeyPem"));
return;
}
memDb.certIndices[subject] = subject;
altnames.forEach(function (altname) {
memDb.certIndices[altname] = subject;
});
accountCerts = memDb.accountCerts[accountId] || {};
accountCerts[subject] = subject;
memDb.accountCerts[accountId] = accountCerts;
memDb.certificates[subject] = certs;
// SAVE to the database, index the email address, the accountId, and alias the domains
cb(null, certs);
}
// 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
var subject;
var subjects;
var accountId;
if (opts.domains) {
subject = memDb.certIndices[opts.domains[0]];
cb(null, memDb.certificates[subject]);
return;
}
if (opts.accountId) {
accountId = memDb.accountIndices[opts.accountId];
}
else if (opts.email) {
accountId = memDb.accountIndices[opts.email];
}
subjects = memDb.accountCerts[accountId] || [];
cb(null, subjects.map(function (subject) {
subject = memDb.certIndices[subject];
return memDb.certificates[subject] || null ;
}));
}
};
return {
getOptions: function () {
Object.keys(defaults).forEach(function (key) {
if ('undefined' === typeof options[key]) {
options[key] = defaults[key];
}
});
// merge options with default settings and then return them
return options;
}
, accounts: accounts
, certificates: certificates
};
};