updates for greenlock-express
This commit is contained in:
parent
7fc11f7908
commit
7774d0f8b1
30
README.md
30
README.md
|
@ -65,12 +65,23 @@ var gl = Greenlock.create({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| maintainerEmail | the developer contact for critical bug and security notifications |
|
| servername | the default servername to use for non-sni requests (many IoT clients) |
|
||||||
| maintainerUpdates | (default: false) receive occasional non-critical notifications |
|
| maintainerEmail | the developer contact for critical bug and security notifications |
|
||||||
| subscriberEmail | the contact who agrees to the Let's Encrypt Subscriber Agreement and the Greenlock Terms of Service<br>this contact receives renewal failure notifications |
|
| maintainerUpdates | (default: false) receive occasional non-critical notifications |
|
||||||
| agreeToTerms | (default: false) either 'true' or a function that presents the Terms of Service and returns it once accepted |
|
| maintainerPackage | if you publish your package for others to use, `require('./package.json').name` here |
|
||||||
|
| maintainerPackageVersion | if you publish your package for others to use, `require('./package.json').version` here |
|
||||||
|
| subscriberEmail | the contact who agrees to the Let's Encrypt Subscriber Agreement and the Greenlock Terms of Service<br>this contact receives renewal failure notifications |
|
||||||
|
| agreeToTerms | (default: false) either 'true' or a function that presents the Terms of Service and returns it once accepted |
|
||||||
|
| store | override the default storage module |
|
||||||
|
| store.module | the name of your storage module |
|
||||||
|
| store.xxxx | options specific to your storage module |
|
||||||
|
| challenges['http-01'] | provide an http-01 challenge module |
|
||||||
|
| challenges['dns-01'] | provide a dns-01 challenge module |
|
||||||
|
| challenges['tls-alpn-01'] | provide a tls-alpn-01 challenge module |
|
||||||
|
| challenges[type].module | the name of your challenge module |
|
||||||
|
| challenges[type].xxxx | module-specific options |
|
||||||
|
|
||||||
### Add Approved Domains
|
### Add Approved Domains
|
||||||
|
|
||||||
|
@ -130,15 +141,18 @@ TODO
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Node.js</summary>
|
<summary>Node.js</summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install --save @root/greenlock
|
npm install --save @root/greenlock
|
||||||
|
npm install --save greenlock-manager-fs
|
||||||
|
npm install --save greenlock-store-fs
|
||||||
|
npm install --save acme-http-01-standalone
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
71
accounts.js
71
accounts.js
|
@ -6,8 +6,11 @@ var E = require('./errors.js');
|
||||||
|
|
||||||
var pending = {};
|
var pending = {};
|
||||||
|
|
||||||
A._getOrCreate = function(greenlock, db, acme, args) {
|
A._getOrCreate = function(gnlck, mconf, db, acme, args) {
|
||||||
var email = args.subscriberEmail || greenlock._defaults.subscriberEmail;
|
var email =
|
||||||
|
args.subscriberEmail ||
|
||||||
|
mconf.subscriberEmail ||
|
||||||
|
gnlck._defaults.subscriberEmail;
|
||||||
|
|
||||||
if (!email) {
|
if (!email) {
|
||||||
throw E.NO_SUBSCRIBER('get account', args.subject);
|
throw E.NO_SUBSCRIBER('get account', args.subject);
|
||||||
|
@ -23,7 +26,14 @@ A._getOrCreate = function(greenlock, db, acme, args) {
|
||||||
return pending[email];
|
return pending[email];
|
||||||
}
|
}
|
||||||
|
|
||||||
pending[email] = A._rawGetOrCreate(greenlock, db, acme, args, email)
|
pending[email] = A._rawGetOrCreate(
|
||||||
|
gnlck,
|
||||||
|
mconf,
|
||||||
|
db,
|
||||||
|
acme,
|
||||||
|
args,
|
||||||
|
email
|
||||||
|
)
|
||||||
.catch(function(e) {
|
.catch(function(e) {
|
||||||
delete pending[email];
|
delete pending[email];
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -38,32 +48,37 @@ A._getOrCreate = function(greenlock, db, acme, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// What we really need out of this is the private key and the ACME "key" id
|
// What we really need out of this is the private key and the ACME "key" id
|
||||||
A._rawGetOrCreate = function(greenlock, db, acme, args, email) {
|
A._rawGetOrCreate = function(gnlck, mconf, db, acme, args, email) {
|
||||||
var p;
|
var p;
|
||||||
if (db.check) {
|
if (db.check) {
|
||||||
p = A._checkStore(greenlock, db, acme, args, email);
|
p = A._checkStore(gnlck, mconf, db, acme, args, email);
|
||||||
} else {
|
} else {
|
||||||
p = Promise.resolve(null);
|
p = Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.then(function(fullAccount) {
|
return p.then(function(fullAccount) {
|
||||||
if (!fullAccount) {
|
if (!fullAccount) {
|
||||||
return A._newAccount(greenlock, db, acme, args, email, null);
|
return A._newAccount(gnlck, mconf, db, acme, args, email, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullAccount.keypair && fullAccount.key && fullAccount.key.kid) {
|
if (fullAccount.keypair && fullAccount.key && fullAccount.key.kid) {
|
||||||
return fullAccount;
|
return fullAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return A._newAccount(greenlock, db, acme, args, email, fullAccount);
|
return A._newAccount(gnlck, mconf, db, acme, args, email, fullAccount);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) {
|
||||||
var keyType = args.accountKeyType || greenlock._defaults.accountKeyType;
|
var keyType =
|
||||||
|
args.accountKeyType ||
|
||||||
|
mconf.accountKeyType ||
|
||||||
|
gnlck._defaults.accountKeyType;
|
||||||
var query = {
|
var query = {
|
||||||
subject: args.subject,
|
subject: args.subject,
|
||||||
email: email,
|
email: email,
|
||||||
|
subscriberEmail: email,
|
||||||
|
customerEmail: args.customerEmail,
|
||||||
account: fullAccount || {}
|
account: fullAccount || {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,8 +88,10 @@ A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
||||||
var accReg = {
|
var accReg = {
|
||||||
subscriberEmail: email,
|
subscriberEmail: email,
|
||||||
agreeToTerms:
|
agreeToTerms:
|
||||||
args.agreeToTerms || greenlock._defaults.agreeToTerms,
|
args.agreeToTerms ||
|
||||||
accountKeypair: keypair,
|
mconf.agreeToTerms ||
|
||||||
|
gnlck._defaults.agreeToTerms,
|
||||||
|
accountKey: keypair.privateKeyJwk || keypair.private,
|
||||||
debug: args.debug
|
debug: args.debug
|
||||||
};
|
};
|
||||||
return acme.accounts.create(accReg).then(function(receipt) {
|
return acme.accounts.create(accReg).then(function(receipt) {
|
||||||
|
@ -86,7 +103,9 @@ A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
||||||
receipt &&
|
receipt &&
|
||||||
receipt.key &&
|
receipt.key &&
|
||||||
(receipt.key.kid || receipt.kid),
|
(receipt.key.kid || receipt.kid),
|
||||||
email: args.email
|
email: args.email,
|
||||||
|
subscriberEmail: email,
|
||||||
|
customerEmail: args.customerEmail
|
||||||
};
|
};
|
||||||
|
|
||||||
var keyP;
|
var keyP;
|
||||||
|
@ -95,6 +114,13 @@ A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
||||||
} else {
|
} else {
|
||||||
query.keypair = keypair;
|
query.keypair = keypair;
|
||||||
query.receipt = receipt;
|
query.receipt = receipt;
|
||||||
|
query.directoryUrl = gnlck._defaults.directoryUrl;
|
||||||
|
/*
|
||||||
|
query.server = gnlck._defaults.directoryUrl.replace(
|
||||||
|
/^https?:\/\//i,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
*/
|
||||||
keyP = db.setKeypair(query, keypair);
|
keyP = db.setKeypair(query, keypair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +135,16 @@ A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
||||||
{
|
{
|
||||||
// id to be set by Store
|
// id to be set by Store
|
||||||
email: email,
|
email: email,
|
||||||
agreeTos: true
|
subscriberEmail: email,
|
||||||
|
customerEmail: args.customerEmail,
|
||||||
|
agreeTos: true,
|
||||||
|
directoryUrl: gnlck._defaults.directoryUrl
|
||||||
|
/*
|
||||||
|
server: gnlck._defaults.directoryUrl.replace(
|
||||||
|
/^https?:\/\//i,
|
||||||
|
''
|
||||||
|
)
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
reg
|
reg
|
||||||
);
|
);
|
||||||
|
@ -137,7 +172,7 @@ A._newAccount = function(greenlock, db, acme, args, email, fullAccount) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
A._checkStore = function(greenlock, db, acme, args, email) {
|
A._checkStore = function(gnlck, mconf, db, acme, args, email) {
|
||||||
if ((args.domain || args.domains) && !args.subject) {
|
if ((args.domain || args.domains) && !args.subject) {
|
||||||
console.warn("use 'subject' instead of 'domain'");
|
console.warn("use 'subject' instead of 'domain'");
|
||||||
args.subject = args.domain;
|
args.subject = args.domain;
|
||||||
|
@ -148,12 +183,12 @@ A._checkStore = function(greenlock, db, acme, args, email) {
|
||||||
account = {};
|
account = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.accountKeypair) {
|
if (args.accountKey) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'rather than passing accountKeypair, put it directly into your account key store'
|
'rather than passing accountKey, put it directly into your account key store'
|
||||||
);
|
);
|
||||||
// TODO we probably don't need this
|
// TODO we probably don't need this
|
||||||
return U._importKeypair(args.accountKeypair);
|
return U._importKeypair(args.accountKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!db.check) {
|
if (!db.check) {
|
||||||
|
@ -165,6 +200,8 @@ A._checkStore = function(greenlock, db, acme, args, email) {
|
||||||
//keypair: undefined,
|
//keypair: undefined,
|
||||||
//receipt: undefined,
|
//receipt: undefined,
|
||||||
email: email,
|
email: email,
|
||||||
|
subscriberEmail: email,
|
||||||
|
customerEmail: args.customerEmail || mconf.customerEmail,
|
||||||
account: account
|
account: account
|
||||||
})
|
})
|
||||||
.then(function(fullAccount) {
|
.then(function(fullAccount) {
|
||||||
|
|
147
certificates.js
147
certificates.js
|
@ -4,13 +4,27 @@ var C = module.exports;
|
||||||
var U = require('./utils.js');
|
var U = require('./utils.js');
|
||||||
var CSR = require('@root/csr');
|
var CSR = require('@root/csr');
|
||||||
var Enc = require('@root/encoding');
|
var Enc = require('@root/encoding');
|
||||||
|
var Keypairs = require('@root/keypairs');
|
||||||
|
|
||||||
var pending = {};
|
var pending = {};
|
||||||
var rawPending = {};
|
var rawPending = {};
|
||||||
|
|
||||||
|
// What the abbreviations mean
|
||||||
|
//
|
||||||
|
// gnlkc => greenlock
|
||||||
|
// mconf => manager config
|
||||||
|
// db => greenlock store instance
|
||||||
|
// acme => instance of ACME.js
|
||||||
|
// chs => instances of challenges
|
||||||
|
// acc => account
|
||||||
|
// args => site / extra options
|
||||||
|
|
||||||
// Certificates
|
// Certificates
|
||||||
C._getOrOrder = function(greenlock, db, acme, challenges, account, args) {
|
C._getOrOrder = function(gnlck, mconf, db, acme, chs, acc, args) {
|
||||||
var email = args.subscriberEmail || greenlock._defaults.subscriberEmail;
|
var email =
|
||||||
|
args.subscriberEmail ||
|
||||||
|
mconf.subscriberEmail ||
|
||||||
|
gnlck._defaults.subscriberEmail;
|
||||||
|
|
||||||
var id = args.altnames.join(' ');
|
var id = args.altnames.join(' ');
|
||||||
if (pending[id]) {
|
if (pending[id]) {
|
||||||
|
@ -18,11 +32,12 @@ C._getOrOrder = function(greenlock, db, acme, challenges, account, args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pending[id] = C._rawGetOrOrder(
|
pending[id] = C._rawGetOrOrder(
|
||||||
greenlock,
|
gnlck,
|
||||||
|
mconf,
|
||||||
db,
|
db,
|
||||||
acme,
|
acme,
|
||||||
challenges,
|
chs,
|
||||||
account,
|
acc,
|
||||||
email,
|
email,
|
||||||
args
|
args
|
||||||
)
|
)
|
||||||
|
@ -39,33 +54,26 @@ C._getOrOrder = function(greenlock, db, acme, challenges, account, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Certificates
|
// Certificates
|
||||||
C._rawGetOrOrder = function(
|
C._rawGetOrOrder = function(gnlck, mconf, db, acme, chs, acc, email, args) {
|
||||||
greenlock,
|
return C._check(gnlck, mconf, db, args).then(function(pems) {
|
||||||
db,
|
|
||||||
acme,
|
|
||||||
challenges,
|
|
||||||
account,
|
|
||||||
email,
|
|
||||||
args
|
|
||||||
) {
|
|
||||||
return C._check(db, args).then(function(pems) {
|
|
||||||
// No pems? get some!
|
// No pems? get some!
|
||||||
if (!pems) {
|
if (!pems) {
|
||||||
return C._rawOrder(
|
return C._rawOrder(
|
||||||
greenlock,
|
gnlck,
|
||||||
|
mconf,
|
||||||
db,
|
db,
|
||||||
acme,
|
acme,
|
||||||
challenges,
|
chs,
|
||||||
account,
|
acc,
|
||||||
email,
|
email,
|
||||||
args
|
args
|
||||||
).then(function(newPems) {
|
).then(function(newPems) {
|
||||||
// do not wait on notify
|
// do not wait on notify
|
||||||
greenlock._notify('cert_issue', {
|
gnlck._notify('cert_issue', {
|
||||||
options: args,
|
options: args,
|
||||||
subject: args.subject,
|
subject: args.subject,
|
||||||
altnames: args.altnames,
|
altnames: args.altnames,
|
||||||
account: account,
|
account: acc,
|
||||||
email: email,
|
email: email,
|
||||||
pems: newPems
|
pems: newPems
|
||||||
});
|
});
|
||||||
|
@ -74,7 +82,7 @@ C._rawGetOrOrder = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nice and fresh? We're done!
|
// Nice and fresh? We're done!
|
||||||
if (!C._isStale(greenlock, args, pems)) {
|
if (!C._isStale(gnlck, mconf, args, pems)) {
|
||||||
// return existing unexpired (although potentially stale) certificates when available
|
// return existing unexpired (although potentially stale) certificates when available
|
||||||
// there will be an additional .renewing property if the certs are being asynchronously renewed
|
// there will be an additional .renewing property if the certs are being asynchronously renewed
|
||||||
//pems._type = 'current';
|
//pems._type = 'current';
|
||||||
|
@ -82,26 +90,20 @@ C._rawGetOrOrder = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting stale? Let's renew to freshen up!
|
// Getting stale? Let's renew to freshen up!
|
||||||
var p = C._rawOrder(
|
var p = C._rawOrder(gnlck, mconf, db, acme, chs, acc, email, args).then(
|
||||||
greenlock,
|
function(renewedPems) {
|
||||||
db,
|
// do not wait on notify
|
||||||
acme,
|
gnlck._notify('cert_renewal', {
|
||||||
challenges,
|
options: args,
|
||||||
account,
|
subject: args.subject,
|
||||||
email,
|
altnames: args.altnames,
|
||||||
args
|
account: acc,
|
||||||
).then(function(renewedPems) {
|
email: email,
|
||||||
// do not wait on notify
|
pems: renewedPems
|
||||||
greenlock._notify('cert_renewal', {
|
});
|
||||||
options: args,
|
return renewedPems;
|
||||||
subject: args.subject,
|
}
|
||||||
altnames: args.altnames,
|
);
|
||||||
account: account,
|
|
||||||
email: email,
|
|
||||||
pems: renewedPems
|
|
||||||
});
|
|
||||||
return renewedPems;
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO what should this be?
|
// TODO what should this be?
|
||||||
if (args.waitForRenewal) {
|
if (args.waitForRenewal) {
|
||||||
|
@ -114,7 +116,7 @@ C._rawGetOrOrder = function(
|
||||||
|
|
||||||
// we have another promise here because it the optional renewal
|
// we have another promise here because it the optional renewal
|
||||||
// may resolve in a different stack than the returned pems
|
// may resolve in a different stack than the returned pems
|
||||||
C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
C._rawOrder = function(gnlck, mconf, db, acme, chs, acc, email, args) {
|
||||||
var id = args.altnames
|
var id = args.altnames
|
||||||
.slice(0)
|
.slice(0)
|
||||||
.sort()
|
.sort()
|
||||||
|
@ -123,10 +125,17 @@ C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
||||||
return rawPending[id];
|
return rawPending[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyType = args.serverKeyType || greenlock._defaults.serverKeyType;
|
var keyType =
|
||||||
|
args.serverKeyType ||
|
||||||
|
mconf.serverKeyType ||
|
||||||
|
gnlck._defaults.serverKeyType;
|
||||||
var query = {
|
var query = {
|
||||||
subject: args.subject,
|
subject: args.subject,
|
||||||
certificate: args.certificate || {}
|
certificate: args.certificate || {},
|
||||||
|
directoryUrl:
|
||||||
|
args.directoryUrl ||
|
||||||
|
mconf.directoryUrl ||
|
||||||
|
gnlck._defaults.directoryUrl
|
||||||
};
|
};
|
||||||
rawPending[id] = U._getOrCreateKeypair(db, args.subject, query, keyType)
|
rawPending[id] = U._getOrCreateKeypair(db, args.subject, query, keyType)
|
||||||
.then(function(kresult) {
|
.then(function(kresult) {
|
||||||
|
@ -134,7 +143,7 @@ C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
||||||
var domains = args.altnames.slice(0);
|
var domains = args.altnames.slice(0);
|
||||||
|
|
||||||
return CSR.csr({
|
return CSR.csr({
|
||||||
jwk: serverKeypair.privateKeyJwk,
|
jwk: serverKeypair.privateKeyJwk || serverKeypair.private,
|
||||||
domains: domains,
|
domains: domains,
|
||||||
encoding: 'der'
|
encoding: 'der'
|
||||||
})
|
})
|
||||||
|
@ -144,21 +153,22 @@ C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
||||||
})
|
})
|
||||||
.then(function(csr) {
|
.then(function(csr) {
|
||||||
function notify() {
|
function notify() {
|
||||||
greenlock._notify('challenge_status', {
|
gnlck._notify('challenge_status', {
|
||||||
options: args,
|
options: args,
|
||||||
subject: args.subject,
|
subject: args.subject,
|
||||||
altnames: args.altnames,
|
altnames: args.altnames,
|
||||||
account: account,
|
account: acc,
|
||||||
email: email
|
email: email
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var certReq = {
|
var certReq = {
|
||||||
debug: args.debug || greenlock._defaults.debug,
|
debug: args.debug || gnlck._defaults.debug,
|
||||||
|
|
||||||
challenges: challenges,
|
challenges: chs,
|
||||||
account: account, // only used if accounts.key.kid exists
|
account: acc, // only used if accounts.key.kid exists
|
||||||
accountKeypair: account.keypair,
|
accountKey:
|
||||||
keypair: account.keypair, // TODO
|
acc.keypair.privateKeyJwk || acc.keypair.private,
|
||||||
|
keypair: acc.keypair, // TODO
|
||||||
csr: csr,
|
csr: csr,
|
||||||
domains: domains, // because ACME.js v3 uses `domains` still, actually
|
domains: domains, // because ACME.js v3 uses `domains` still, actually
|
||||||
onChallengeStatus: notify,
|
onChallengeStatus: notify,
|
||||||
|
@ -190,7 +200,7 @@ C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
||||||
return db.set(query);
|
return db.set(query);
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return C._check(db, args);
|
return C._check(gnlck, mconf, db, args);
|
||||||
})
|
})
|
||||||
.then(function(bundle) {
|
.then(function(bundle) {
|
||||||
// TODO notify Manager
|
// TODO notify Manager
|
||||||
|
@ -207,14 +217,17 @@ C._rawOrder = function(greenlock, db, acme, challenges, account, email, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// returns pems, if they exist
|
// returns pems, if they exist
|
||||||
C._check = function(db, args) {
|
C._check = function(gnlck, mconf, db, args) {
|
||||||
var query = {
|
var query = {
|
||||||
subject: args.subject,
|
subject: args.subject,
|
||||||
// may contain certificate.id
|
// may contain certificate.id
|
||||||
certificate: args.certificate
|
certificate: args.certificate,
|
||||||
|
directoryUrl:
|
||||||
|
args.directoryUrl ||
|
||||||
|
mconf.directoryUrl ||
|
||||||
|
gnlck._defaults.directoryUrl
|
||||||
};
|
};
|
||||||
return db.check(query).then(function(pems) {
|
return db.check(query).then(function(pems) {
|
||||||
console.log('[debug] has pems? (yes)', pems);
|
|
||||||
if (!pems) {
|
if (!pems) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -235,9 +248,13 @@ C._check = function(db, args) {
|
||||||
|
|
||||||
return U._getKeypair(db, args.subject, query)
|
return U._getKeypair(db, args.subject, query)
|
||||||
.then(function(keypair) {
|
.then(function(keypair) {
|
||||||
console.log('[debug get keypair]', Object.keys(keypair));
|
return Keypairs.export({
|
||||||
pems.privkey = keypair.privateKeyPem;
|
jwk: keypair.privateKeyJwk || keypair.private,
|
||||||
return pems;
|
encoding: 'pem'
|
||||||
|
}).then(function(pem) {
|
||||||
|
pems.privkey = pem;
|
||||||
|
return pems;
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(function() {
|
.catch(function() {
|
||||||
// TODO report error, but continue the process as with no cert
|
// TODO report error, but continue the process as with no cert
|
||||||
|
@ -247,12 +264,12 @@ C._check = function(db, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Certificates
|
// Certificates
|
||||||
C._isStale = function(greenlock, args, pems) {
|
C._isStale = function(gnlck, mconf, args, pems) {
|
||||||
if (args.duplicate) {
|
if (args.duplicate) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var renewAt = C._renewableAt(greenlock, args, pems);
|
var renewAt = C._renewableAt(gnlck, mconf, args, pems);
|
||||||
|
|
||||||
if (Date.now() >= renewAt) {
|
if (Date.now() >= renewAt) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -261,12 +278,16 @@ C._isStale = function(greenlock, args, pems) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
C._renewableAt = function(greenlock, args, pems) {
|
C._renewableAt = function(gnlck, mconf, args, pems) {
|
||||||
if (args.renewAt) {
|
if (args.renewAt) {
|
||||||
return args.renewAt;
|
return args.renewAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var renewOffset = args.renewOffset || greenlock._defaults.renewOffset || 0;
|
var renewOffset =
|
||||||
|
args.renewOffset ||
|
||||||
|
mconf.renewOffset ||
|
||||||
|
gnlck._defaults.renewOffset ||
|
||||||
|
0;
|
||||||
var week = 1000 * 60 * 60 * 24 * 6;
|
var week = 1000 * 60 * 60 * 24 * 6;
|
||||||
if (!args.force && Math.abs(renewOffset) < week) {
|
if (!args.force && Math.abs(renewOffset) < week) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
65
greenlock.js
65
greenlock.js
|
@ -65,10 +65,37 @@ G.create = function(gconf) {
|
||||||
var defaults = G._defaults(gconf);
|
var defaults = G._defaults(gconf);
|
||||||
|
|
||||||
greenlock.manager = Manager.create(defaults);
|
greenlock.manager = Manager.create(defaults);
|
||||||
|
greenlock._init = function() {
|
||||||
|
var p;
|
||||||
|
greenlock._init = function() {
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
p = greenlock.manager.config().then(function(conf) {
|
||||||
|
var changed = false;
|
||||||
|
if (!conf.challenges) {
|
||||||
|
changed = true;
|
||||||
|
conf.challenges = defaults.challenges;
|
||||||
|
}
|
||||||
|
if (!conf.store) {
|
||||||
|
changed = true;
|
||||||
|
conf.store = defaults.store;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
return greenlock.manager.config(conf);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
greenlock._init();
|
||||||
|
|
||||||
// The goal here is to reduce boilerplate, such as error checking
|
// The goal here is to reduce boilerplate, such as error checking
|
||||||
// and duration parsing, that a manager must implement
|
// and duration parsing, that a manager must implement
|
||||||
greenlock.add = function(args) {
|
greenlock.add = function(args) {
|
||||||
|
return greenlock._init().then(function() {
|
||||||
|
return greenlock._add(args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
greenlock._add = function(args) {
|
||||||
return Promise.resolve().then(function() {
|
return Promise.resolve().then(function() {
|
||||||
// durations
|
// durations
|
||||||
if (args.renewOffset) {
|
if (args.renewOffset) {
|
||||||
|
@ -128,23 +155,26 @@ G.create = function(gconf) {
|
||||||
|
|
||||||
greenlock._notify = function(ev, params) {
|
greenlock._notify = function(ev, params) {
|
||||||
var mng = greenlock.manager;
|
var mng = greenlock.manager;
|
||||||
if (mng.notif || greenlock._defaults.notify) {
|
if (mng.notify || greenlock._defaults.notify) {
|
||||||
try {
|
try {
|
||||||
var p = (mng.notify || greenlock._defaults.notify)(ev, params);
|
var p = (mng.notify || greenlock._defaults.notify)(ev, params);
|
||||||
if (p && p.catch) {
|
if (p && p.catch) {
|
||||||
p.catch(function(e) {
|
p.catch(function(e) {
|
||||||
console.error("Error on event '" + ev + "':");
|
console.error(
|
||||||
|
"Promise Rejection on event '" + ev + "':"
|
||||||
|
);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error on event '" + ev + "':");
|
console.error("Thrown Exception on event '" + ev + "':");
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (/error/i.test(ev)) {
|
if (/error/i.test(ev)) {
|
||||||
console.error("Error event '" + ev + "':");
|
console.error("Error event '" + ev + "':");
|
||||||
console.error(params);
|
console.error(params);
|
||||||
|
console.error(params.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -180,6 +210,11 @@ G.create = function(gconf) {
|
||||||
|
|
||||||
// needs to get info about the renewal, such as which store and challenge(s) to use
|
// needs to get info about the renewal, such as which store and challenge(s) to use
|
||||||
greenlock.renew = function(args) {
|
greenlock.renew = function(args) {
|
||||||
|
return greenlock.manager.config().then(function(mconf) {
|
||||||
|
return greenlock._renew(mconf, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
greenlock._renew = function(mconf, args) {
|
||||||
if (!args) {
|
if (!args) {
|
||||||
args = {};
|
args = {};
|
||||||
}
|
}
|
||||||
|
@ -207,7 +242,7 @@ G.create = function(gconf) {
|
||||||
function next() {
|
function next() {
|
||||||
var site = sites.shift();
|
var site = sites.shift();
|
||||||
if (!site) {
|
if (!site) {
|
||||||
return null;
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var order = {
|
var order = {
|
||||||
|
@ -216,7 +251,7 @@ G.create = function(gconf) {
|
||||||
renewedOrFailed.push(order);
|
renewedOrFailed.push(order);
|
||||||
// TODO merge args + result?
|
// TODO merge args + result?
|
||||||
return greenlock
|
return greenlock
|
||||||
.order(site)
|
._order(mconf, site)
|
||||||
.then(function(pems) {
|
.then(function(pems) {
|
||||||
order.pems = pems;
|
order.pems = pems;
|
||||||
})
|
})
|
||||||
|
@ -237,7 +272,10 @@ G.create = function(gconf) {
|
||||||
|
|
||||||
greenlock._acme = function(args) {
|
greenlock._acme = function(args) {
|
||||||
var acme = ACME.create({
|
var acme = ACME.create({
|
||||||
debug: args.debug
|
maintainerEmail: greenlock._defaults.maintainerEmail,
|
||||||
|
packageAgent: greenlock._defaults.packageAgent,
|
||||||
|
notify: greenlock._notify,
|
||||||
|
debug: greenlock._defaults.debug || args.debug
|
||||||
});
|
});
|
||||||
var dirUrl = args.directoryUrl || greenlock._defaults.directoryUrl;
|
var dirUrl = args.directoryUrl || greenlock._defaults.directoryUrl;
|
||||||
|
|
||||||
|
@ -266,6 +304,13 @@ G.create = function(gconf) {
|
||||||
};
|
};
|
||||||
|
|
||||||
greenlock.order = function(args) {
|
greenlock.order = function(args) {
|
||||||
|
return greenlock._init().then(function() {
|
||||||
|
return greenlock.manager.config().then(function(mconf) {
|
||||||
|
return greenlock._order(mconf, args);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
greenlock._order = function(mconf, args) {
|
||||||
return greenlock._acme(args).then(function(acme) {
|
return greenlock._acme(args).then(function(acme) {
|
||||||
var storeConf = args.store || greenlock._defaults.store;
|
var storeConf = args.store || greenlock._defaults.store;
|
||||||
return P._load(storeConf.module).then(function(plugin) {
|
return P._load(storeConf.module).then(function(plugin) {
|
||||||
|
@ -276,17 +321,18 @@ G.create = function(gconf) {
|
||||||
|
|
||||||
return A._getOrCreate(
|
return A._getOrCreate(
|
||||||
greenlock,
|
greenlock,
|
||||||
|
mconf,
|
||||||
store.accounts,
|
store.accounts,
|
||||||
acme,
|
acme,
|
||||||
args
|
args
|
||||||
).then(function(account) {
|
).then(function(account) {
|
||||||
var challengeConfs =
|
var challengeConfs =
|
||||||
args.challenges || greenlock._defaults.challenges;
|
args.challenges ||
|
||||||
console.log('[debug] challenge confs', challengeConfs);
|
mconf.challenges ||
|
||||||
|
greenlock._defaults.challenges;
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
Object.keys(challengeConfs).map(function(typ01) {
|
Object.keys(challengeConfs).map(function(typ01) {
|
||||||
var chConf = challengeConfs[typ01];
|
var chConf = challengeConfs[typ01];
|
||||||
console.log('[debug] module', chConf);
|
|
||||||
return P._load(chConf.module).then(function(
|
return P._load(chConf.module).then(function(
|
||||||
plugin
|
plugin
|
||||||
) {
|
) {
|
||||||
|
@ -305,6 +351,7 @@ G.create = function(gconf) {
|
||||||
});
|
});
|
||||||
return C._getOrOrder(
|
return C._getOrOrder(
|
||||||
greenlock,
|
greenlock,
|
||||||
|
mconf,
|
||||||
store.certificates,
|
store.certificates,
|
||||||
acme,
|
acme,
|
||||||
challenges,
|
challenges,
|
||||||
|
|
|
@ -5,38 +5,15 @@
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@root/acme": {
|
"@root/acme": {
|
||||||
"version": "3.0.0-wip.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@root/acme/-/acme-3.0.0-wip.3.tgz",
|
"resolved": "https://registry.npmjs.org/@root/acme/-/acme-3.0.5.tgz",
|
||||||
"integrity": "sha512-7Fq9FuO0WQgKPgyYmKHst71EbIqH764A3j6vF1aKemgWXXq2Wqy8G+2SJwt3/MSXhQ7X+qLmWRLLJ7U4Zlygsg==",
|
"integrity": "sha512-qtAE7E0yPlajlhiojT6Fz8PV0BIvq+eNKY1mbG3zFf+idppYn66R7nrn17mvrXsQaRhabZ/C+M9MAk4Xt8UBBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@root/csr": "^0.8.1",
|
|
||||||
"@root/encoding": "^1.0.1",
|
"@root/encoding": "^1.0.1",
|
||||||
"@root/keypairs": "^0.9.0",
|
"@root/keypairs": "^0.9.0",
|
||||||
"@root/pem": "^1.0.4",
|
"@root/pem": "^1.0.4",
|
||||||
"@root/request": "^1.3.11",
|
"@root/request": "^1.3.11",
|
||||||
"@root/x509": "^0.7.2"
|
"@root/x509": "^0.7.2"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@root/csr": {
|
|
||||||
"version": "0.8.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@root/csr/-/csr-0.8.1.tgz",
|
|
||||||
"integrity": "sha512-hKl0VuE549TK6SnS2Yn9nRvKbFZXn/oAg+dZJU/tlKl/f/0yRXeuUzf8akg3JjtJq+9E592zDqeXZ7yyrg8fSQ==",
|
|
||||||
"requires": {
|
|
||||||
"@root/asn1": "^1.0.0",
|
|
||||||
"@root/pem": "^1.0.4",
|
|
||||||
"@root/x509": "^0.7.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@root/keypairs": {
|
|
||||||
"version": "0.9.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@root/keypairs/-/keypairs-0.9.0.tgz",
|
|
||||||
"integrity": "sha512-NXE2L9Gv7r3iC4kB/gTPZE1vO9Ox/p14zDzAJ5cGpTpytbWOlWF7QoHSJbtVX4H7mRG/Hp7HR3jWdWdb2xaaXg==",
|
|
||||||
"requires": {
|
|
||||||
"@root/encoding": "^1.0.1",
|
|
||||||
"@root/pem": "^1.0.4",
|
|
||||||
"@root/x509": "^0.7.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@root/asn1": {
|
"@root/asn1": {
|
||||||
|
@ -117,6 +94,11 @@
|
||||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
|
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"greenlock-manager-fs": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/greenlock-manager-fs/-/greenlock-manager-fs-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-tEt9npVDDR27FThVsh2PizkNPLS9V60ljbxpYnLRUkv5LoMvOTm4hHfNCEanOIL5PY8rfilh96+8v519xeYKQg=="
|
||||||
|
},
|
||||||
"greenlock-store-fs": {
|
"greenlock-store-fs": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/greenlock-store-fs/-/greenlock-store-fs-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/greenlock-store-fs/-/greenlock-store-fs-3.0.2.tgz",
|
||||||
|
|
|
@ -34,13 +34,15 @@
|
||||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@root/acme": "^3.0.0-wip.3",
|
"@root/acme": "^3.0.5",
|
||||||
"@root/csr": "^0.8.1",
|
"@root/csr": "^0.8.1",
|
||||||
"@root/keypairs": "^0.9.0",
|
"@root/keypairs": "^0.9.0",
|
||||||
"@root/mkdirp": "^1.0.0",
|
"@root/mkdirp": "^1.0.0",
|
||||||
"@root/request": "^1.3.10",
|
"@root/request": "^1.3.10",
|
||||||
|
"acme-dns-01-digitalocean": "^3.0.1",
|
||||||
"acme-http-01-standalone": "^3.0.0",
|
"acme-http-01-standalone": "^3.0.0",
|
||||||
"cert-info": "^1.5.1",
|
"cert-info": "^1.5.1",
|
||||||
|
"greenlock-manager-fs": "^0.1.0",
|
||||||
"greenlock-store-fs": "^3.0.2",
|
"greenlock-store-fs": "^3.0.2",
|
||||||
"safe-replace": "^1.1.0"
|
"safe-replace": "^1.1.0"
|
||||||
},
|
},
|
||||||
|
|
28
utils.js
28
utils.js
|
@ -3,7 +3,7 @@
|
||||||
var U = module.exports;
|
var U = module.exports;
|
||||||
|
|
||||||
var promisify = require('util').promisify;
|
var promisify = require('util').promisify;
|
||||||
var resolveSoa = promisify(require('dns').resolveSoa);
|
//var resolveSoa = promisify(require('dns').resolveSoa);
|
||||||
var resolveMx = promisify(require('dns').resolveMx);
|
var resolveMx = promisify(require('dns').resolveMx);
|
||||||
var punycode = require('punycode');
|
var punycode = require('punycode');
|
||||||
var Keypairs = require('@root/keypairs');
|
var Keypairs = require('@root/keypairs');
|
||||||
|
@ -165,18 +165,28 @@ U._genKeypair = function(keyType) {
|
||||||
|
|
||||||
// TODO use ACME._importKeypair ??
|
// TODO use ACME._importKeypair ??
|
||||||
U._importKeypair = function(keypair) {
|
U._importKeypair = function(keypair) {
|
||||||
|
// this should import all formats equally well:
|
||||||
|
// 'object' (JWK), 'string' (private key pem), kp.privateKeyPem, kp.privateKeyJwk
|
||||||
|
if (keypair.private || keypair.d) {
|
||||||
|
return U._jwkToSet(keypair.private || keypair);
|
||||||
|
}
|
||||||
if (keypair.privateKeyJwk) {
|
if (keypair.privateKeyJwk) {
|
||||||
return U._jwkToSet(keypair.privateKeyJwk);
|
return U._jwkToSet(keypair.privateKeyJwk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keypair.privateKeyPem) {
|
if ('string' !== typeof keypair && !keypair.privateKeyPem) {
|
||||||
// TODO put in errors
|
// TODO put in errors
|
||||||
throw new Error('missing private key');
|
throw new Error('missing private key');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Keypairs.import({ pem: keypair.privateKeyPem }).then(function(priv) {
|
return Keypairs.import({ pem: keypair.privateKeyPem || keypair }).then(
|
||||||
return U._jwkToSet(priv);
|
function(priv) {
|
||||||
});
|
if (!priv.d) {
|
||||||
|
throw new Error('missing private key');
|
||||||
|
}
|
||||||
|
return U._jwkToSet(priv);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
U._jwkToSet = function(jwk) {
|
U._jwkToSet = function(jwk) {
|
||||||
|
@ -263,7 +273,9 @@ U._getOrCreateKeypair = function(db, subject, query, keyType, mustExist) {
|
||||||
};
|
};
|
||||||
|
|
||||||
U._getKeypair = function(db, subject, query) {
|
U._getKeypair = function(db, subject, query) {
|
||||||
return U._getOrCreateKeypair(db, subject, query, '', true).then(function (result) {
|
return U._getOrCreateKeypair(db, subject, query, '', true).then(function(
|
||||||
return result.keypair;
|
result
|
||||||
});
|
) {
|
||||||
|
return result.keypair;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue