node package manager
Loosely couple your services. Use Orgs to version and reuse your code. Create a free org »

peerca

peerca

generate ssl certificates for peer authentication

build status

Instead of paying a lot of money to get a certificate signed by an NSA-approved certificate authority, with peerca each server explicitly signs the certificates that are allowed to connect to it. This is similar to how the authorized_keys file works in ssh but for TLS certificates.

This package mostly shells out to openssl commands.

example

tls authentication

In this example we'll set up certificates locally and on a remote server.

First, install peerca everywhere:

$ npm install -g peerca
$ ssh substack.net 'npm install -g peerca'

Generate tls keys and certificates:

$ peerca generate
$ ssh substack.net 'peerca generate -h substack.net'

Send the local certificates to the remote server, sign them on the remote server under the name substack-laptop, and save the result:

$ peerca request \
  | ssh substack.net 'peerca authorize substack-laptop' \
  | peerca save substack.net

Now we can build a tls client locally that fetches tls options for connecting to substack.net:

var tls = require('tls');
var ca = require('peerca')();
var opts = ca.options('substack.net');
 
var stream = tls.connect(7007, 'substack.net', opts);
stream.pipe(process.stdout);

and on substack.net we can spin up a server:

var tls = require('tls');
var ca = require('peerca')({ host: 'substack.net' });
var opts = ca.options();
 
var server = tls.createServer(opts, function (stream) {
    stream.end('beep boop\n');
});
server.listen(7007);

docker authentication

The certificates generated by peerca are useful for configuring shared access to any server that can use tls client certificates for verification. Docker is one such service.

If you don't have keys generated already, on each side generate them with:

$ peerca generate
$ ssh substack.net 'peerca generate'

Now sign the local certificates with the remote key:

$ peerca request \
  | ssh substack.net 'peerca authorize substack-laptop' \
  | peerca save substack.net

On the remote side, run docker with tls verification:

$ ssh substack.net 'sudo docker -d --tlsverify
  --tlscacert=`peerca file ca` \
  --tlscert=`peerca file cert` \
  --tlskey=`peerca file key` \
  -H=0.0.0.0:2376'

and on the local side, use peerca file to fetch the appropriate keys for the server name:

$ docker --tlsverify \
  --tlscacert=`peerca file ca -c substack.net` \
  --tlscert=`peerca file cert -c substack.net` \
  --tlskey=`peerca file key -c substack.net` \
  -H=substack.net:2376 \
  ps

usage

peerca COMMAND OPTIONS
 
  peerca generate
 
    Generate certificate files.
 
  peerca request {-o CERTREQ}
 
    Create a certificate request and write to CERTREQ or stdout.
 
  peerca authorize {-i CERTREQ | -o CERTAR }
 
    Sign a certificate request file CERTREQ or stdin,
    writing to a certificate archive file CERTAR or stdout.
 
  peerca save NAME {-i CERTAR}
 
    Add a certificate archive from a file CERTAR or stdin for a domain NAME.
 
  peerca file key             Print the private key file path.
  peerca file cert            Print the certificate file.
  peerca file cert -c REMOTE  Certificate file for connecting to REMOTE.
  peerca file ca              Certificate authority file.
  peerca file ca -c REMOTE    CA file for connecting to REMOTE.
 
  peerca list host          Print each host in DIR.
  peerca list authorized    Print each authorized name.
  peerca list saved         Print each saved connection name.
 
  peerca hash
 
    Print the fingerprint hash for HOST in DIR.
 
  GLOBAL OPTIONS
  
    -d DIR   Profile directory. If not provided uses the environment
             variable $PEERCA_PATH or ~/.config/peerca
    -h HOST  Domain name (FQDN) to use. If not provided uses the
             environment variable $PEERCA_HOST or "localhost"
 

methods

var peerca = require('peerca')

var ca = peerca(opts)

Create a peerca instance ca from options:

  • opts.dir - configuration directory, default: $PEERCA_PATH or '~/.config/peerca'
  • opts.host - hostname, default: $PEERCA_HOST or 'localhost'

ca.generate(host=ca.host, cb)

Generate certificate and key files on disk in the configuration directory. cb(err) fires when the files have been written successfully or an error occurs.

ca.fingerprint(host=ca.host, cb)

Calculate the fingerprint of the local public certificate in cb(err, hash).

var rstream = ca.request()

Return a readable stream rstream with a certificate request that should be piped into a remote ca.authorize().

var dstream = ca.authorize(host)

Return a duplex stream dstream that accepts a certificate request stream from a remote ca.request() as input and produces a certificate archive that should be fed back into ca.save() on the same remote host.

var wstream = ca.save(host)

Return a writable stream wstream that saves the certificate archive for the remote host.

ca.list(name, cb)

For each name, call cb(err, ls) with a list of results. The named lists to use for name are:

  • 'host' - hosts configured in the configuration directory
  • 'authorized' - hosts authorized with .authorize()
  • 'saved' - names saved with .save()

var files = ca.files(host)

Return the file paths for certificates and keys necessary to connect to host. To create a server, omit the host argument.

var opts = ca.options(host)

Return the certificates and keys necessary to connect to host as an object mapping keys to buffers that you can pass in directly to tls.connect() or tls.createServer().

This method reads the options synchronously, so you should only use this method when you first start up a process.

install

With npm do:

npm install peerca

license

MIT