working example with self-signed certificates

This commit is contained in:
AJ ONeal 2014-07-15 03:20:49 +00:00
parent 0e66e66dc8
commit 1b5ba16ad6
6 changed files with 227 additions and 1 deletions

View File

@ -1,4 +1,83 @@
nodejs-self-signed-certificate-example
======================================
The end off all your self-sign certificate woes (in node.js at least)
An example that works.
The end off all your self-signed certificate woes (in node.js at least)
Test for yourself
---
This is an easy-as-git-clone example that will get you on your way without
any `DEPTH_ZERO_SELF_SIGNED_CERT` or `SSL certificate problem: Invalid certificate chain` headaches.
### Get the repo
```bash
git clone git@github.com:coolaj86/nodejs-self-signed-certificate-example.git
pushd nodejs-self-signed-certificate-example
npm install
```
**For the super impatient**:
```bash
bash test.sh
```
### Create certificates for `local.ldsconnect.org`
`local.ldsconnect.org` points to `localhost`, so it's ideal for your first test.
```bash
bash make-root-ca-and-certificates.sh 'local.ldsconnect.org'
```
### Run the server
```bash
node ./serve.js 4443 &
# use `fg` and `ctrl+c` to kill
```
### Test in a client
Visit in a web browser
<https://local.ldsconnect.org>
Test (warning free) in node.js
```bash
node ./request-without-warnings.js 4443
```
Test (warning free) with cURL
```bash
curl -v https://local.ldsconnect.org \
--cacert client/my-private-root-ca.crt.pem
```
Now season to taste
---
You can poke around in the files for generating the certificates,
but all you really have to do is replace `local.ldsconnect.org`
with your very own domain name.
But where's the magic?
====
Who's the man behind the curtain you ask?
Well... I lied. This demo doesn't use self-signed certificates.
It uses a self-signed Root CA and a signed certificate.
It turns out that self-signed certificates were designed to be
used by the Root Certificate Authorities, not by web servers.
So instead of trying to work through eleventeen brazillion errors
about self-signed certs, you can just create an authority and then
add the authority to your chain (viola, now it's trusted).

View File

@ -0,0 +1,48 @@
#!/bin/bash
FQDN=$1
# make directories to work from
mkdir -p server/ client/ all/
# Create your very own Root Certificate Authority
openssl genrsa \
-out all/my-private-root-ca.key.pem \
2048
# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
openssl req \
-x509 \
-new \
-nodes \
-key all/my-private-root-ca.key.pem \
-days 1024 \
-out all/my-private-root-ca.crt.pem \
-subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"
# Create a Device Certificate for each domain,
# such as example.com, *.example.com, awesome.example.com
# NOTE: You MUST match CN to the domain name or ip address you want to use
openssl genrsa \
-out all/my-server.key.pem \
2048
# Create a request from your Device, which your Root CA will sign
openssl req -new \
-key all/my-server.key.pem \
-out all/my-server.csr.pem \
-subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}"
# Sign the request from Device with your Root CA
openssl x509 \
-req -in all/my-server.csr.pem \
-CA all/my-private-root-ca.crt.pem \
-CAkey all/my-private-root-ca.key.pem \
-CAcreateserial \
-out all/my-server.crt.pem \
-days 500
# Put things in their proper place
rsync -a all/my-server.{key,crt}.pem server/
rsync -a all/my-private-root-ca.crt.pem server/
rsync -a all/my-private-root-ca.crt.pem client/

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "nodejs-self-signed-certificate-example",
"version": "1.0.0",
"description": "The end off all your self-sign certificate woes (in node.js at least)",
"main": "serve.js",
"scripts": {
"test": "bash test.sh"
},
"repository": {
"type": "git",
"url": "git://github.com/coolaj86/nodejs-self-signed-certificate-example.git"
},
"keywords": [
"nodejs",
"ssl",
"self-signed",
"certificate",
"authority",
"certificates",
"root",
"ca",
"cas"
],
"author": "AJ ONeal <awesome@coolaj86.com> (http://coolaj86.com)",
"license": "Apache-2",
"bugs": {
"url": "https://github.com/coolaj86/nodejs-self-signed-certificate-example/issues"
},
"homepage": "https://github.com/coolaj86/nodejs-self-signed-certificate-example",
"dependencies": {
"ssl-root-cas": "^1.1.4"
}
}

21
request-without-warnings.js Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env node
'use strict';
var https = require('https')
, fs = require('fs')
, path = require('path')
, ca = fs.readFileSync(path.join(__dirname, 'client', 'my-private-root-ca.crt.pem'))
, port = process.argv[2] || 4443
;
var options = {
host: 'local.ldsconnect.org'
, port: port
, path: '/'
, ca: ca
};
options.agent = new https.Agent(options);
https.request(options, function(res) {
res.pipe(process.stdout);
}).end();

35
serve.js Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env node
'use strict';
var https = require('https')
, port = process.argv[2] || 4443
, fs = require('fs')
, path = require('path')
, server
, options
;
require('ssl-root-cas')
.inject()
.addFile(path.join(__dirname, 'server', 'my-private-root-ca.crt.pem'))
;
options = {
key: fs.readFileSync(path.join(__dirname, 'server', 'my-server.key.pem'))
// You don't need to specify `ca`, it's done by `ssl-root-cas`
//, ca: [ fs.readFileSync(path.join(__dirname, 'server', 'my-private-root-ca.crt.pem'))]
, cert: fs.readFileSync(path.join(__dirname, 'server', 'my-server.crt.pem'))
};
function app(req, res) {
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, encrypted world!');
}
server = https.createServer(options, app).listen(port, function () {
port = server.address().port;
console.log('Listening on https://127.0.0.1:' + port);
console.log('Listening on https://' + server.address().address + ':' + port);
console.log('Listening on https://local.ldsconnect.org:' + port);
});

10
test.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
bash make-root-ca-and-certificates.sh 'local.ldsconnect.org'
node ./serve.js &
sleep 2
node ./request-without-warnings.js
echo ""