Using a local development trusted CA on MacOS
TLS certificates are so ubiquitous that you now very often need them even during the development phase.
Developers are thus used to create “self-signed” certificates and configure their client requiring TLS support to accept self-signed certificates. This can be fine for development: As both the client and the server are on the same computer, the risk of man-in-the-middle attacks is limited. However, this can still be a dangerous setup, as you take the risk to forget the option and ship to production a client that accepts self-signed certificates. It would thus be vulnerable to man-in-the-middle attacks and defeat the purpose of using TLS in the first place.
We can help you build your next macOS app in weeks rather than months
Read more about ProcessOne and Swift »
The best approach is to create your own local certificate authority for development and to have your development computer trust that root CA. This article will show how to configure such an environment on MacOS with both ejabberd and Phoenix. If you are developing on Linux however, you should be able to use mkcert
as well and can skip the part on setting up the iOS simulator.
Note: Be careful not to share your root CA key, as it could be exploited to run targeted man-in-the-middle attacks against your development computer.
Creating the local trusted Certificate Authority
The mkcert project is making this setup very easy.
First, install mkcert on your Mac, for example with Homebrew:
$ brew install mkcert
$ brew install nss # if you use Firefox
Then, create your CA root certificate and install it in your trusted store (it will ask your admin password):
$ mkcert -install
Using the local CA at "/Users/mremond/Library/Application Support/mkcert"
The local CA is now installed in the Firefox trust store (requires browser restart)! ????
Finally, create your signed certificate for your localhost:
$ mkcert localhost 127.0.0.1 ::1
Using the local CA at "/Users/mremond/Library/Application Support/mkcert"
Created a new certificate valid for the following names ????
- "localhost"
- "127.0.0.1"
- "::1"
The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem"
You should now be able to use Safari or Firefox with a service using that new certificate without having any SSL trust warning.
Installing your root certificate in your iOS simulator and development device
When developing iOS applications, you have to use HTTPS or secure Websocket (or have to set a temporary exception in your project info.plist). Reusing your local certificate authority is thus the best approach as well during development. You just have to tell iOS to trust your local CA.
- Drag and drop the
rootCA.pem
file on your simulator. That file is locating in the directory~/Library/Application Support/mkcert
. The simulator will open Safari and offer you to download the file. - Accept the file download. Safari will then confirm that the file has been added to your profiles.
You now need to install it from the setting to trust it.
- Go to the Settings app and then to “General -> Profile”. Select your new mkcert profile and click install and then confirm installation. The root certificate should now be displayed as verified.
- Still in the Settings app, you can now go to “General -> About -> Certificate Trust Settings” to enable full trust for that root certificate.
You will now have no trust warning when you connect on HTTPS on localhost on a site using your signed cert. You can also use HTTPS or Secure Websockets from a development iOS app, without any workaround.
You can use a similar approach on your development device to have your device download the rootCA.pem
file and ensure the OS will trust it.
Configuring your server applications to use your signed certificates
ejabberd
Configuring ejabberd to use your signed development certificate can be done copying your localhost+2.pem
and localhost+2-key.pem
file to ejabberd config directory and referring to them in the config file:
hosts:
- localhost
...
certfiles:
- localhost+2-key.pem
- localhost+2.pem
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: true
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
"/admin": ejabberd_web_admin
"/api": mod_http_api
"/bosh": mod_bosh
"/captcha": ejabberd_captcha
"/upload": mod_http_upload
"/ws": ejabberd_http_ws
"/oauth": ejabberd_oauth
You should now be able to use ejabberd https service on https://localhost:5443
without any warning. You thus can use secure Websocket and BOSH over HTTPS.
Phoenix
Copy your localhost key and cert to your Phoenix project directory priv/cert
:
$ mkdir priv/cert
$ mv localhost+2* priv/cert
Update the file config/dev.exs
to use your localhost development key and cert. Add your https configuration in your endpoint config:
https: [
port: 4001,
cipher_suite: :strong,
keyfile: "priv/cert/localhost+2-key.pem",
certfile: "priv/cert/localhost+2.pem"
],
Now, when you start your development server with mix phx.server
, it will support a new trusted https service on port 4001.
Photo by Christopher Gower, Unsplash.