Auth doesn't have to be a nightmare — Docker to the rescue!

Preview:

DESCRIPTION

How do you support many different authorization methods (OAUTH, HTTP Basic/Digest, SSL certificates…) for many different apps (a Rails website, a Python/Flask API, realtime events streaming with Node.js, and more…)? We review a bunch of options, and propose an original way to do it with Docker and Containers.

Citation preview

APIStrat SFOctober 2013

Authdoesn’t have to be a

nightmareDockerto therescue!

Jérôme Petazzoni — @jpetazzo

What’s The Problem?

Multiple auths in multiple apps

● OAUTH● OAUTH2● OpenID● SSL client certs● HTTP Basic (in SSL, right?)

● HTTP Digest● IP addresses

(seriously?)

● VPNs, IPSEC● custom tokens

● website(e.g. Ruby on Rails)

● API(e.g. Python+Flask)

● realtime events (e.g. Node.js)

● secret project(Golang, Rust…)

The “Matrix from Hell”of authentication/authorizationOAUTH ? ? ? ? ?OAUTH2 ? ? ? ? ?OpenID ? ? ? ? ?SSL certs ? ? ? ? ?HTTP Basicor Digest ? ? ? ? ?IP addresses,VPN... ? ? ? ? ?custom auth ? ? ? ? ?

Ruby Python Python(Django!)

Java Other langs...

What’s The Solution?

What’s The Solutions?are

Solution 1

Solution 1

● this is actually what most people do● because at first the matrix isn’t that big● then you add more services● want to support more backends● you end up picking one auth method● N implementations instead of MxN

Solution 1

● this is actually what most people do● because at first the matrix isn’t that big● then you add more services● want to support more backends● you end up picking one auth method● N implementations instead of MxN

Grade: C

Solution 1

● this is actually what most people do● because at first the matrix isn’t that big● then you add more services● want to support more backends● you end up picking one (or two) auth method

○ e.g. basic auth over SSL + API tokens● N implementations (or 2xN) instead of MxN

Grade: B

Solution 2

● delegate auth to a proxy/external process

Client

Proxy

Service

Here there be $AUTH

Here there be simple HTTP headers

Solution 2: the problems

● I work on the Ruby API● I don’t want to install the Node.js stuff● but the auth component is in Node.js!● I have to learn how to deploy Node.js● also, deployment is more complex

Solution 2: the problems

● I work on the Ruby API● I don’t want to install the Node.js stuff● but the auth component is in Node.js!● I have to learn how to deploy Node.js● also, deployment is more complex

Grade: B(single lang shops)

Grade: D(everybody else)

Solution 3

Solution 3

● put each component in a VM

Client

Proxy VM

Service VM

Here there be $AUTH

Here there be simple HTTP headers

Solution 3: the problems

● create (and maintain) VM images● VMs are RAM-heavy

○ now you have a good reason to get 16 GB of RAM!● VMs are disk-heavy

○ now you need to download a 500 MB VM to update the auth proxy to test a 4-lines commit

● VM networking is not awesome○ discovery and plumbing can require some voodoo

Solution 3

Grade: B(if you have a vagrant

guru in residence,and super shiny

awesome laptops)

Grade: D(everybody else)

Solution 4: the container

Solution 4: the Linux container

Solution 4

● put each component in a container

Client

Proxy LXC

Service LXC

Here there be $AUTH

Here there be simple HTTP headers

Solution 4: pros and cons

● your dev env must be Linux● or you can use a VM

○ but just one○ no Hogwarts diploma required

● containers are lightweight○ I can run 100 containers on my laptop○ updating a container is more like “git pull”

● networking is easier○ and is getting even more easier!○ service discovery

Solution 4

Grade: ?you tell me at the end

of the presentation

What’s aLinux Container?

What’s a Linux container?High level approach

Lightweight Virtual Machine● looks like a VM● can run stuff as root● can install packages● can run sshd, syslog, cron...

“Machine Container”

What’s a Linux container?Low level approach

Chroot on steroids● normal processes, but isolated● share kernel with the host● doesn’t need to run ssh, syslog, cron...

“Application Container”

What’s a Linux container?Technical approach

Two big sets of kernel features:● namespaces

○ isolate containers○ one namespace cannot see/affect another

● control groups○ meter and limit resources○ CPU, RAM, disk I/O…○ prevent a single container from hogging the host

Note: you can use namespaces and/orcgroups without using containers

What’s Docker?Open Source project

(i.e. satisfaction guaranteed,or your money back)

1. Runtime for Linux containersjpetazzo@tarrasque:~$ sudo docker run -t -i ubuntu bash

root@092ee318746f:/#

→ create an Ubuntu VM, and run a shell in it.

Total time: less than 0.5s

(If necessary, the “ubuntu” imagewill be downloaded automatically.)

But Docker is also...

2. Standard format for containers3. Public place to share them

● library of standard images(ubuntu, fedora, redis, postgresql…)

● create your own images(from scratch or based on existing ones)

● upload them to the public registry(searchable index w/ social features)

● upload them to private registry● 3rd party hosted registries already exist

Real world example:Test this new Ghost blog engine

● Look for “ghost” on http://index.docker.io/● Find orchardup/ghost

jpetazzo@tarrasque:~$ sudo docker run -d orchardup/ghost

c6000fa5ddc6

Total time: <0.5s(+5m to download the image on this hotel WiFi)

Runtime for Linux containersjpetazzo@tarrasque:~$ sudo docker inspect c6000fa5ddc6

...

"PortMapping": {

"Tcp": {

"2368": "49153"

},

...

→ if I run this on a server somewhere, the new service is publicly available on port 49153.

How does the Auth problem fit in?

● create a “HTTP Basic Auth + SSL” container○ based on e.g. existing Nginx container○ inject a custom auth header, e.g. x-username○ strip rogue x-username header (duh!)

● lock the Ghost service so it doesn’t expose its TCP port anymore to the outside world○ but it will still accept connections from containers

● patch the Ghost service to look for the header

WAITHow do I create those container images?

Creating an image with run/commit

1. docker run ubuntu bash2. apt-get install this and that3. docker commit <containerid> <imagename>4. docker run <imagename> bash5. git clone git://.../mycode6. pip install -r requirements.txt7. docker commit <containerid> <imagename>8. repeat steps 4-7 as necessary9. docker tag <imagename> <user/image>

10. docker push <user/image>

Creating an image with a Dockerfile# This is a Dockerfile to build a CouchDB containerFROM ubuntuRUN apt-get -y updateRUN apt-get install -y g++ erlang-dev erlang-base-hipe …RUN apt-get install libmozjs185-dev libicu-dev libtool …RUN apt-get install make wgetRUN wget http://.../apache-couchdb-1.3.1.tar.gz \ | tar -C /tmp -zxf-RUN cd /tmp/apache-couchdb-* && ./configure && make installRUN printf "[httpd]\nport = 8101\nbind_address = 0.0.0.0" \ >/usr/local/etc/couchdb/local.d/docker.iniEXPOSE 8101CMD ["/usr/local/bin/couchdb"]

docker build -t jpetazzo/couchdb .docker push jpetazzo/couchdb

SHAREauth containersapp containers

Solution 4: moment of truth

● we just built perfect packages:○ distro-independent○ without dependency issues○ that can run in dev, staging, production

● without getting our hands dirty○ and barely rolling up our sleeves

● we can share them with other projects/shops

Please allow me to verbosely formulate my genuine enthusiasm.

BONUSWe can ship our code with those containers

Deploying Containers

● docker pull + docker run from registry● Docker can be controlled through REST API,

so you can control a fleet of Docker hosts● PAAS-like: Cocaine, Deis, Maestro…

♥ OpenStack?● Nova can deploy Docker containers (since Havana)

● Heat can deploy Docker containers (since last week)

Thank you!Questions?

twitter.com/jpetazzotwitter.com/dockerhttp://docker.io/https://github.com/dotcloud/docker

Future of Docker

● service discovery(containers will be able to discover resources)

● compatibility with Red Hat Enterprise Linux(currently Docker runs best on Ubuntu)

● support for other runtimes and storage(Jails, Zones, BTRFS, ZFS…)