Enabling TLS in the Dev Loop: Self-Signed Certs, nip, and edgestack.me

Fast feedback without compromising on production-like config

Daniel Bryant
Ambassador Labs

--

Photo by Jonatan Pie on Unsplash

If you have ever worked on a greenfield web-based application you will have experienced the pain of testing your application with TLS enabled. It’s easy to spin up an app or microservice and access this via an IP address or localhost, but this isn’t a fully qualified domain name and doesn’t quite behave in the same way. And if you’re containerizing your app and deploying to something like Kubernetes, then you’ll potentially want to configure your API gateway to terminate TLS before proxying requests through.

So what are your options?

Self-Signed Certificates

There are many instructions to be found online for using OpenSSL to generate a self-signed certificate.

The advantages of this approach is relative simplicity. Providing you can install OpenSSL on your local machine it is typically a case of generating a private key and self-signed certificate and loading this into your application server or API gateway. Unless you’re dealing with SNI or using a gateway that handles the certificate chain in a complicated way, this should be relatively straightforward.

The disadvantages to this technique is that a lot of clients (quite rightly) don’t work well with self-signed certificates. For example, Chrome tries to make it very difficult to view pages with invalid TLS certificates. You can set config flags or type a secret password, but this isn’t ideal, especially for automated testing.

If you’re testing via mobile apps then you will have to explicitly trust the self-signed server certificate in your code, but even this isn’t a foolproof solution, for example, you’re using certificate pinning.

nip.io

The nip.io service is a “dead simple wildcard DNS for any IP Address”, and it allows you to map example domain names like magic.127.0.0.1.nip.io to 127.0.0.1. This means that you can spin up a Docker for Mac/Windows or minikube cluster locally, and route traffic to this via the nip.io URL.

The advantages are that this is a very easy and powerful solution for generating domain names that map to a local app or Kubernetes cluster, and you can use this domain name with a public CA to avoid the need to use self-signed certificates.

The primary disadvantage is that you are relying on an external service, which means your dev loop is coupled with the SLA (or lack thereof) from this service. I’m sure we’ve all experienced the pain when GitHub briefly stops working…

nip.io is very flexible and you can even use dash notation, such as magic-127–0–0–1.nip.io, which allows you to use the free LetsEncrypt (a nonprofit public CA) to generate TLS certificates, as it’s just a regular sub-domain of nip.io You will need to take care in regards to any rate-limiting across the services (generating certs etc), as this could impact your fast dev loop.

Custom domain (or edgestack.me) and Let’s Encrypt

If you already have a custom domain name, then you have more options. I’ve already mentioned the Let’s Encrypt service, and there are of course a range of free and paid DNS service providers. However, you typically have to wire these up together, and if you’re deploying apps to Kubernetes you will need to use something like ExternalDNS to keep everything synchronized.

If you’re working with Kubernetes the Ambassador Labs team have made this process easier for you to get started with: simply deploy the Ambassador API gateway via edgectl. This tool asks a series of questions about where your deployed app is located and provisions an edgestack.me domain name and associated TLS certificate.

If you already have your own domain name you can also visit the K8s Initializer and answer a few questions to spin up an application-ready cluster with Ingress, CD, and observability tooling, and then follow the ACME instructions to configure a Let’s Encrypt TLS certificate. This is useful for use cases that involve cloud deployments where you may have various load balancers and networking config in the mix (e.g. AWS ALB vs NLB).

The advantages of this approach is the production-like realism. The closer your development testing playground is to production, the more confidence you can build that your application will work correctly when deployed live.

The disadvantages are that there can be more moving parts, and the dev loop can become slow due to the local coding to remote deployment loop. This is typically resolved by using local-to-remote tooling like Telepresence, Tilt, or Skaffold.

Don’t compromise on security testing

Testing that applications and microservices can be run securely is table stakes today. Cyber crime and hacking are both big business and relatively easy for opportunists to get involved in. Running your local dev loop and testing with security features like TLS-enabled shouldn’t be a blocker.

--

--

DevRel and Technical GTM Leader | News/Podcasts @InfoQ | Web 1.0/2.0 coder, platform engineer, Java Champion, CS PhD | cloud, K8s, APIs, IPAs | learner/teacher