express server läuft jetzt mit https
This commit is contained in:
Lukas Nowy
2018-12-16 19:08:08 +01:00
parent 5589b0df3f
commit fd947bd852
475 changed files with 91128 additions and 0 deletions

21
express-server/node_modules/le-sni-auto/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Daplie, Inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

194
express-server/node_modules/le-sni-auto/README.md generated vendored Normal file
View File

@ -0,0 +1,194 @@
le-sni-auto
===========
| Sponsored by [ppl](https://ppl.family)
An auto-sni strategy for registering and renewing letsencrypt certificates using SNICallback.
This does a couple of rather simple things:
* caches certificates in memory
* calls `getCertificatesAsync(domain, null)` when a certificate is not in memory
* calls `getCertificatesASync(domain, certs)` when a certificate is up for renewal or expired
Install
=======
```bash
npm install --save le-sni-auto@2.x
```
Usage
=====
With node-letsencrypt
---------------------
```javascript
'use strict';
var leSni = require('le-sni-auto').create({
renewWithin: 14 * 24 * 60 * 60 1000 // do not renew more than 14 days before expiration
, renewBy: 10 * 24 * 60 * 60 1000 // do not wait more than 10 days before expiration
, tlsOptions: {
rejectUnauthorized: true // These options will be used with tls.createSecureContext()
, requestCert: false // in addition to key (privkey.pem) and cert (cert.pem + chain.pem),
, ca: null // which are provided by letsencrypt
, crl: null
}
});
var le = require('letsencrypt').create({
server: 'staging'
, sni: leSni
, approveDomains: function (domain, cb) {
// here you would lookup details such as email address in your db
cb(null, { email: 'john.doe@gmail.com.', domains: [domain, 'www.' + domain], agreeTos: true }}
}
});
var redirectHttps = require('redirect-https').create();
http.createServer(le.middleware(redirectHttps));
var app = require('express')();
https.createServer(le.tlsOptions, le.middleware(app)).listen(443);
```
You can also provide a thunk-style `getCertificates(domain, certs, cb)`.
Standalone
----------
```javascript
'use strict';
var leSni = require('le-sni-auto').create({
renewWithin: 14 * 24 * 60 * 60 1000 // do not renew prior to 10 days before expiration
, renewBy: 10 * 24 * 60 * 60 1000 // do not wait more than 5 days before expiration
// key (privkey.pem) and cert (cert.pem + chain.pem) will be provided by letsencrypt
, tlsOptions: { rejectUnauthorized: true, requestCert: false, ca: null, crl: null }
, getCertificatesAsync: function (domain, certs) {
// return a promise with an object with the following keys:
// { privkey, cert, chain, expiresAt, issuedAt, subject, altnames }
}
});
var tlsOptions = {
SNICallback: leSni.sniCallback
};
https.createServer(tlsOptions, app);
```
You can also provide a thunk-style `getCertificates(domain, certs, cb)`.
API
===
* create(options)
* `getCertificates(domain, certs, cb)` or `getCertificatesAsync(domain, certs)`
* `renewWithin` (default 7 days, min 3 days)
* `renewBy` (default 2 days, min 12 hours)
* `sniCallback(domain, cb)`
* `cacheCerts(certs)`
* `uncacheDomain(domain)`
.renewWithin
-----------
Specifies the maximum amount of time (in ms) before
the certificate expires to renew it.
Say the cert expires in 90 days and you would like
to renew, **at earliest** 10 days before it expires.
You would set this to `10 * 24 * 60 * 60 * 1000`.
.renewBy
--------
Specifies the maximum amount of time (in ms) before
the certificate expires to renew it.
Say the cert expires in 90 days and you would like
to renew, **at latest** 10 days before it expires.
You would set this to `10 * 24 * 60 * 60 * 1000`.
**MUST** be **less than** `renewWithin`.
.sniCallback()
-----------
This gets passed to `https.createServer(tlsOptions, app)` as `tlsOptions.SNICallback`.
```javascript
var leSni = require('le-sni-auto').create({
renewWithin: 14 * 24 * 60 * 60 1000
});
var tlsOptions = {
SNICallback: leSni.sniCallback
};
function app(req, res) {
res.end("Hello, World!");
}
https.createServer(tlsOptions, app);
```
.cacheCerts()
-----------
Manually load a certificate into the cache.
This is useful in a cluster environment where the master
may wish to inform multiple workers of a new or renewed certificate,
or to satisfy tls-sni-01 challenges.
```
leSni.cacheCerts({
, privkey: '<<privkey.pem>>'
, cert: '<<cert.pem + chain.pem>>'
, subject: 'example.com'
, altnames: [ 'example.com', 'www.example.com' ]
, issuedAt: 1470975565000
, expiresAt: 1478751565000
, auto: true
});
```
.uncacheCerts()
-----------
Remove cached certificates from the cache.
This is useful once a tls-sni-01 challenge has been satisfied.
```
leSni.uncacheCerts({
, subject: 'example.com'
, altnames: [ 'example.com', 'www.example.com' ]
});
```

172
express-server/node_modules/le-sni-auto/index.js generated vendored Normal file
View File

@ -0,0 +1,172 @@
'use strict';
var DAY = 24 * 60 * 60 * 1000;
var HOUR = 60 * 60 * 1000;
var MIN = 60 * 1000;
var defaults = {
// don't renew before the renewWithin period
renewWithin: 30 * DAY
, _renewWithinMin: 3 * DAY
// renew before the renewBy period
, renewBy: 21 * DAY
, _renewByMin: Math.floor(DAY / 2)
// just to account for clock skew really
, _dropDead: 5 * MIN
};
// autoSni = { renewWithin, renewBy, getCertificates, tlsOptions, _dbg_now }
module.exports.create = function (autoSni) {
if (!autoSni.getCertificatesAsync) { autoSni.getCertificatesAsync = require('bluebird').promisify(autoSni.getCertificates); }
if (!autoSni.renewWithin) { autoSni.renewWithin = autoSni.notBefore || defaults.renewWithin; }
if (autoSni.renewWithin < defaults._renewWithinMin) {
throw new Error("options.renewWithin should be at least " + (defaults._renewWithinMin / DAY) + " days");
}
if (!autoSni.renewBy) { autoSni.renewBy = autoSni.notAfter || defaults.renewBy; }
if (autoSni.renewBy < defaults._renewByMin) {
throw new Error("options.renewBy should be at least " + (defaults._renewBy / HOUR) + " hours");
}
if (!autoSni.tlsOptions) { autoSni.tlsOptions = autoSni.httpsOptions || {}; }
autoSni._dropDead = defaults._dropDead;
//autoSni.renewWithin = autoSni.notBefore; // i.e. 15 days
autoSni._renewWindow = autoSni.renewWithin - autoSni.renewBy; // i.e. 1 day
//autoSni.renewRatio = autoSni.notBefore = autoSni._renewWindow; // i.e. 1/15 (6.67%)
var tls = require('tls');
var _autoSni = {
// in-process cache
_ipc: {}
, getOptions: function () {
return JSON.parse(JSON.stringify(defaults));
}
// cache and format incoming certs
, cacheCerts: function (certs) {
var meta = {
certs: certs
, tlsContext: 'string' === typeof certs.cert && tls.createSecureContext({
key: certs.privkey
// backwards/forwards compat
, cert: (certs.cert||'').replace(/[\r\n]+$/, '') + '\r\n' + certs.chain
, rejectUnauthorized: autoSni.tlsOptions.rejectUnauthorized
, requestCert: autoSni.tlsOptions.requestCert // request peer verification
, ca: autoSni.tlsOptions.ca // this chain is for incoming peer connctions
, crl: autoSni.tlsOptions.crl // this crl is for incoming peer connections
}) || { '_fake_tls_context_': true }
, subject: certs.subject
, auto: 'undefined' === typeof certs.auto ? true : certs.auto
// stagger renewal time by a little bit of randomness
, renewAt: (certs.expiresAt - (autoSni.renewWithin - (autoSni._renewWindow * Math.random())))
// err just barely on the side of safety
, expiresNear: certs.expiresAt - autoSni._dropDead
};
var link = { subject: certs.subject };
certs.altnames.forEach(function (domain) {
autoSni._ipc[domain] = link;
});
autoSni._ipc[certs.subject] = meta;
return meta;
}
, uncacheCerts: function (certs) {
certs.altnames.forEach(function (domain) {
delete autoSni._ipc[domain];
});
delete autoSni._ipc[certs.subject];
}
// automate certificate registration on request
, sniCallback: function (domain, cb) {
var certMeta = autoSni._ipc[domain];
var promise;
var now = (autoSni._dbg_now || Date.now());
if (certMeta && !certMeta.then && certMeta.subject !== domain) {
//log(autoSni.debug, "LINK CERT", domain);
certMeta = autoSni._ipc[certMeta.subject];
}
if (!certMeta) {
//log(autoSni.debug, "NO CERT", domain);
// we don't have a cert and must get one
promise = autoSni.getCertificatesAsync(domain, null).then(autoSni.cacheCerts);
autoSni._ipc[domain] = promise;
}
else if (certMeta.then) {
//log(autoSni.debug, "PROMISED CERT", domain);
// we are already getting a cert
promise = certMeta
}
else if (now >= certMeta.expiresNear) {
//log(autoSni.debug, "EXPIRED CERT");
// we have a cert, but it's no good for the average user
promise = autoSni.getCertificatesAsync(domain, certMeta.certs).then(autoSni.cacheCerts);
autoSni._ipc[certMeta.subject] = promise;
} else {
// it's time to renew the cert
if (certMeta.auto && now >= certMeta.renewAt) {
//log(autoSni.debug, "RENEWABLE CERT");
// give the cert some time (2-5 min) to be validated and replaced before trying again
certMeta.renewAt = (autoSni._dbg_now || Date.now()) + (2 * MIN) + (3 * MIN * Math.random());
// let the update happen in the background
autoSni.getCertificatesAsync(domain, certMeta.certs).then(autoSni.cacheCerts);
}
// return the valid cert right away
cb(null, certMeta.tlsContext);
return;
}
// promise the non-existent or expired cert
promise.then(function (certMeta) {
cb(null, certMeta.tlsContext);
}, function (err) {
// console.error('ERROR in le-sni-auto:');
// console.error(err.stack || err);
cb(err);
// don't reuse this promise
delete autoSni._ipc[certMeta && certMeta.subject ? certMeta.subject : domain];
});
}
};
Object.keys(_autoSni).forEach(function (key) {
autoSni[key] = _autoSni[key];
});
_autoSni = null;
return autoSni;
};

98
express-server/node_modules/le-sni-auto/package.json generated vendored Normal file
View File

@ -0,0 +1,98 @@
{
"_args": [
[
"le-sni-auto@^2.1.4",
"/nodeapps/https-test/greenlock-express.js"
]
],
"_from": "le-sni-auto@>=2.1.4 <3.0.0",
"_hasShrinkwrap": false,
"_id": "le-sni-auto@2.1.6",
"_inCache": true,
"_installable": true,
"_location": "/le-sni-auto",
"_nodeVersion": "10.13.0",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/le-sni-auto_2.1.6_1541843237023_0.4202196992257634"
},
"_npmUser": {
"email": "coolaj86@gmail.com",
"name": "coolaj86"
},
"_npmVersion": "6.4.1",
"_phantomChildren": {},
"_requested": {
"name": "le-sni-auto",
"raw": "le-sni-auto@^2.1.4",
"rawSpec": "^2.1.4",
"scope": null,
"spec": ">=2.1.4 <3.0.0",
"type": "range"
},
"_requiredBy": [
"/",
"/greenlock"
],
"_resolved": "https://registry.npmjs.org/le-sni-auto/-/le-sni-auto-2.1.6.tgz",
"_shasum": "32a00bfb2364814d57670b0c2e28e5e32bb08b00",
"_shrinkwrap": null,
"_spec": "le-sni-auto@^2.1.4",
"_where": "/nodeapps/https-test/greenlock-express.js",
"author": {
"email": "coolaj86@gmail.com",
"name": "AJ ONeal",
"url": "https://coolaj86.com/"
},
"bugs": {
"url": "https://git.coolaj86.com/coolaj86/le-sni-auto.js/issues"
},
"dependencies": {
"bluebird": "^3.5.1"
},
"description": "An auto-sni strategy for registering and renewing letsencrypt certificates using SNICallback",
"devDependencies": {},
"directories": {},
"dist": {
"fileCount": 5,
"integrity": "sha512-LcfkF2yQ1nrep+ZfyG+SfR3pHphKFD3zMZ9FKervGfTfvgScCv/XGbX+vxsGZEKZjvzxKbFZ/5LdSCXuLXUU6A==",
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5qklCRA9TVsSAnZWagAAMQgQAJBe7o5sWViVB3xBrs+V\ngUVOFRVv1PyoeL4oYeJ0vM3nkw29OBLqf4ZuP5hyl7HquWVd1JGWLEdJGnkL\nF4+PVcgbFQtVC9/yecCeVXHZ5b4K14GSHIpKp3awxV0yGZQtU4tPQcF15BQV\nYGqLF8epvi5229V24CMqfMyMh8rRPdTEIA3zNG9utz7/sgRAgBCONApm1J/x\nXCpIH15B133U4ig0426KXYco98ddlrLfZKdnVBrSSoORhVpTUiigWRduibYP\neGXKC78ORyXZ1kS8K19USM2KFBZj9IuNQ+xEjkw4nkRex4p33rJtaLxtMzso\ncr9qxLzJUAWrdOCbGVPrhMCCyo9068iHMYehEtDsyYL/KxBdoeWKvpfDl8lY\nGWU5IazTkRFT2cQF9CzvFgY1tsPDzrvVGFZEnJoZ7d4TLwjpB6jyucF1T+hL\no+EN1Qr3IZFaAoYyxWEsNbZOpftWsg9/M9rE30w4hhoPuU1N8L84EQGFEZo9\nxwJOZkH4/xULhipVCP3LVNlln+PSumxtasV9+f9mzYshtHhHoNcvwFtrL3VB\nafdccue0AsF+shdgpPPV2G/b9o0goKlP3uT4GrpmKLIMGHy8j+JOsvLkgS+i\nwR9J3HgjGTGFunXqneXsV+BGUbltCmX9IwhWLXwMoJhiSszhH8VWygkOHTwG\nTDna\r\n=ItG1\r\n-----END PGP SIGNATURE-----\r\n",
"shasum": "32a00bfb2364814d57670b0c2e28e5e32bb08b00",
"tarball": "https://registry.npmjs.org/le-sni-auto/-/le-sni-auto-2.1.6.tgz",
"unpackedSize": 17428
},
"gitHead": "14458181bf07ad8429e961e92561396e23f41196",
"homepage": "https://git.coolaj86.com/coolaj86/le-sni-auto.js",
"keywords": [
"SNICallback",
"auto-sni",
"certbot",
"le-sni",
"le-sni-",
"letsencrypt",
"sni-auto"
],
"license": "(MIT OR Apache-2.0)",
"main": "index.js",
"maintainers": [
{
"name": "coolaj86",
"email": "coolaj86@gmail.com"
},
{
"name": "ppl",
"email": "npm@ppl.family"
}
],
"name": "le-sni-auto",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://git.coolaj86.com/coolaj86/le-sni-auto.js.git"
},
"scripts": {
"test": "node test.js"
},
"version": "2.1.6"
}

205
express-server/node_modules/le-sni-auto/test.js generated vendored Normal file
View File

@ -0,0 +1,205 @@
'use strict';
var DAY = 24 * 60 * 60 * 1000;
var MIN = 60 * 1000;
var START_DAY = new Date(2015, 0, 1, 17, 30, 0, 0).valueOf();
var NOT_BEFORE = 10 * DAY;
var NOT_AFTER = 5 * DAY;
var EXPIRES_AT = START_DAY + NOT_BEFORE + (15 * MIN);
var RENEWABLE_DAY = EXPIRES_AT - (60 * MIN);
var CERT_1 = {
expiresAt: EXPIRES_AT
, subject: 'example.com'
, altnames: ['example.com', 'www.example.com']
};
var CERT_2 = {
expiresAt: EXPIRES_AT + NOT_BEFORE + (60 * MIN)
, subject: 'example.com'
, altnames: ['example.com', 'www.example.com']
};
var CERT_3 = {
expiresAt: EXPIRES_AT
, subject: 'example.com'
, altnames: ['example.com', 'www.example.com']
, auto: false
};
var count = 0;
var expectedCount = 4;
var tests = [
function (domain, certs, cb) {
count += 1;
console.log('#1 is 1 of 4');
if (!domain) {
throw new Error("should have a domain");
}
if (certs) {
console.log('certs');
console.log(certs);
throw new Error("shouldn't have certs that don't even exist yet");
}
cb(null, CERT_1);
}
, function (/*domain, certs, cb*/) {
console.log('#2 should NOT be called');
throw new Error("Should not call register renew a certificate with more than 10 days left");
}
, function (domain, certs, cb) {
count += 1;
console.log('#3 is 2 of 4');
// NOTE: there's a very very small chance this will fail occasionally (if Math.random() < 0.01)
if (!certs) {
throw new Error("should have certs to renew (renewAt)");
}
cb(null, CERT_1);
}
, function (domain, certs, cb) {
count += 1;
console.log('#4 is 3 of 4');
if (!certs) {
throw new Error("should have certs to renew (expiresNear)");
}
cb(null, CERT_2);
}
, function (/*domain, certs, cb*/) {
console.log('#5 should NOT be called');
throw new Error("Should not call register renew a certificate with more than 10 days left");
}
, function (domain, certs, cb) {
count += 1;
console.log('#6 is 4 of 4');
if (certs) {
throw new Error("should not have certs that have been uncached");
}
cb(null, CERT_3);
}
, function (/*domain, certs, cb*/) {
console.log('#7 should NOT be called');
throw new Error("Should not call register renew a non-auto certificate");
}
].map(function (fn) {
return require('bluebird').promisify(fn);
});
// opts = { notBefore, notAfter, letsencrypt.renew, letsencrypt.register, tlsOptions }
var leSni = require('./').create({
notBefore: NOT_BEFORE
, notAfter: NOT_AFTER
, getCertificatesAsync: tests.shift()
, _dbg_now: START_DAY
});
var shared = 0;
var expectedShared = 3;
leSni.sniCallback('example.com', function (err, tlsContext) {
if (err) { throw err; }
shared += 1;
});
leSni.sniCallback('example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #1");
}
leSni.getCertificatesAsync = tests.shift();
leSni.sniCallback('example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #2");
}
leSni.getCertificatesAsync = tests.shift();
leSni._dbg_now = RENEWABLE_DAY;
leSni.sniCallback('www.example.com', function (err, tlsContext) {
if (err) { throw err; }
shared += 1;
});
leSni.sniCallback('example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #3");
}
leSni.getCertificatesAsync = tests.shift();
leSni._dbg_now = EXPIRES_AT;
leSni.sniCallback('www.example.com', function (err, tlsContext) {
if (err) { throw err; }
shared += 1;
});
leSni.sniCallback('www.example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #4");
}
leSni.getCertificatesAsync = tests.shift();
leSni.sniCallback('www.example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #5");
}
leSni.uncacheCerts({
subject: 'example.com'
, altnames: ['example.com', 'www.example.com']
});
leSni.getCertificatesAsync = tests.shift();
leSni.sniCallback('example.com', function (err, tlsContext) {
if (err) { throw err; }
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #6");
}
leSni.getCertificatesAsync = tests.shift();
leSni._dbg_now = RENEWABLE_DAY;
leSni.sniCallback('example.com', function (err, tlsContext) {
if (!tlsContext._fake_tls_context_) {
throw new Error("Did not return tlsContext #7");
}
if (expectedCount !== count) {
throw new Error("getCertificate only called " + count + " times");
}
if (expectedShared !== shared) {
throw new Error("wrongly used only " + shared + " shared promises");
}
if (tests.length) {
throw new Error("some test functions not run");
}
console.log('PASS');
});
});
});
});
});
});
});