ssl-root-cas
Advanced tools
Comparing version 1.1.10 to 1.1.11
@@ -12,3 +12,2 @@ 'use strict'; | ||
, outputPemsDir | ||
, Promise = require('es6-promise').Promise | ||
; | ||
@@ -186,3 +185,5 @@ | ||
function run(filename) { | ||
return new Promise(function (resolve, reject) { | ||
var PromiseA = require('es6-promise').Promise; | ||
return new PromiseA(function (resolve, reject) { | ||
if (!filename) { | ||
@@ -205,3 +206,3 @@ console.error("Error: No file specified"); | ||
fs.mkdirSync(outputPemsDir); | ||
} | ||
} | ||
@@ -223,2 +224,8 @@ console.info("Loading latest certificates from " + CERTDB_URL); | ||
if (response.headers['content-type'] !== 'text/plain') { | ||
console.error("Fetching failed with incorrect content type %s", response.headers['content-type']); | ||
reject({ code: 2, error: "Fetching failed with incorrect content type " + response.headers['content-type'] }); | ||
return; | ||
} | ||
var lines = body.split("\n") | ||
@@ -225,0 +232,0 @@ , certs = parseCertData(lines) |
{ | ||
"name": "ssl-root-cas", | ||
"version": "1.1.10", | ||
"version": "1.1.11", | ||
"description": "The module you need to solve node's SSL woes when including a custom certificate.", | ||
@@ -31,5 +31,5 @@ "main": "ssl-root-cas", | ||
"dependencies": { | ||
"es6-promise": "^2.0.0", | ||
"es6-promise": "^3.2.1", | ||
"request": "^2.47.0" | ||
} | ||
} |
203
README.md
@@ -0,5 +1,44 @@ | ||
IMPORTANT: Try this first | ||
========= | ||
2015-Jul-13: I just discovered that the most common reason you would have the kind of problems this module solves is actually due to **failing to properly bundle the Intermediate CAs** with the server certificate. | ||
**Incorrect Example** | ||
```js | ||
// INCORRECT (but might still work) | ||
var server https.createServer({ | ||
key: fs.readFileSync('privkey.pem', 'ascii') | ||
, cert: fs.readFileSync('cert.pem', 'ascii') // a PEM containing ONLY the SERVER certificate | ||
}); | ||
``` | ||
**Correct Example** | ||
```js | ||
// CORRECT (should always work) | ||
var server https.createServer({ | ||
key: fs.readFileSync('privkey.pem', 'ascii') | ||
, cert: fs.readFileSync('fullchain.pem', 'ascii') // a PEM containing the SERVER and ALL INTERMEDIATES | ||
}); | ||
``` | ||
**Example `fullchain.pem`** | ||
``` | ||
cat \ | ||
cert.pem \ | ||
intermediate-twice-removed.pem \ | ||
interemediate-once-removed.pem \ | ||
> fullchain.pem | ||
``` | ||
Note that you **should not** include the `root.pem` in the bundle and that the bundle should be constructed with the least authoritative certificate first - your server's certificate, followed by the furthest removed intermediate, and then the next closest to the root, etc. | ||
Also note that in the case of cross-signed certificates (typically only issued from new root certificate authorities) there may be more than one intermediate at equal distances, in which case either in that tier may come first. | ||
SSL Root CAs | ||
================= | ||
The module you need to solve node's SSL woes when including a custom certificate. | ||
The module you need to solve node's SSL woes when including a custom certificate. Particularly, if you need to add a **non-standard Root CA**, then this is the right module for you. | ||
@@ -12,2 +51,8 @@ Let's say you're trying to connect to a site with a cheap-o SSL cert - | ||
**Common Errors** | ||
* `CERT_UNTRUSTED` - the common root CAs are missing, this module fixes that. | ||
* `UNABLE_TO_VERIFY_LEAF_SIGNATURE` could be either the same as the above, or the below | ||
* `unable to verify the first certificate` - the intermediate certificate wasn't bundled along with the server certificate, you'll need to fix that | ||
This module is the solution to your woes! | ||
@@ -116,3 +161,50 @@ | ||
BAD IDEAS | ||
Kinda Bad Ideas | ||
===== | ||
```javascript | ||
'use strict'; | ||
var request = require('request'); | ||
var agentOptions; | ||
var agent; | ||
agentOptions = { | ||
host: 'www.example.com' | ||
, port: '443' | ||
, path: '/' | ||
, rejectUnauthorized: false | ||
}; | ||
agent = new https.Agent(agentOptions); | ||
request({ | ||
url: "https://www.example.com/api/endpoint" | ||
, method: 'GET' | ||
, agent: agent | ||
}, function (err, resp, body) { | ||
// ... | ||
}); | ||
``` | ||
By using an `agent` with `rejectUnauthorized` you at limit the security vulnerability to the requests that deal with that one site instead of making your entire node process completely, utterly insecure. | ||
### Other Options | ||
If you were using a self-signed cert you would add this option: | ||
```javascript | ||
agentOptions.ca = [ selfSignedRootCaPemCrtBuffer ]; | ||
``` | ||
For trusted-peer connections you would also add these 2 options: | ||
```javascript | ||
agentOptions.key = clientPemKeyBuffer; | ||
agentOptions.cert = clientPemCrtSignedBySelfSignedRootCaBuffer; | ||
``` | ||
REALLY Bad Ideas | ||
=== | ||
@@ -137,4 +229,7 @@ | ||
# Index | ||
It's unfortunate that `process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';` is even documented. It should only be used for debugging and should never make it into in sort of code that runs in the wild. Almost every library that runs atop `https` has a way of passing agent options through. Those that don't should be fixed. | ||
# Appendix | ||
Other information you might want to know while you're here. | ||
@@ -147,3 +242,3 @@ | ||
``` | ||
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr | ||
openssl req -new -sha256 -newkey rsa:2048 -nodes -keyout server.key -out server.csr | ||
``` | ||
@@ -161,7 +256,7 @@ | ||
That creates a sha-1 hash. | ||
That created a signing request with a sha-256 hash. | ||
When you submit that to the likes of RapidSSL you'll get back an X.509 that you should call `server.crt` (at least for the purposes of this mini-tutorial). | ||
When you submit that to the likes of RapidSSL you'll get back an X.509 that you should call `server.crt.pem` (at least for the purposes of this mini-tutorial). | ||
You cannot use "bundled" certificates (`.pem`) with node.js. | ||
You **must** use a bundled certificate for your server (the server and intermediates, **not** root), but you cannot use bundles `ca` property. | ||
@@ -175,10 +270,9 @@ ### A single HTTPS server | ||
var https = require('https') | ||
, fs = require('fs') | ||
, connect = require('connect') | ||
, app = connect() | ||
, sslOptions | ||
, server | ||
, port = 4080 | ||
; | ||
var https = require('https'); | ||
var fs = require('fs'); | ||
var express = require('express'); | ||
var app = express(); | ||
var sslOptions; | ||
var server; | ||
var port = 4080; | ||
@@ -188,8 +282,12 @@ require('ssl-root-cas/latest') | ||
.addFile(__dirname + '/ssl/Geotrust Cross Root CA.txt') | ||
.addFile(__dirname + '/ssl/Rapid SSL CA.txt') | ||
// NOTE: intermediate certificates should be bundled with | ||
// the site's certificate, which is issued by the server | ||
// when you connect. You only need to add them here if the | ||
// server is misconfigured and you can't change it | ||
//.addFile(__dirname + '/ssl/Rapid SSL CA.txt') | ||
; | ||
sslOptions = { | ||
key: fs.readFileSync('./ssl/server.key') | ||
, cert: fs.readFileSync('./ssl/server.crt') | ||
key: fs.readFileSync('./ssl/privkey.pem') | ||
, cert: fs.readFileSync('./ssl/fullchain.pem') | ||
}; | ||
@@ -201,3 +299,5 @@ | ||
server = https.createServer(sslOptions, app).listen(port, function(){ | ||
server = https.createServer(sslOptions); | ||
server.on('request', app); | ||
server.listen(port, function(){ | ||
console.log('Listening on https://' + server.address().address + ':' + server.address().port); | ||
@@ -218,16 +318,18 @@ }); | ||
``` | ||
webapps/ | ||
└── vhosts | ||
/etc/letsencrypt | ||
└── live | ||
├── aj.the.dj | ||
│ └── ssl | ||
│ ├── server.crt | ||
│ └── server.key | ||
│ ├── cert.pem // contains my server certificate | ||
│ ├── chain.pem // contains RapidSSL intermediate | ||
│ ├── cert+chain.pem // contains both | ||
│ └── privkey.pem // my private key | ||
├── ballprovo.com | ||
│ └── ssl | ||
│ ├── server.crt | ||
│ └── server.key | ||
│ ├── cert.pem | ||
│ ├── chain.pem | ||
│ ├── cert+chain.pem | ||
│ └── privkey.pem | ||
├── server.js | ||
└── ssl | ||
├── Geotrust Cross Root CA.txt | ||
└── Rapid SSL CA.txt | ||
├── Geotrust Cross Root CA.txt // the Root Authority | ||
└── Rapid SSL CA.txt // the Intermediate Authority | ||
``` | ||
@@ -241,25 +343,24 @@ | ||
var https = require('https') | ||
, http = require('http') | ||
, fs = require('fs') | ||
, crypto = require('crypto') | ||
, connect = require('connect') | ||
, vhost = require('vhost') | ||
var https = require('https'); | ||
var http = require('http'); | ||
var fs = require('fs'); | ||
var crypto = require('crypto'); | ||
var express = require('express'); | ||
var vhost = require('vhost'); | ||
// connect / express app | ||
, app = connect() | ||
var app = express(); | ||
// SSL Server | ||
, secureContexts = {} | ||
, secureOpts | ||
, secureServer | ||
, securePort = 4443 | ||
var secureContexts = {}; | ||
var secureOpts; | ||
var secureServer; | ||
var securePort = 4443; | ||
// force SSL upgrade server | ||
, server | ||
, port = 4080 | ||
var server; | ||
var port = 4080; | ||
// the ssl domains I have | ||
, domains = ['aj.the.dj', 'ballprovo.com'] | ||
; | ||
var domains = ['aj.the.dj', 'ballprovo.com']; | ||
@@ -269,3 +370,3 @@ require('ssl-root-cas/latest') | ||
.addFile(__dirname + '/ssl/Geotrust Cross Root CA.txt') | ||
.addFile(__dirname + '/ssl/Rapid SSL CA.txt') | ||
//.addFile(__dirname + '/ssl/Rapid SSL CA.txt') | ||
; | ||
@@ -286,4 +387,4 @@ | ||
secureContexts[domain] = crypto.createCredentials({ | ||
key: fs.readFileSync(__dirname + '/' + domain + '/ssl/server.key') | ||
, cert: fs.readFileSync(__dirname + '/' + domain + '/ssl/server.crt') | ||
key: fs.readFileSync(__dirname + '/' + domain + '/privkey.pem') | ||
, cert: fs.readFileSync(__dirname + '/' + domain + '/cert+chain.pem') | ||
}).context; | ||
@@ -308,4 +409,4 @@ | ||
// fallback / default domain | ||
, key: fs.readFileSync(__dirname + '/aj.the.dj/ssl/server.key') | ||
, cert: fs.readFileSync(__dirname + '/aj.the.dj/ssl/server.crt') | ||
, key: fs.readFileSync(__dirname + '/aj.the.dj/privkey.pem') | ||
, cert: fs.readFileSync(__dirname + '/aj.the.dj/cert+chain.pem') | ||
}; | ||
@@ -342,5 +443,5 @@ | ||
* [http://greengeckodesign.com/blog/2013/06/15/creating-an-ssl-certificate-for-node-dot-js/](Creating an SSL Certificate for node.js) | ||
* [http://www.hacksparrow.com/express-js-https-server-client-example.html/comment-page-1](HTTPS Trusted Peer Example) | ||
* [Creating an SSL Certificate for node.js](http://greengeckodesign.com/blog/2013/06/15/creating-an-ssl-certificate-for-node-dot-js/) | ||
* [HTTPS Trusted Peer Example](http://www.hacksparrow.com/express-js-https-server-client-example.html/comment-page-1) | ||
* [How to Create a CSR for HTTPS SSL (demo with name.com, node.js)](http://blog.coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/) | ||
* [coolaj86/Painless-Self-Signed-Certificates-in-node](https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js) |
366624
4576
434
+ Addedes6-promise@3.3.1(transitive)
- Removedes6-promise@2.3.0(transitive)
Updatedes6-promise@^3.2.1