4 ms·
Nice reference piece. I personally have rarely found the need to handle TLS in my application code; even in a cloud-native environment where you want to secure
by cdogl 6y ago
Nice reference piece.
I personally have rarely found the need to handle TLS in my application code; even in a cloud-native environment where you want to secure traffic inside your network, I prefer to do TLS termination in another process (in Kubernetes land this would be a sidecar container in a pod), because {nginx,envoy,caddy,etc} have great TLS support and there are strong standard conventions for how to configure them with the key. It's often much easier for someone to come along and figure figure out how you're configuring a standard HTTP reverse proxy than to figure out some bespoke application configuration when a TLS key needs to be rotated.
This is probably a little naive and I suspect that some highly latency-sensitive applications benefit from the overhead of that additional hop (even if it's over localhost), but I think offloading the TLS workload as its own concern has many benefits.
- debarshri 6y agoI have alot seen IoT devices with embedded certificates handled via application code. In these situations certificate rotation is a full firmware update. Also, places where there is resource constraints to run sidecar. Sidecars, proxies makes quite some sense in cloud setting.
- cdogl 6y agoFair point. I see everything through the lens of my cloud / SaaS niche but Go is now used far more broadly than that.
- Cthulhu_ 6y agoSame; on the one side my Go app will be running as its own webserver, but on the other hand it'll be years before it's ready to run standalone (it's replacing a legacy app); until then it'll be running behind an Apache webserver which also takes care of HTTPS.
- 1vuio0pswjnm7 6y agoI adopted this thinking some time ago. haproxy, stunnel and, to a lesser extent, sslsplit are ones I would add to the list. Letting these programs deal with TLS allows me to use so much more networking software that either will never be TLS-capable or which requires too much attention to constantly monitor whether the developers are using the libraries properly and keeping up with the latest versions.
- 1vuio0pswjnm7 6y agoAs an end user, I MITM TLS so I can see and, if necessary, modify what is being sent from applications. TLS-enabled servers are bound to the loopback. I must have control over what is being sent. If an application denies the user control over what is sent then I will exercise control outside the application. Applications only communicate with the loopback, not the network.
- spacemanmatt 6y agoI came here to muse on basically the same question. Nginx and other TLS termination options seem way more robust than any library I'd write an app server in. After all, this is intended for security, so the dev-op in me dictates: Use a product that is close to bulletproof as possible.
- bombcar 6y agoIt also allows security and other patches even after the application has been abandoned or otherwise ignored (much more important for non-open source applications).
- kitd 6y agoYou're correct from the PoV of the server, but it is still very useful to have the capability built into the standard library for those clients that need to use TLS.
- idoubtit 6y agoIn order to mitigate the latency of using nginx as a reverse-proxy, I recently added a feature to a Haskell application: instead of listening on a TCP port, it can listen on a unix socket. It's not only faster, it also avoids the congestion problems of TCP, and adds security (unix user and group permissions).
- NovemberWhiskey 6y agoThere are a lot of factors. One thing is your compute environment; if there's a really solid way to assure that the connection between your proxy and your service implementation remains secure then that's one thing - however, outside of K8s (or similar) that may not be easy or may be bespoke, and there's a configuration overhead of assuring that proxies run the right place, bind the right ports, expose them only to the right places and so on. Even assuming a good orchestrator, there is that extra degree of assurance in knowing that TLS is actually being terminated in your process. Public CA PKI vs. enterprise PKI also makes a difference; it's easy enough to integrate with LetsEncrypt or whatever using Nginx but your enterprise PKI might be more complex and having SDKs for direct integration into service code might actually be easier. In a large environment, or one where certificates are short-lived, the operational aspect dominates. Level of cloud buy-in is also a factor; for example, if you're deep in AWS then you're probably already hosting behind an AWS load balancer of some sort that knows how to terminate TLS and also knows how to integrate with ACM for automated renewals. Finally, if you need client authentication certificates then you might find your proxy implementation just passes them on to you as headers (or perhaps just does chain validation), which leaves you holding the bag for the rest of that in your service anyway.
- tialaramex 6y agoThis isn't very Zero Trust, it creates a delicious soft centre where there's not even encryption if an adversary can get there. Likely in a small toy system this is all just binaries running inside a VM like the K8s setup you describe - and you could reason that any adversary who is running inside your VM has won already, but on bigger systems this design increasingly makes it likely production will end up with the unencrypted bits moving over at least some sort of internal network. I've built things that worked that way, but I've also built things that deliberately did their own TLS, and I know for sure which I'd have confidence in to protect valuable data.