• This repository has been archived on 28/Aug/2019
  • Stars
    star
    1,282
  • Rank 36,705 (Top 0.8 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 10 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A shell which places users into individual docker containers

ARCHIVAL NOTICE

This project is no longer maintained and is left up for historic purposes.

dockersh

A user shell for isolated, containerized environments.

What is this?

dockersh is designed to be used as a login shell on machines with multiple interactive users.

When a user invokes dockersh, it will bring up a Docker container (if not already running), and then spawn a new interactive shell in the container's namespace.

dockersh can be used as a shell in /etc/passwd or as an ssh ForceCommand.

This allows you to have a single ssh process on the normal ssh port which places user sessions into their own individual docker containers in a secure and locked down manner.

Why do I want this?

You want to allow multiple users to ssh onto a single box, but you'd like some isolation between those users. With dockersh each user enters their own individual docker container (acting like a lightweight virtual machine), with their home directory mounted from the host system (so that user data is persistent between container restarts), but with its own kernel namespaces for processes and networking.

This means that the user is isolated from the rest of the system, and they can only see their own processes, and have their own network stack. This gives better privacy between users, and can also be used for more easily separating each user's processes from the rest of the system with per user constraints.

Normally to give users individual containers you have to run an ssh daemon in each container, and either have have a different port for each user to ssh to or some nasty Forcecommand hacks (which only work with agent forwarding from the client).

Dockersh eliminates the need for any of these techniques by acting like a regular shell which can be used in /etc/passwd or as an ssh ForceCommand.
This allows you to have a single ssh process, on the normal ssh port, and gives a secure way to connect users into their own individual docker containers.

SECURITY WARNING

dockersh tries hard to drop all privileges as soon as possible, including disabling the suid, sgid, raw sockets and mknod capabilities of the target process (and all children), however this doesn't mean that it is safe enough to allow public access to dockersh containers!

WARNING: Whilst this project tries to make users inside containers have lowered privileges and drops capabilities to limit users ability to escalate their privilege level, it is not certain to be completely secure. Notably when Docker adds user namespace support, this can be used to further lock down privileges.

SECOND WARNING: The dockersh binary needs the suid bit set so that it can make the syscalls to adjust kernel namespaces, so any security issues in this code are likely to be exploitable to root.

Requirements

Linux >= 3.8

Docker >= 1.2.0

If you want to build it locally (rather than in a docker container), Go >= 1.2

Installation

With docker

(This is the recommended method).

Build the Dockerfile in the local directory into an image, and run it like this:

$ docker build .
# Progress, takes a while the first time..
....
Successfully built 3006a08eef2e 
$ docker run -v /usr/local/bin:/target 3006a08eef2e

Without docker

You need to install golang (tested on 1.2 and 1.3), then you should just be able to run:

go get
make

and a 'dockersh' binary will be generated in your $GOPATH (or your current working directory if $GOPATH isn't set). N.B. This binary needs to be moved to where you would like to install it (recommended /usr/local/bin), and owned by root + u+s (suid). This is done automatically if you use the Docker based installed, but you need to do it manually if you're compiling the binary yourself.

Invoking dockersh

There are two main methods of invoking dockersh. Either:

  1. Put the path to dockersh into /etc/shells, and then change the users shell in /etc/passwd (e.g. chsh myuser -s /usr/local/bin/dockersh)
  2. Set dockersh as the ssh ForceCommand in the users $HOME/.ssh/config, or globally in /etc/ssh/ssh_config

Note: The dockersh binary needs the suid bit set to operate!

Configuration

We use gcfg to read configs in an ini style format.

The global config file, /etc/dockershrc has a [dockersh] block in it, and zero or more [user "foo"] blocks.

This can be used to set settings globally or per user, and also to enable the setting of settings in the (optional) per user configuration file (~/.dockersh), if enabled.

Config file values

Setting name Type Description Default value Example value
imagename String The name of the container image to launch for the user. The %u sequence will interpolate the username busybox ubuntu, or %u/mydockersh
containername String The name of the container (per user) which is launched. %u_dockersh %u-dsh
mounthome Bool If the users home directory should be mounted in the target container false true
mounttmp Bool If /tmp should be mounted into the target container (so that ssh agent forwarding works). N.B. Security risk false true
mounthometo String Where to map the user's home directory inside the container. %h /opt/home/myhomedir
mounthomefrom String Where to map the user's home directory from on the host. %h /opt/home/%u
usercwd String Where to chdir into the container when starting a shell. %h /
containerusername String Username which should be used inside the container. %u root
shell String The shell that should be started for the user inside the container. /bin/ash /bin/bash
mountdockersocket Bool If to mount the docker socket from the host. (DANGEROUS) false true
dockersocket String The location of the docker socket from the host. /var/run/docker.sock /opt/docker/var/run/docker.sock
entrypoint String The entrypoint for the persistent process to keep the container running internal /sbin/yoursupervisor
cmd Array of Strings Additional parameters to pass when launching the container as the command line -c'/echo foo'
dockeropt Array of Strings Additional options to pass to docker when launching the container. Can be used to mount additional volumes or limit memory etc. -v /some/place:/foovol
enableuserconfig Bool Set to true to enable reading of per user ~/.dockersh files false true
enableuserimagename Bool Set to true to enable reading of imagename parameter from ~/.dockersh files false true
enableusercontainername Bool Set to true to enable reading of containername parameter from ~/.dockersh files. (Dangerous!) false true
enableusermounthome Bool Set to true to enable reading of mounthome parameter from ~/.dockersh files false true
enableusermounttmp Bool Set to true to enable reading of mounttmp parameter from ~/.dockersh files false true
enableusermounthometo Bool Set to true to enable reading of mounthometo parameter from ~/.dockersh files false true
enableusermounthomefrom Bool Set to true to enable reading of mounthomefrom parameter from ~/.dockersh files false true
enableuserusercwd Bool Set to true to enable reading of usercwd parameter from ~/.dockersh files false true
enableusercontainerusername bool Set to true to enable reading of containerusername parameter from ~/.dockersh files false true
enableusershell Bool Set to true to enable reading of shell parameter from ~/.dockersh files false true
enableuserentrypoint Bool Set to true to enable users to set their own supervisor daemon / entry point to the container for PID 1 false true
enableusercmd Bool Set to true to enable users to set the additional command parameters to the entry point false true
enableuserdockeropt Bool Set to true to enable users to set additional options to the docker container that's started. (Dangerous!) false true

Notes:

  • Boolean settings are set by just putting the setting name in the config (see examples below).
  • You must set both enableuserconfig and the specific enableuserxxx setting that you want in /etc/dockersh to get any values parsed from ~/.dockersh
  • Array values are represented by having the same config key appear multiple times, once per value.

Config interpolations

The following sequences are interpolated if found in configuration variables:

Sequence Interpolation
%u The username of the user running dockersh
%h The homedirectory (from /etc/passwd) of the user running dockersh

Example configs

A very restricted environment, with only the busybox container, limited to 32M of memory, /etc/dockersh looks like this:

[dockersh]
imagename = busybox
shell = /bin/ash
usercwd = /

A fairly restricted shell environment, but with homedirectories and one admin user being allowed additional privs, set the following /etc/dockersh

[dockersh]
imagename = ubuntu:precise
shell = /bin/bash
mounthome

[user "someadminguy"]
mounttmp
mountdockersocket

In a less restrictive environment, you may allow users to choose their own container and shell, from a 'shell' container they have uploaded to the registry, and have ssh agent forwarding working, with the following /etc/dockersh

[dockersh]
imagename = "%u/shell"
mounthome
mounttmp
enableuserconfig
enableusershell

[user "someadminguy"]
mountdockersocket

And an example user's ~/.dockersh

[dockersh]
shell = /bin/zsh

Or just allowing your users to run whatever container they want:

[dockersh]
mounthome
mounttmp
enableuserconfig
enableuserimagename

Caveats

  • User namespaces are not supported (yet) so if users escalate to root inside the container, they can probably escape
  • Tty/Pty handling is not great - whilst things appear to work, they don't go well in unusual circumstances (e.g. your process being killed due to OOM).
  • This code has not been audited by a 3rd party or a container expert, there are probably issues waiting to be found!

TODO

  • How do we deal with changed settings (i.e. when to recycle the container)
    • Document just kill 1 inside the container?
  • Fix up go panics when exiting the root container.
  • getpwnam so that we can interpolate the user's shell from /etc/shells (if used in ForceCommand mode!)
  • Decent test cases
  • Use libcontainer a lot more, in favour of our code:
  • Find a better way to make ssh agent sockets work than to bind /tmp

Contributing

Patches are very very welcome!

This is our first real Go project, so we apologise about the shoddy quality of the code.

Please make a branch and send us a pull request.

Please ensure that you use the supplied pre-commit hook to correctly format your code with go fmt:

ln -s hooks/pre-commit .git/hooks/pre-commit

Copyright

Copyright (c) 2014 Yelp. Some rights are reserved (see the LICENSE file for more details).

More Repositories

1

elastalert

Easy & Flexible Alerting With ElasticSearch
Python
7,926
star
2

dumb-init

A minimal init system for Linux containers
Python
6,806
star
3

detect-secrets

An enterprise friendly way of detecting and preventing secrets in code.
Python
3,704
star
4

mrjob

Run MapReduce jobs on Hadoop or Amazon Web Services
Python
2,615
star
5

osxcollector

A forensic evidence collection & analysis toolkit for OS X
Python
1,858
star
6

paasta

An open, distributed platform as a service
Python
1,681
star
7

undebt

A fast, straightforward, reliable tool for performing massive, automated code refactoring
Python
1,634
star
8

MOE

A global, black box optimization engine for real world metric optimization.
C++
1,306
star
9

dataset-examples

Samples for users of the Yelp Academic Dataset
Python
1,189
star
10

yelp.github.io

A showcase of projects we've open sourced and open source projects we use
JavaScript
701
star
11

bravado

Bravado is a python client library for Swagger 2.0 services
Python
603
star
12

yelp-api

Examples of code using our v2 API
PHP
580
star
13

service-principles

A guide to service principles at Yelp for our service oriented architecture
423
star
14

swagger-gradle-codegen

💫 A Gradle Plugin to generate your networking code from Swagger
Kotlin
413
star
15

mysql_streamer

MySQLStreamer is a database change data capture and publish system.
Python
409
star
16

pyleus

Pyleus is a Python framework for developing and launching Storm topologies.
Python
406
star
17

yelp-fusion

Yelp Fusion API
Python
401
star
18

docker-custodian

Keep docker hosts tidy
Python
355
star
19

android-school

The best videos from the Android community and beyond
350
star
20

Tron

Next generation batch process scheduling and management
Python
340
star
21

kafka-utils

Python
313
star
22

bento

DEPRECATED - A delicious framework for building modularized Android user interfaces, by Yelp.
Kotlin
306
star
23

Testify

A more pythonic testing framework.
Python
303
star
24

clusterman

Cluster Autoscaler for Kubernetes and Mesos
Python
295
star
25

kotlin-android-workshop

A Kotlin Workshop for engineers familiar with Java and Android development.
Kotlin
288
star
26

threat_intel

Threat Intelligence APIs
Python
264
star
27

nrtsearch

A high performance gRPC server on top of Apache Lucene
Java
254
star
28

python-gearman

Gearman API - Client, worker, and admin client interfaces
Python
242
star
29

py_zipkin

Provides utilities to facilitate the usage of Zipkin in Python
Python
225
star
30

fuzz-lightyear

A pytest-inspired, DAST framework, capable of identifying vulnerabilities in a distributed, micro-service ecosystem through chaos engineering testing and stateful, Swagger fuzzing.
Python
205
star
31

yelp-python

A Python library for the Yelp API
Python
182
star
32

venv-update

Synchronize your virtualenv quickly and exactly.
Python
178
star
33

firefly

Firefly is a web application aimed at powerful, flexible time series graphing for web developers.
JavaScript
171
star
34

amira

AMIRA: Automated Malware Incident Response & Analysis
Python
150
star
35

aactivator

Automatically source and unsource a project's environment
Python
145
star
36

YLTableView

Objective-C
144
star
37

love

A system to share your appreciation
Python
142
star
38

lemon-reset

Consistent, cross-browser React DOM tags, powered by CSS Modules. 🍋
JavaScript
131
star
39

dataloader-codegen

🤖 dataloader-codegen is an opinionated JavaScript library for automatically generating DataLoaders over a set of resources (e.g. HTTP endpoints).
TypeScript
110
star
40

bravado-core

Python
109
star
41

data_pipeline

Data Pipeline Clientlib provides an interface to tail and publish to data pipeline topics.
Python
109
star
42

detect-secrets-server

Python
108
star
43

yelp-ruby

A Ruby gem for communicating with the Yelp REST API
Ruby
105
star
44

swagger_spec_validator

Python
104
star
45

ybinlogp

A fast mysql binlog parser
C
97
star
46

beans

Bringing people together, one cup of coffee at a time
Python
93
star
47

casper

A fast web application platform built in Rust and Luau
Rust
90
star
48

schematizer

A schema store service that tracks and manages all the schemas used in the Data Pipeline
Python
86
star
49

requirements-tools

requirements-tools contains scripts for working with Python requirements, primarily in applications.
Python
81
star
50

osxcollector_output_filters

Filters that process and transform the output of osxcollector
Python
77
star
51

sensu_handlers

Custom Sensu Handlers to support a multi-tenant environment, allowing checks themselves to emit the type of handler behavior they need in the event json
Ruby
75
star
52

graphql-guidelines

GraphQL @ Yelp Schema Guidelines
Makefile
74
star
53

kegmate

Arduino/iPad powered kegerator
Objective-C
72
star
54

ephemeral-port-reserve

Find an unused port, reliably
Python
68
star
55

parcelgen

Helpful tool to make data objects easier for Android
Python
65
star
56

salsa

A tool for exporting iOS components into Sketch 📱💎
Swift
62
star
57

yelp-ios

Objective-C
61
star
58

docker-observium

Observium docker image with both professional and community edition support, ldap auth, and easy plugin support.
ApacheConf
58
star
59

yelp-android

Java
55
star
60

terraform-provider-signalform

SignalForm is a terraform provider to codify SignalFx detectors, charts and dashboards
Go
44
star
61

mycroft

Python
42
star
62

pidtree-bcc

eBPF tool for logging process ancestry of outbound TCP connections
Python
41
star
63

terraform-provider-gitfile

Terraform provider for checking out git repositories and making changes
Go
40
star
64

ffmpeg-android

Shell
39
star
65

pushmanager

Pushmanager is a web application to manage source code deployments.
Python
38
star
66

zygote

A Python HTTP process management utility.
Python
38
star
67

yelp_kafka

An extension of the kafka-python package that adds features like multiprocess consumers.
Python
38
star
68

pgctl

Manage sets of developer services -- "playground control"
Python
31
star
69

EMRio

Elastic MapReduce instance optimizer
Python
31
star
70

s3mysqldump

Dump mysql tables to s3, and parse them
Python
31
star
71

android-varanus

A client-side Android library to monitor and limit network traffic sent by your apps
Kotlin
29
star
72

pyramid_zipkin

Pyramid tween to add Zipkin service spans
Python
29
star
73

puppet-netstdlib

A collection of Puppet functions for interacting with the network
Ruby
27
star
74

sqlite3dbm

sqlite-backed dictionary conforming to the dbm interface
Python
27
star
75

send_nsca

Pure-python NSCA client
Python
26
star
76

docker-push-latest-if-changed

Python
26
star
77

data_pipeline_avro_util

Provides a Pythonic interface for reading and writing Avro schemas
Python
26
star
78

cocoapods-readonly

Automatically locks all CocoaPod source files.
Ruby
26
star
79

uwsgi_metrics

Python
26
star
80

WebImageView

An enhanced and improved ImageView for Android that displays images loaded over the interwebs
Java
25
star
81

task_processing

Interfaces and shared infrastructure for generic task processing at Yelp.
Python
23
star
82

PushmasterApp

(Legacy) Yelp pushmaster application built on Google App Engine
Python
22
star
83

tlspretense-service

A Docker container that exposes tlspretense on a port.
Makefile
20
star
84

puppet-uchiwa

Puppet module for installing Uchiwa
Ruby
20
star
85

yelp_cheetah

cheetah, hacked by yelpers
Python
20
star
86

logfeeder

Python
20
star
87

fido

Asynchronous HTTP client built on top of Crochet and Twisted
Python
20
star
88

swagger-spec-compatibility

Python library to check Swagger Spec backward compatibility
Python
20
star
89

pyramid-hypernova

A Python client for Airbnb's Hypernova server, for use with the Pyramid web framework.
Python
19
star
90

mr3po

protocols for use with mrjob
Python
16
star
91

YPFastDateParser

A class for parsing strings into NSDate instances, several times faster than NSDateFormatter
Objective-C
15
star
92

yelp_uri

Utilities for dealing with URIs, invented and maintained by Yelp.
Python
14
star
93

pysensu-yelp

A Python library to emit Sensu events that the Yelp Sensu Handlers can understand for Self-Service Sensu Monitoring
Python
14
star
94

terraform-provider-cloudhealth

Terraform provider for Cloudhealth
Go
14
star
95

yelp-rails-example

An example Rails application that uses the Yelp gem to integrate with the API
Ruby
13
star
96

named_decorator

Dynamically name wrappers based on their callees to untangle profiles of large python codebases
Python
12
star
97

pt-online-schema-change-plugins

Perl
11
star
98

environment_tools

Tools for programmatically describing Yelp's different environments (prod, dev, stage)
Python
11
star
99

puppet-cron

A super great cron Puppet module with timeouts, locking, monitoring, and more!
Ruby
11
star
100

pyswf

Python
10
star