Skip to content

Commit

Permalink
Feature: Allow multiple Subject Alternative Name (SAN) extensions (#52)
Browse files Browse the repository at this point in the history
* Feature: Adding multiple domains using subject alternative name (SAN)

* Update README with Docker and SAN instructions

* Update readme

* Readme polish

* Tweaks

* Formatting fixes

* Adjust pathForDomain

* Create a stable hash for directory path of SAN listed domains

* Merge SAN with validation features

* Tweak for latest typescript
  • Loading branch information
camsjams authored Jul 14, 2021
1 parent d343e2d commit be273aa
Show file tree
Hide file tree
Showing 9 changed files with 2,719 additions and 43 deletions.
92 changes: 92 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,98 @@ The `certutil` tooling is installed in OS-specific ways:
so devcert will simply fallback to the wizard approach for Firefox outlined
above)

## Multiple domains (SAN)
If you are developing a multi-tenant app or have many apps locally, you can generate a security
certificate using `devcert` to also use the [Subject Alternative Name](https://en.wikipedia.org/wiki/Subject_Alternative_Name)
extension, just pass an array of domains instead.

```js
let ssl = await devcert.certificateFor([
'localhost',
'local.api.example.com',
'local.example.com',
'local.auth.example.com'
]);
https.createServer(ssl, app).listen(3000);
```

## Docker and local development
If you are developing with Docker, one option is to install `devcert` into a base folder in your home directory and
generate certificates for all of your local Docker projects. See comments and caveats in [this issue](https://github.com/davewasmer/devcert/issues/17).

While not elegant, you only really need to do this as often as you add new domains locally, which is probably not very often.

The general script would look something like:

```js
// example: make a directory in home directory such as ~/devcert-util
// ~/devcert-util/generate.js
const fs = require('fs');
const devcert = require('devcert');

// or if its just one domain - devcert.certificateFor('local.example.com')
devcert.certificateFor([
'localhost',
'local.api.example.com',
'local.example.com',
'local.auth.example.com'
])
.then(({key, cert}) => {
fs.writeFileSync('./certs/tls.key', key);
fs.writeFileSync('./certs/tls.cert', cert);
})
.catch(console.error);
```

An easy way to use the files generated from above script is to copy the `~/devcert-util/certs` folder into your Docker projects:
```
# local-docker-project-root/
🗀 certs/
🗎 tls.key
🗎 tls.cert
```

And add this line to your `.gitignore`:
```
certs/
```

These two files can now easily be used by any project, be it Node.js or something else.

In Node, within Docker, simply load the copied certificate files into your https server:
```js
const fs = require('fs');
const Express = require('express');
const app = new Express();
https
.createServer({
key: fs.readFileSync('./certs/tls.key'),
cert: fs.readFileSync('./certs/tls.cert')
}, app)
.listen(3000);
```

Also works with webpack dev server or similar technologies:
```js
// webpack.config.js
const fs = require('fs');

module.exports = {
//...
devServer: {
contentBase: join(__dirname, 'dist'),
host: '0.0.0.0',
public: 'local.api.example.com',
port: 3000,
publicPath: '/',
https: {
key: fs.readFileSync('./certs/tls.key'),
cert: fs.readFileSync('./certs/tls.cert')
}
}
};
```

## How it works

When you ask for a development certificate, devcert will first check to see
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,4 @@ subjectAltName = @subject_alt_names
subjectKeyIdentifier = hash

[ subject_alt_names ]
DNS.1 = <%= domain %>
DNS.2 = *.<%= domain %>
<%= subjectAltNames %>
3 changes: 1 addition & 2 deletions openssl-configurations/domain-certificates.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ extendedKeyUsage = serverAuth
subjectAltName = @subject_alt_names

[ subject_alt_names ]
DNS.1 = <%= domain %>
DNS.2 = *.<%= domain %>
<%= subjectAltNames %>
Loading

0 comments on commit be273aa

Please sign in to comment.