Bullet proof Django security – How application isolation in Docker improves security in Django servers
When it comes to security, the rule of thumb is, any open vulnerability WILL be exploited sooner than later. Django provides a strong foundation for to build secure web applications, but is that enough? What about server security? It is not uncommon for secure web apps to be hacked due to poor server security.
Let’s take the case of a typical Django web application infrastructure. It would have an Nginx front end, uWSGI application servers, caching servers, and database servers. In some cases the same physical server would host multiple services like Nginx and database servers. I can see you nodding – its all too common.
Now, consider all those other applications you need to run on production. For eg., Puppet configuration management server, JIRA issue tracking software, and so on. Where do you put all those? Yes, of course, the under-utilized Nginx server which is hardly using the 8 GB memory it has. Looks like a sane way to go about things. Or is it?
Poor server security = insecure Django apps
Tight packing different apps and services in the same physical server can open up some serious security loop holes:
- App vulnerabilities affecting server reputation – Remember that issue tracking software you used before you switched to the new one? Is it still online? If you answered yes, you are not alone. Old, un-maintained apps offer an easy way for attackers to upload malware, and most webmasters come to know about it only when their server IPs show up as malware source in search engines.
- Service vulnerabilities affecting data security – This is an even graver cause of concern. It is easy to forget non-critical services like mail server or PHP libraries running in your server when your focus is on your Django app. A critical un-patched vulnerability in a publicly exposed service can give attackers even root access, and soon all your customer data might be at risk.
So, what’s the way out?
As a server management company, we’ve seen that frequent security audits and proactive hardening can go a long way in securing your servers, but a fundamentally secure infrastructure design is the best way to avoid security issues.
The central issue here is that even if you make your Django app very secure, vulnerabilities in other apps can compromise your security. The logical solution to that is to put each application in a different server, or in other words, enforce Application Isolation. You can do app isolation using VPS or cloud instances, but the cost effective way to do that is with container technology.
Django application isolation using Docker
Docker is now a popular name in container server virtualization. Its resource usage is minimal, offers a wide range of server application images, and provides pretty solid container isolation.
Docker uses a Linux technology called namespaces to isolate processes, networking, process communication, mount points, etc., so that there is no way that a process in one container can access another container. This limits the ability of an attacker in a compromised app or service to spread their scope of attack.
Interestingly, Docker brought in a renewed interest in minimal operating systems, some of which (like CoreOS) are built from ground up for security and scalability. A server infrastructure built using CoreOS + Docker gives you a secure foundation for your Django apps. Its benefits are:
- Security through minimalism
- Minimal OS – CoreOS has a tiny footprint with just enough software to support and scale Docker containers. This reduces the surface area for attackers to exploit, and makes vulnerability management very efficient.
- Minimal container – In the same way, Docker containers have just enough packages to support the service running in it. Along with improving the security, it makes resource usage very efficient.
- Security through application isolation – By using the namespaces technology in Linux kernel, your apps are fully isolated from other services that could be compromised.
- Advanced security through AppArmor / SELinux – For augmented security, your containers can be further hardened using Linux kernel security systems like GRSEC, SELinux, AppArmor, etc.
- Minimal cost overhead – Since Docker containers use very little resources, you’d be able to run a Docker based Django infrastructure using the same number of servers you currently have. You do not have to invest in more number of servers.
Sounds good. So, how do I get started?
Dockerising a Django application is worth a full article on its own. However, I’ll go through the main steps involved in putting your Django app in a Docker infrastructure.
- Install a minimal host operating system in your servers.
- Get Docker images for your various services like uWSGI, Nginx, Database servers, Caching servers, etc. from Docker Hub, and run them as separate containers. You can also build one for yourself from a minimal base image like phusion/baseimage.
- In case you install any new packages or customize your environment settings, record that down in a Dockerfile.
- Build server images (aka Docker images) using your Dockerfile, and put them into a private Docker registry.
- Once you have Docker images for all the various services in your infrastructure, create the different service containers in your servers using Docker run.
- Update your deployment scripts (or automation tools) to put your web application code in your new containers. Restart the services, and your Django app is online from your Docker infrastructure.
Securing the server environment is a critical part of Django security. Shared space among various apps and services can lead to major security breaches even if you’ve made the most secure Django application. Application isolation as implemented through Docker is a cost effective way to ensure server security.