Reliable apps with (HA)Proxy — Part 2.

TLS Calzone

For some services, securing and logging access is paramount. For HTTPS traffic you can often get by with Basic HTTP Auth. Managing such solution can become slightly complicated (e.g. you need to implement account and secret management), so you try to find next best thing.

Aside from the crazy modern stuff, there is a simple and very effective solution in the form TLS clients certificates. It is very effective, you can secure TCP or HTTP services, and user management can be pushed out of your application (for example you can use XCA to roll your own CA). It also helps that TLS has built in mechanisms for certificate revocation, so you’re fully covered in that, often overlooked, feature.

frontend myapp
bind :443 ssl crt myapp.pem verify required ca-file ca.pem crl-file crl.pem
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
...

HAProxy is handling the authentication part, and can also provide help with authorization part, by relaying information from the client certificate. Here we pass CommonName from the cert to the backend service (usually, for TLS client certs, that would conceptually match username). This way, your application can properly authorize users, with user info available in HTTP headers. It doesn’t get easier than that for HTTP apps.

There is much more info for TLS client auth with HAProxy in the decade old post from Baptiste.

Wrap Crispy JWT

If you have seen our previous section about TLS client authentication, you might also want to use the same trick for OAuth/JWT tokens. Why should you write the same authentication code over and over , for every service behind load balancer (and often you have service written in different languages, so you don’t get to share the code in the backend). JWT and OAuth are slightly too complicated for this blog post format, so I’ll just show the most interesting configuration parts here. For full setup check out the links. HAProxy setup is interesting since most of the JWT stuff is actually implemented in Lua, as an extension script for HAProxy.

global
...
lua-load /path/to/lua/script/dir/jwtverify.lua
# Replace the Auth0 URL with your own:
setenv OAUTH_ISSUER <https://youraccount.auth0.com/>
setenv OAUTH_AUDIENCE <https://api.example.com>
setenv OAUTH_PUBKEY_PATH /etc/haproxy/pem/pubkey.pem
frontend myapp
bind :443 ssl crt /path/to/cert/myapp.pem alpn h2,http1.1
http-request deny unless { req.hdr(authorization) -m found }
http-request lua.jwtverify
http-request deny unless { var(txn.authorized) -m bool }
...

I also must shout out to Envoy people here, they seem to have implemented much of the necessary functionality for JWT directly in the Envoy.

The TLS Calzone + Wrap Crispy essay is part of a series of "recipes" that explore the ways of bulding reliable applications with (HA)Proxy.PS. If you have any questions on any of the above outlined thoughts, feel free to share them in the comment section.Click here to read Part 3.: Docker Cake + Say my name — Log and resolve doubts

--

--