@root/greenlock
Advanced tools
Comparing version 3.0.0-wip.0 to 3.0.1
@@ -9,4 +9,7 @@ 'use strict'; | ||
A._getOrCreate = function(greenlock, db, acme, args) { | ||
var email = args.subscriberEmail || greenlock._defaults.subscriberEmail; | ||
A._getOrCreate = function(gnlck, mconf, db, acme, args) { | ||
var email = | ||
args.subscriberEmail || | ||
mconf.subscriberEmail || | ||
gnlck._defaults.subscriberEmail; | ||
@@ -27,3 +30,10 @@ if (!email) { | ||
pending[email] = A._rawGetOrCreate(greenlock, db, acme, args, email) | ||
pending[email] = A._rawGetOrCreate( | ||
gnlck, | ||
mconf, | ||
db, | ||
acme, | ||
args, | ||
) | ||
.catch(function(e) { | ||
@@ -43,6 +53,6 @@ delete pending[email]; | ||
// 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; | ||
if (db.check) { | ||
p = A._checkStore(greenlock, db, acme, args, email); | ||
p = A._checkStore(gnlck, mconf, db, acme, args, email); | ||
} else { | ||
@@ -54,3 +64,3 @@ p = Promise.resolve(null); | ||
if (!fullAccount) { | ||
return A._newAccount(greenlock, db, acme, args, email, null); | ||
return A._newAccount(gnlck, mconf, db, acme, args, email, null); | ||
} | ||
@@ -62,11 +72,16 @@ | ||
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) { | ||
var keyType = args.accountKeyType || greenlock._defaults.accountKeyType; | ||
A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) { | ||
var keyType = | ||
args.accountKeyType || | ||
mconf.accountKeyType || | ||
gnlck._defaults.accountKeyType; | ||
var query = { | ||
subject: args.subject, | ||
email: email, | ||
subscriberEmail: email, | ||
customerEmail: args.customerEmail, | ||
account: fullAccount || {} | ||
@@ -81,4 +96,6 @@ }; | ||
agreeToTerms: | ||
args.agreeToTerms || greenlock._defaults.agreeToTerms, | ||
accountKeypair: keypair, | ||
args.agreeToTerms || | ||
mconf.agreeToTerms || | ||
gnlck._defaults.agreeToTerms, | ||
accountKey: keypair.privateKeyJwk || keypair.private, | ||
debug: args.debug | ||
@@ -95,3 +112,5 @@ }; | ||
(receipt.key.kid || receipt.kid), | ||
email: args.email | ||
email: args.email, | ||
subscriberEmail: email, | ||
customerEmail: args.customerEmail | ||
}; | ||
@@ -105,2 +124,9 @@ | ||
query.receipt = receipt; | ||
query.directoryUrl = gnlck._defaults.directoryUrl; | ||
/* | ||
query.server = gnlck._defaults.directoryUrl.replace( | ||
/^https?:\/\//i, | ||
'' | ||
); | ||
*/ | ||
keyP = db.setKeypair(query, keypair); | ||
@@ -120,3 +146,12 @@ } | ||
email: email, | ||
agreeTos: true | ||
subscriberEmail: email, | ||
customerEmail: args.customerEmail, | ||
agreeTos: true, | ||
directoryUrl: gnlck._defaults.directoryUrl | ||
/* | ||
server: gnlck._defaults.directoryUrl.replace( | ||
/^https?:\/\//i, | ||
'' | ||
) | ||
*/ | ||
}, | ||
@@ -149,3 +184,3 @@ reg | ||
A._checkStore = function(greenlock, db, acme, args, email) { | ||
A._checkStore = function(gnlck, mconf, db, acme, args, email) { | ||
if ((args.domain || args.domains) && !args.subject) { | ||
@@ -161,8 +196,8 @@ console.warn("use 'subject' instead of 'domain'"); | ||
if (args.accountKeypair) { | ||
if (args.accountKey) { | ||
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 | ||
return U._importKeypair(args.accountKeypair); | ||
return U._importKeypair(args.accountKey); | ||
} | ||
@@ -179,2 +214,4 @@ | ||
email: email, | ||
subscriberEmail: email, | ||
customerEmail: args.customerEmail || mconf.customerEmail, | ||
account: account | ||
@@ -181,0 +218,0 @@ }) |
@@ -7,2 +7,3 @@ 'use strict'; | ||
var Enc = require('@root/encoding'); | ||
var Keypairs = require('@root/keypairs'); | ||
@@ -12,5 +13,18 @@ var pending = {}; | ||
// 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 | ||
C._getOrOrder = function(greenlock, db, acme, challenges, account, args) { | ||
var email = args.subscriberEmail || greenlock._defaults.subscriberEmail; | ||
C._getOrOrder = function(gnlck, mconf, db, acme, chs, acc, args) { | ||
var email = | ||
args.subscriberEmail || | ||
mconf.subscriberEmail || | ||
gnlck._defaults.subscriberEmail; | ||
@@ -23,7 +37,8 @@ var id = args.altnames.join(' '); | ||
pending[id] = C._rawGetOrOrder( | ||
greenlock, | ||
gnlck, | ||
mconf, | ||
db, | ||
acme, | ||
challenges, | ||
account, | ||
chs, | ||
acc, | ||
email, | ||
@@ -45,20 +60,13 @@ args | ||
// Certificates | ||
C._rawGetOrOrder = function( | ||
greenlock, | ||
db, | ||
acme, | ||
challenges, | ||
account, | ||
email, | ||
args | ||
) { | ||
return C._check(db, args).then(function(pems) { | ||
C._rawGetOrOrder = function(gnlck, mconf, db, acme, chs, acc, email, args) { | ||
return C._check(gnlck, mconf, db, args).then(function(pems) { | ||
// No pems? get some! | ||
if (!pems) { | ||
return C._rawOrder( | ||
greenlock, | ||
gnlck, | ||
mconf, | ||
db, | ||
acme, | ||
challenges, | ||
account, | ||
chs, | ||
acc, | ||
email, | ||
@@ -68,7 +76,7 @@ args | ||
// do not wait on notify | ||
greenlock._notify('cert_issue', { | ||
gnlck._notify('cert_issue', { | ||
options: args, | ||
subject: args.subject, | ||
altnames: args.altnames, | ||
account: account, | ||
account: acc, | ||
email: email, | ||
@@ -82,3 +90,3 @@ pems: newPems | ||
// 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 | ||
@@ -91,22 +99,16 @@ // there will be an additional .renewing property if the certs are being asynchronously renewed | ||
// Getting stale? Let's renew to freshen up! | ||
var p = C._rawOrder( | ||
greenlock, | ||
db, | ||
acme, | ||
challenges, | ||
account, | ||
email, | ||
args | ||
).then(function(renewedPems) { | ||
// do not wait on notify | ||
greenlock._notify('cert_renewal', { | ||
options: args, | ||
subject: args.subject, | ||
altnames: args.altnames, | ||
account: account, | ||
email: email, | ||
pems: renewedPems | ||
}); | ||
return renewedPems; | ||
}); | ||
var p = C._rawOrder(gnlck, mconf, db, acme, chs, acc, email, args).then( | ||
function(renewedPems) { | ||
// do not wait on notify | ||
gnlck._notify('cert_renewal', { | ||
options: args, | ||
subject: args.subject, | ||
altnames: args.altnames, | ||
account: acc, | ||
email: email, | ||
pems: renewedPems | ||
}); | ||
return renewedPems; | ||
} | ||
); | ||
@@ -124,3 +126,3 @@ // TODO what should this be? | ||
// 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 | ||
@@ -134,6 +136,13 @@ .slice(0) | ||
var keyType = args.serverKeyType || greenlock._defaults.serverKeyType; | ||
var keyType = | ||
args.serverKeyType || | ||
mconf.serverKeyType || | ||
gnlck._defaults.serverKeyType; | ||
var query = { | ||
subject: args.subject, | ||
certificate: args.certificate || {} | ||
certificate: args.certificate || {}, | ||
directoryUrl: | ||
args.directoryUrl || | ||
mconf.directoryUrl || | ||
gnlck._defaults.directoryUrl | ||
}; | ||
@@ -146,3 +155,3 @@ rawPending[id] = U._getOrCreateKeypair(db, args.subject, query, keyType) | ||
return CSR.csr({ | ||
jwk: serverKeypair.privateKeyJwk, | ||
jwk: serverKeypair.privateKeyJwk || serverKeypair.private, | ||
domains: domains, | ||
@@ -156,18 +165,13 @@ encoding: 'der' | ||
.then(function(csr) { | ||
function notify() { | ||
greenlock._notify('challenge_status', { | ||
options: args, | ||
subject: args.subject, | ||
altnames: args.altnames, | ||
account: account, | ||
email: email | ||
}); | ||
function notify(ev, opts) { | ||
gnlck._notify(ev, opts); | ||
} | ||
var certReq = { | ||
debug: args.debug || greenlock._defaults.debug, | ||
debug: args.debug || gnlck._defaults.debug, | ||
challenges: challenges, | ||
account: account, // only used if accounts.key.kid exists | ||
accountKeypair: account.keypair, | ||
keypair: account.keypair, // TODO | ||
challenges: chs, | ||
account: acc, // only used if accounts.key.kid exists | ||
accountKey: | ||
acc.keypair.privateKeyJwk || acc.keypair.private, | ||
keypair: acc.keypair, // TODO | ||
csr: csr, | ||
@@ -204,3 +208,3 @@ domains: domains, // because ACME.js v3 uses `domains` still, actually | ||
.then(function() { | ||
return C._check(db, args); | ||
return C._check(gnlck, mconf, db, args); | ||
}) | ||
@@ -222,10 +226,13 @@ .then(function(bundle) { | ||
// returns pems, if they exist | ||
C._check = function(db, args) { | ||
C._check = function(gnlck, mconf, db, args) { | ||
var query = { | ||
subject: args.subject, | ||
// 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) { | ||
console.log('[debug] has pems? (yes)', pems); | ||
if (!pems) { | ||
@@ -251,5 +258,9 @@ return null; | ||
.then(function(keypair) { | ||
console.log('[debug get keypair]', Object.keys(keypair)); | ||
pems.privkey = keypair.privateKeyPem; | ||
return pems; | ||
return Keypairs.export({ | ||
jwk: keypair.privateKeyJwk || keypair.private, | ||
encoding: 'pem' | ||
}).then(function(pem) { | ||
pems.privkey = pem; | ||
return pems; | ||
}); | ||
}) | ||
@@ -264,3 +275,3 @@ .catch(function() { | ||
// Certificates | ||
C._isStale = function(greenlock, args, pems) { | ||
C._isStale = function(gnlck, mconf, args, pems) { | ||
if (args.duplicate) { | ||
@@ -270,3 +281,3 @@ return true; | ||
var renewAt = C._renewableAt(greenlock, args, pems); | ||
var renewAt = C._renewableAt(gnlck, mconf, args, pems); | ||
@@ -280,3 +291,3 @@ if (Date.now() >= renewAt) { | ||
C._renewableAt = function(greenlock, args, pems) { | ||
C._renewableAt = function(gnlck, mconf, args, pems) { | ||
if (args.renewAt) { | ||
@@ -286,3 +297,7 @@ 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; | ||
@@ -289,0 +304,0 @@ if (!args.force && Math.abs(renewOffset) < week) { |
@@ -68,2 +68,23 @@ 'use strict'; | ||
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; | ||
}; | ||
@@ -73,2 +94,7 @@ // The goal here is to reduce boilerplate, such as error checking | ||
greenlock.add = function(args) { | ||
return greenlock._init().then(function() { | ||
return greenlock._add(args); | ||
}); | ||
}; | ||
greenlock._add = function(args) { | ||
return Promise.resolve().then(function() { | ||
@@ -133,8 +159,10 @@ // durations | ||
var mng = greenlock.manager; | ||
if (mng.notify) { | ||
if (mng.notify || greenlock._defaults.notify) { | ||
try { | ||
var p = mng.notify(ev, params); | ||
var p = (mng.notify || greenlock._defaults.notify)(ev, params); | ||
if (p && p.catch) { | ||
p.catch(function(e) { | ||
console.error("Error on event '" + ev + "':"); | ||
console.error( | ||
"Promise Rejection on event '" + ev + "':" | ||
); | ||
console.error(e); | ||
@@ -144,3 +172,3 @@ }); | ||
} catch (e) { | ||
console.error("Error on event '" + ev + "':"); | ||
console.error("Thrown Exception on event '" + ev + "':"); | ||
console.error(e); | ||
@@ -152,2 +180,3 @@ } | ||
console.error(params); | ||
console.error(params.stack); | ||
} | ||
@@ -188,2 +217,7 @@ } | ||
greenlock.renew = function(args) { | ||
return greenlock.manager.config().then(function(mconf) { | ||
return greenlock._renew(mconf, args); | ||
}); | ||
}; | ||
greenlock._renew = function(mconf, args) { | ||
if (!args) { | ||
@@ -216,3 +250,3 @@ args = {}; | ||
if (!site) { | ||
return null; | ||
return Promise.resolve(null); | ||
} | ||
@@ -226,3 +260,3 @@ | ||
return greenlock | ||
.order(site) | ||
._order(mconf, site) | ||
.then(function(pems) { | ||
@@ -232,4 +266,12 @@ order.pems = pems; | ||
.catch(function(err) { | ||
order.error = err; | ||
greenlock._notify('order_error', order); | ||
// For greenlock express serialization | ||
err.toJSON = errorToJSON; | ||
err.subject = site.subject; | ||
if (args.servername) { | ||
err.servername = args.servername; | ||
} | ||
// for debugging, but not to be relied on | ||
err._order = order; | ||
// TODO err.context = err.context || 'renew_certificate' | ||
greenlock._notify('error', err); | ||
}) | ||
@@ -249,3 +291,6 @@ .then(function() { | ||
var acme = ACME.create({ | ||
debug: args.debug | ||
maintainerEmail: greenlock._defaults.maintainerEmail, | ||
packageAgent: greenlock._defaults.packageAgent, | ||
notify: greenlock._notify, | ||
debug: greenlock._defaults.debug || args.debug | ||
}); | ||
@@ -279,2 +324,9 @@ var dirUrl = args.directoryUrl || greenlock._defaults.directoryUrl; | ||
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) { | ||
@@ -290,2 +342,3 @@ var storeConf = args.store || greenlock._defaults.store; | ||
greenlock, | ||
mconf, | ||
store.accounts, | ||
@@ -296,8 +349,8 @@ acme, | ||
var challengeConfs = | ||
args.challenges || greenlock._defaults.challenges; | ||
console.log('[debug] challenge confs', challengeConfs); | ||
args.challenges || | ||
mconf.challenges || | ||
greenlock._defaults.challenges; | ||
return Promise.all( | ||
Object.keys(challengeConfs).map(function(typ01) { | ||
var chConf = challengeConfs[typ01]; | ||
console.log('[debug] module', chConf); | ||
return P._load(chConf.module).then(function( | ||
@@ -321,2 +374,3 @@ plugin | ||
greenlock, | ||
mconf, | ||
store.certificates, | ||
@@ -365,2 +419,6 @@ acme, | ||
if ('function' === typeof opts.notify) { | ||
defaults.notify = opts.notify; | ||
} | ||
if (!defaults._maintainerPackage) { | ||
@@ -570,1 +628,9 @@ defaults._maintainerPackage = pkg.name; | ||
}; | ||
function errorToJSON(e) { | ||
var error = {}; | ||
Object.getOwnPropertyNames(e).forEach(function(k) { | ||
error[k] = e[k]; | ||
}); | ||
return error; | ||
} |
{ | ||
"name": "@root/greenlock", | ||
"version": "3.0.0-wip.0", | ||
"version": "3.0.1", | ||
"description": "The easiest Let's Encrypt client for Node.js and Browsers", | ||
@@ -11,2 +11,3 @@ "homepage": "https://rootprojects.org/greenlock/", | ||
"lib", | ||
"bin", | ||
"dist" | ||
@@ -38,3 +39,3 @@ ], | ||
"dependencies": { | ||
"@root/acme": "^3.0.0-wip.3", | ||
"@root/acme": "^3.0.6", | ||
"@root/csr": "^0.8.1", | ||
@@ -46,3 +47,4 @@ "@root/keypairs": "^0.9.0", | ||
"cert-info": "^1.5.1", | ||
"greenlock-store-fs": "^3.0.2", | ||
"greenlock-manager-fs": "^0.6.0", | ||
"greenlock-store-fs": "^3.2.0", | ||
"safe-replace": "^1.1.0" | ||
@@ -49,0 +51,0 @@ }, |
@@ -7,4 +7,6 @@ 'use strict'; | ||
var spawnSync = require('child_process').spawnSync; | ||
var PKG_DIR = __dirname; | ||
// Exported for CLIs and such to override | ||
P.PKG_DIR = __dirname; | ||
P._load = function(modname) { | ||
@@ -39,3 +41,3 @@ try { | ||
cmd = spawnSync(npm, args, { | ||
cwd: PKG_DIR, | ||
cwd: P.PKG_DIR, | ||
windowsHide: true | ||
@@ -50,3 +52,3 @@ }); | ||
"' in '" + | ||
PKG_DIR + | ||
P.PKG_DIR + | ||
"'" | ||
@@ -77,3 +79,3 @@ ); | ||
"' in '" + | ||
PKG_DIR + | ||
P.PKG_DIR + | ||
"'" | ||
@@ -83,3 +85,3 @@ ); | ||
console.error( | ||
'Try for yourself:\n\tcd ' + PKG_DIR + '\n\tnpm ' + args.join(' ') | ||
'Try for yourself:\n\tcd ' + P.PKG_DIR + '\n\tnpm ' + args.join(' ') | ||
); | ||
@@ -100,3 +102,3 @@ | ||
var cmd = spawn(npm, args, { | ||
cwd: PKG_DIR, | ||
cwd: P.PKG_DIR, | ||
windowsHide: true | ||
@@ -119,3 +121,3 @@ }); | ||
"' in '" + | ||
PKG_DIR + | ||
P.PKG_DIR + | ||
"'" | ||
@@ -144,3 +146,3 @@ ); | ||
"' in '" + | ||
PKG_DIR + | ||
P.PKG_DIR + | ||
"'" | ||
@@ -150,3 +152,3 @@ ); | ||
'Try for yourself:\n\tcd ' + | ||
PKG_DIR + | ||
P.PKG_DIR + | ||
'\n\tnpm ' + | ||
@@ -153,0 +155,0 @@ args.join(' ') |
235
README.md
@@ -1,24 +0,231 @@ | ||
# root-greenlock.js | ||
# @root/greenlock | ||
🔐 Free SSL, Free Wildcard SSL, and Fully Automated HTTPS for Node.js and Browsers, issued by Let's Encrypt v2 via ACME | ||
Typically file propagation is faster and more reliably than DNS propagation. | ||
Therefore, http-01 will be preferred to dns-01 except when wildcards or **private domains** are in use. | ||
Greenlock™ is the easiest way to integrate Let's Encrypt into your projects, products, and infrastructure. | ||
http-01 will only be supplied as a defaut if no other challenge is provided. | ||
- [x] **Wildcard** Certificates | ||
- [x] **IoT** Environments | ||
- [x] **Enterprise** and **On-Prem** | ||
- [x] **Private** Networks | ||
- [x] **Localhost** Development | ||
- [x] **Web Hosting** Providers | ||
- [x] **Commercial** support | ||
We've built it simple enough for Hobbyists, and robust enough for the Enterprise. | ||
<!-- | ||
# Localhost Development | ||
<details> | ||
<summary>HTTPS on Localhost</summary> | ||
TODO | ||
</details> | ||
# WebServer with Automatic HTTPS | ||
<details> | ||
<summary>Learn more about the Greenlock Web Server</summary> | ||
TODO | ||
</details> | ||
# Commandline | ||
<details> | ||
<summary>Learn more about the Greenlock CLI</summary> | ||
TODO | ||
</details> | ||
--> | ||
# JavaScript Library | ||
<details> | ||
<summary>Greenlock API (shared among JS implementations)</summary> | ||
### Instantiate | ||
```js | ||
// Creates an instance of greenlock with certain default values | ||
var gl = Greenlock.create({ | ||
// Staging for testing environments | ||
staging: true, | ||
// This should be the contact who receives critical bug and security notifications | ||
// Optionally, you may receive other (very few) updates, such as important new features | ||
maintainerEmail: 'jon@example.com', | ||
maintainerUpdates: true, // default: false | ||
// The "Let's Encrypt Subscriber" (often the same as the maintainer) | ||
// NOT the end customer (except where that is also the maintainer) | ||
subscriberEmail: 'jon@example.com', | ||
agreeToTerms: true // default: false | ||
}); | ||
``` | ||
Greenlock.create | ||
Greenlock#add | ||
Greenlock#order... or Greenlock#issue? | ||
Greenlock#renew... or Greenlock#issue? | ||
Greenlock#remove | ||
Greenlock#get | ||
Greenlock#all | ||
| Parameter | Description | | ||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| servername | the default servername to use for non-sni requests (many IoT clients) | | ||
| maintainerEmail | the developer contact for critical bug and security notifications | | ||
| maintainerUpdates | (default: false) receive occasional non-critical notifications | | ||
| 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 | ||
```js | ||
gl.add({ | ||
subject: 'example.com', | ||
altnames: ['example.com', 'www.example.com', 'exampleapi.com'] | ||
}); | ||
``` | ||
Better scaling | ||
| Parameter | Description | | ||
| --------------- | ---------------------------------------------------------------------------------- | | ||
| subject | the first domain on, and identifier of the certificate | | ||
| altnames | first domain, plus additional domains<br>note: the order should always be the same | | ||
| subscriberEmail | if different from the default (i.e. multi-tenant, whitelabel) | | ||
| agreeToTerms | if subscriber is different from the default | | ||
cluster lazy-load, remote management | ||
### Issue and Renew Certificates | ||
`server identifier (for sharding, for manager)` | ||
This will renew only domains that have reached their `renewAt` or are within the befault `renewOffset`. | ||
```js | ||
return greenlock | ||
.renew() | ||
.then(function(pems) { | ||
console.info(pems); | ||
}) | ||
.then(function(results) { | ||
results.forEach(function(site) { | ||
if (site.error) { | ||
console.error(site.subject, site.error); | ||
return; | ||
} | ||
}); | ||
}); | ||
``` | ||
| Parameter | Type | Description | | ||
| ---------- | ---- | ---------------------------------------------------------- | | ||
| (optional) | - | ALL parameters are optional, but some should be paired | | ||
| force | bool | force silly options, such as tiny durations | | ||
| duplicate | bool | force the domain to renew, regardless of age or expiration | | ||
<!-- | ||
| servername | string<br>hostname | renew the certificate that has this domain in its altnames (for ServerName Indication / SNI lookup) | | ||
| renewOffset | string<br>+ duration | renew domains that have been **issued** after the given duration. ex: '45d' (45 days _after_) | | ||
| renewOffset | string<br>- duration | renew domains, by this duration, before they **expire**. ex: '-3w' (3 weeks _before_) | | ||
--> | ||
Note: only previous approved domains (via `gl.add()`) may be renewed | ||
Note: this will NOT throw an **error**. It will return an array of certifates or errors. | ||
### More | ||
TODO | ||
</details> | ||
<details> | ||
<summary>Node.js</summary> | ||
```bash | ||
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 | ||
</details> | ||
<details> | ||
<summary>Express.js</summary> | ||
```js | ||
'use strict'; | ||
var Greenlock = require(@root/greenlock-express); | ||
var greenlock = Greenlock.create({ | ||
// for security and critical bug notices | ||
maintainerEmail: 'jon@example.com' | ||
// for | ||
maintainerNewsletter: true | ||
}); | ||
``` | ||
</details> | ||
<details> | ||
<summary>WebPack</summary> | ||
TODO | ||
</details> | ||
<details> | ||
<summary>VanillaJS for Browsers</summary> | ||
TODO | ||
</details> | ||
--> | ||
# HTTP-01 & DNS-01 Integrations | ||
For Public Web Servers running on a VPS, the **default HTTP-01 challenge plugin** | ||
will work just fine for most people. | ||
However, for | ||
- **Wildcard Certificates** | ||
- **IoT Environments** | ||
- **Enterprise On-Prem** | ||
- **Private Networks** | ||
Greenlock provides an easy way to integrate Let's Encrypt with your existing services | ||
through a variety of **DNS-01** infrastructure | ||
Why | ||
Typically file propagation is faster and more reliably than DNS propagation. | ||
Therefore, http-01 will be preferred to dns-01 except when wildcards or **private domains** are in use. | ||
http-01 will only be supplied as a defaut if no other challenge is provided. | ||
You can use ACME (Let's Encrypt) with | ||
- [x] DNS-01 Challenges | ||
- CloudFlare | ||
- [Digital Ocean](https://git.rootprojects.org/root/acme-dns-01-digitalocean.js) | ||
- [DNSimple](https://git.rootprojects.org/root/acme-dns-01-dnsimple.js) | ||
- [DuckDNS](https://git.rootprojects.org/root/acme-dns-01-duckdns.js) | ||
- [GoDaddy](https://git.rootprojects.org/root/acme-dns-01-godaddy.js) | ||
- [Gandi](https://git.rootprojects.org/root/acme-dns-01-gandi.js) | ||
- [NameCheap](https://git.rootprojects.org/root/acme-dns-01-namecheap.js) | ||
- [Name.com](https://git.rootprojects.org/root/acme-dns-01-namedotcom.js) | ||
- Route53 (AWS) | ||
- [Vultr](https://git.rootprojects.org/root/acme-dns-01-vultr.js) | ||
- Build your own | ||
- [x] HTTP-01 Challenges | ||
- [In-Memory](https://git.rootprojects.org/root/acme-http-01-standalone.js) (Standalone) | ||
- [FileSystem](https://git.rootprojects.org/root/acme-http-01-webroot.js) (WebRoot) | ||
- S3 (AWS, Digital Ocean, etc) | ||
- [x] TLS-ALPN-01 Challenges | ||
- Contact us to learn about Greenlock Pro |
28
utils.js
@@ -6,3 +6,3 @@ 'use strict'; | ||
var promisify = require('util').promisify; | ||
var resolveSoa = promisify(require('dns').resolveSoa); | ||
//var resolveSoa = promisify(require('dns').resolveSoa); | ||
var resolveMx = promisify(require('dns').resolveMx); | ||
@@ -169,2 +169,7 @@ var punycode = require('punycode'); | ||
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) { | ||
@@ -174,3 +179,3 @@ return U._jwkToSet(keypair.privateKeyJwk); | ||
if (!keypair.privateKeyPem) { | ||
if ('string' !== typeof keypair && !keypair.privateKeyPem) { | ||
// TODO put in errors | ||
@@ -180,5 +185,10 @@ throw new Error('missing private key'); | ||
return Keypairs.import({ pem: keypair.privateKeyPem }).then(function(priv) { | ||
return U._jwkToSet(priv); | ||
}); | ||
return Keypairs.import({ pem: keypair.privateKeyPem || keypair }).then( | ||
function(priv) { | ||
if (!priv.d) { | ||
throw new Error('missing private key'); | ||
} | ||
return U._jwkToSet(priv); | ||
} | ||
); | ||
}; | ||
@@ -270,5 +280,7 @@ | ||
U._getKeypair = function(db, subject, query) { | ||
return U._getOrCreateKeypair(db, subject, query, '', true).then(function (result) { | ||
return result.keypair; | ||
}); | ||
return U._getOrCreateKeypair(db, subject, query, '', true).then(function( | ||
result | ||
) { | ||
return result.keypair; | ||
}); | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
79521
15
2144
1
232
3
10
8
+ Addedgreenlock-manager-fs@^0.6.0
+ Addedgreenlock-manager-fs@0.6.5(transitive)
Updated@root/acme@^3.0.6
Updatedgreenlock-store-fs@^3.2.0