Ephemeral Docker jails for running untrusted Ruby code.
Hoosegow runs both in your code and in a Docker container. When you call a method on a Hoosegow instance, it proxies the method call to another instance of Hoosegow running inside a Docker container.
Hoosegow is intended to add a layer of security to projects that need to run code that is not fully trusted/audited. Because the untrusted code is running inside a Docker container, an attacker who manages to exploit a vulnerability in the code must also break out of the Docker container before gaining any access to the host system.
This means that Hoosegow is only as strong as Docker. Docker employs Kernel namespaces, capabilities, and cgroups to contain processes running inside a container. This is not true virtualization though, and a process running as root inside the container can compromise the host system. Any privilege escalation bugs in the host Kernel could also be used to become root and compromise the host machine. Further hardening of the base Ubuntu image, along with tools like AppArmor or SE-Linux can improve the security posture of an application relying on Hoosegow/Docker.
The following are some useful resources regarding the security of Docker:
- The Docker Security article from Docker.io.
- The LXC, Docker, Security slides from Jérôme Petazzoni.
- The series of Docker security articles from Daniel J. Walsh (one, two).
Gems are available from the releases page. Download a gem to
vendor/cache directory, and add this to your Gemfile:
Defining Methods to Proxy
You need to define the methods you want to have run in the Docker container. To do this, you need to create a
inmate.rb file that defines a
Hoosegow::Inmate module. Any methods on this module will be available on
Hoosegow instances and will be proxied to the Docker container. Here is an example
class Hoosegow module Inmate def reverse(input) input.reverse end end end
inmate.rb file should be in its own folder, with an optional
Gemfile to specify dependencies. This directory will be copied to the Docker container at build time so your methods are available to be proxied to. You specify the location of the directory containing the
inmate.rb file when instantiating a
hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps") hoosegow.reverse "foobar" #=> "raboof"
Building the Docker Image
Before you can start using Hoosegow, you need to build the Docker image that Hoosegow will proxy method calls to. This can be done in a rake task or bootstrap script:
hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps") hoosegow.build_image hoosegow.image_name #=> "hoosegow:2f8f155e72828ddab9bd8bd0e355c47fb01a5323"
The image will need to be rebuilt with any changes to Hoosegow or the
inmate.rb file. If the image is built ahead of time (by a rake task or bootstrap script), you can pass the name of the image to use when instantiating a Hoosegow instance:
ENV['HOOSEGOW_IMAGE'] #=> "hoosegow:2f8f155e72828ddab9bd8bd0e355c47fb01a5323" hoosegow = Hoosegow.new :inmate_dir => File.join(RAILS_ROOT, "hoosegow_deps") :image_name => ENV['HOOSEGOW_IMAGE']
Configuring the Connection to Docker
By default Docker's API listens locally on a Unix socket. If you are running Docker with it's default configuration, you don't need to worry about configuring Hoosegow.
Configure Hoosegow to connect to a non-standard Unix socket.
Hoosegow.new :socket => '/path/to/socket'
Configure Hoosegow to connect to a Docker daemon running on another computer.
Hoosegow.new :host => '192.168.1.192', :port => 4243