Compare commits
	
		
			10 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7cdb42db7a | |||
|  | 37a7fd55b7 | ||
|  | e96ab294b6 | ||
|  | 7bdf8804a3 | ||
|  | 718e081495 | ||
|  | 258ad19f77 | ||
|  | 03a4db1034 | ||
|  | b0eff828bb | ||
|  | 00157ab870 | ||
|  | a0bda23683 | 
							
								
								
									
										101
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								README.md
									
									
									
									
									
								
							| @ -1,8 +1,99 @@ | |||||||
| # See [`greenlock-store-test`](https://git.rootprojects.org/root/greenlock-store-test.js) | # le-store-SPEC | ||||||
| 
 | 
 | ||||||
| That's the test. | The reference implementation, specification, template, and tests for creating an le-store- strategy. | ||||||
| 
 | 
 | ||||||
| ## Reference implementations | The reference implementation is completely in-memory. | ||||||
| 
 | 
 | ||||||
| * [`greenlock-store-fs`](https://git.rootprojects.org/root/greenlock-store-fs.js) | See [Help Wanted: Database Plugins (for saving certs)](https://github.com/Daplie/node-letsencrypt/issues/39) | ||||||
| * [`greenlock-store-sequelize`](https://git.rootprojects.org/root/greenlock-store-sequelize.js) | 
 | ||||||
|  | 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: { ... } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | |||||||
							
								
								
									
										332
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										332
									
								
								index.js
									
									
									
									
									
								
							| @ -4,342 +4,108 @@ module.exports.create = function (options) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   var crypto = require('crypto'); |  | ||||||
|   var defaults = {}; |   var defaults = {}; | ||||||
|   var memDb = { |  | ||||||
|     accountKeypairs: {} |  | ||||||
|   , certificateKeypairs: {} |  | ||||||
|   , accountIndices: {} |  | ||||||
|   , certIndices: {} |  | ||||||
|   , certificates: {} |  | ||||||
|   , accounts: {} |  | ||||||
|   , accountCerts: {} |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   var accounts = { |   var accounts = { | ||||||
|  | 
 | ||||||
|     // Accounts
 |     // Accounts
 | ||||||
|     setKeypair: function (opts, keypair, cb) { |     setKeypair: function (opts, keypair, cb) { | ||||||
|       // opts.email // non-optional
 |       // opts.email     // optional
 | ||||||
|       // opts.keypair // non-optional
 |       // opts.accountId // optional - same as returned from acounts.set(opts, reg)
 | ||||||
| 
 | 
 | ||||||
|       if (!opts.email) { |  | ||||||
|         cb(new Error("MUST use email when setting Keypair")); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       if (!keypair.privateKeyJwk) { |       // SAVE to db (as PEM and/or JWK) and index each domain in domains to this keypair
 | ||||||
|         cb(new Error("MUST use privateKeyJwk when setting Keypair")); |       // keypair = { privateKeyPem: '...', privateKeyJwk: { ... } }
 | ||||||
|         return; |       cb(null, keypair); | ||||||
|       } |  | ||||||
|       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
 |     // Accounts
 | ||||||
|   , checkKeypair: function (opts, cb) { |   , checkKeypair: function (opts, cb) { | ||||||
|       // opts.email // optional
 |       // opts.email // optional
 | ||||||
|       // opts.accountId // optional
 |       // opts.accountId // optional - same as returned from acounts.set(opts, reg)
 | ||||||
| 
 | 
 | ||||||
|       var keypair = opts.keypair || {}; |  | ||||||
|       var index; |  | ||||||
| 
 | 
 | ||||||
|       if (keypair.publicKeyPem) { |       // check db and return null or keypair object with one
 | ||||||
|         index = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex'); |       // (or both) of privateKeyPem or privateKeyJwk
 | ||||||
|         index = memDb.accountIndices[index]; |       cb(null, { privateKeyPem: '...', privateKeyJwk: {} }); | ||||||
|       } |  | ||||||
|       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
 | ||||||
|  |   , 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
 |     // Accounts
 | ||||||
|   , set: function (opts, reg, cb) { |   , set: function (opts, reg, cb) { | ||||||
|       // opts.email
 |       // opts.email
 | ||||||
|       // reg.keypair
 |       // reg.keypair
 | ||||||
|       // reg.receipt // response from acme server
 |       // reg.receipt // response from acme server
 | ||||||
| 
 | 
 | ||||||
|       var keypair = reg.keypair || opts.keypair || {}; |  | ||||||
|       var accountId; |  | ||||||
|       var index; |  | ||||||
| 
 | 
 | ||||||
|       if (keypair.publicKeyPem) { |       // You must implement a method to deterministically generate 'id'
 | ||||||
|         index = crypto.createHash('sha256').update(keypair.publicKeyPem).digest('hex'); |       // For example, you could do this:
 | ||||||
|         index = memDb.accountIndices[index]; |       // var id = crypto.createHash('sha256').update(reg.keypair.publicKeyPem).digest('hex');
 | ||||||
|       } |       cb(null, { id: '...', email: opts.email, keypair: reg.keypair, receipt: reg.receipt }); | ||||||
|       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 = { |   var certificates = { | ||||||
|  | 
 | ||||||
|     // Certificates
 |     // Certificates
 | ||||||
|     setKeypair: function (opts, keypair, cb) { |     setKeypair: function (opts, keypair, cb) { | ||||||
|       // opts.domains
 |       // opts.domains - this is an array, but you nly need the first (or any) of them
 | ||||||
| 
 |  | ||||||
|       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; |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |       // SAVE to db (as PEM and/or JWK) and index each domain in domains to this keypair
 | ||||||
|       if (!keypair.privateKeyJwk) { |       cb(null, keypair); | ||||||
|         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
 |     // Certificates
 | ||||||
|   , checkKeypair: function (opts, cb) { |   , checkKeypair: function (opts, cb) { | ||||||
|       // opts.domains
 |       // opts.domains - this is an array, but you only need the first (or any) of them
 | ||||||
|       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]); |       // check db and return null or keypair object with one of privateKeyPem or privateKeyJwk
 | ||||||
|  |       cb(null, { privateKeyPem: '...', privateKeyJwk: {} }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     // 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
 |     // Certificates
 | ||||||
|   , check: function (opts, cb) { |   , check: function (opts, cb) { | ||||||
|       // You will be provided one of these (which should be tried in this order)
 |       // You will be provided one of these (which should be tried in this order)
 | ||||||
|       // opts.domains
 |       // opts.domains
 | ||||||
|       // opts.email // optional
 |       // opts.email // optional
 | ||||||
|       // opts.accountId // 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) { |       // return certificate PEMs from db if they exist, otherwise null
 | ||||||
|         accountId = memDb.accountIndices[opts.accountId]; |       // optionally include expiresAt and issuedAt, if they are known exactly
 | ||||||
|       } |       // (otherwise they will be read from the cert itself later)
 | ||||||
|       else if (opts.email) { |       cb(null, { privkey: 'PEM', cert: 'PEM', chain: 'PEM', domains: [], accountId: '...' }); | ||||||
|         accountId = memDb.accountIndices[opts.email]; |  | ||||||
|     } |     } | ||||||
|  |     // 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
 | ||||||
| 
 | 
 | ||||||
|       subjects = memDb.accountCerts[accountId] || []; |       // opts.certs.privkey
 | ||||||
|       cb(null, subjects.map(function (subject) { |       // opts.certs.cert
 | ||||||
|         subject = memDb.certIndices[subject]; |       // opts.certs.chain
 | ||||||
|         return memDb.certificates[subject] || null ; | 
 | ||||||
|       })); | 
 | ||||||
|  |       // SAVE to the database, index the email address, the accountId, and alias the domains
 | ||||||
|  |       cb(null,  { privkey: 'PEM', cert: 'PEM', chain: 'PEM' }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   }; |   }; | ||||||
| @ -348,12 +114,6 @@ module.exports.create = function (options) { | |||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     getOptions: function () { |     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
 |       // merge options with default settings and then return them
 | ||||||
|       return options; |       return options; | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user