From dbf39403d33b100c83580a6456e02ce8fe5bb67e Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Thu, 10 Sep 2015 15:51:12 +0100 Subject: [PATCH 1/3] [proxy] Autoconfigure TLS based on daemon settings With this on OSX you can: ```sh $ boot2docker init $ boot2docker up $ eval $(boot2docker shellinit) $ weave launch $ eval $(weave env) ``` --- .gitignore | 2 + Makefile | 9 +++-- prog/docker_tls_args/main.go | 77 ++++++++++++++++++++++++++++++++++++ prog/weaveexec/Dockerfile | 2 +- weave | 20 ++++++---- 5 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 prog/docker_tls_args/main.go diff --git a/.gitignore b/.gitignore index 95bb841f..91961534 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ prog/weaveproxy/weaveproxy prog/sigproxy/sigproxy prog/weavewait/weavewait prog/netcheck/netcheck +prog/docker_tls_args/docker_tls_args testing/cover/cover testing/runner/runner tools/bin @@ -55,6 +56,7 @@ prog/weaveexec/weaveproxy prog/weaveexec/weavewait prog/weaveexec/sigproxy prog/weaveexec/netcheck +prog/weaveexec/docker_tls_args prog/weaveexec/docker*.tgz Vagrantfile.local test/tls/*.pem diff --git a/Makefile b/Makefile index cbbd0f83..c375a7ab 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,11 @@ SIGPROXY_EXE=prog/sigproxy/sigproxy WEAVEWAIT_EXE=prog/weavewait/weavewait WEAVEHOSTS_EXE=prog/weavehosts/weavehosts NETCHECK_EXE=prog/netcheck/netcheck +DOCKERTLSARGS_EXE=prog/docker_tls_args/docker_tls_args COVER_EXE=testing/cover/cover RUNNER_EXE=testing/runner/runner -EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_EXE) $(COVER_EXE) $(RUNNER_EXE) +EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) $(COVER_EXE) $(RUNNER_EXE) WEAVER_UPTODATE=.weaver.uptodate WEAVEEXEC_UPTODATE=.weaveexec.uptodate @@ -79,8 +80,9 @@ $(WEAVEWAIT_EXE): prog/weavewait/main.go net/*.go $(WEAVEHOSTS_EXE): prog/weavehosts/weavehosts.go $(COVER_EXE): testing/cover/cover.go $(RUNNER_EXE): testing/runner/runner.go +$(DOCKERTLSARGS_EXE): prog/docker_tls_args/*.go -$(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(WEAVEHOSTS_EXE) $(COVER_EXE) $(RUNNER_EXE): +$(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(WEAVEHOSTS_EXE) $(COVER_EXE) $(RUNNER_EXE) $(DOCKERTLSARGS_EXE): go get ./$(@D) go build -o $@ ./$(@D) @@ -88,13 +90,14 @@ $(WEAVER_UPTODATE): prog/weaver/Dockerfile $(WEAVER_EXE) $(SUDO) docker build -t $(WEAVER_IMAGE) prog/weaver touch $@ -$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_EXE) +$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) cp weave prog/weaveexec/weave cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait cp $(WEAVEHOSTS_EXE) prog/weaveexec/weavehosts cp $(NETCHECK_EXE) prog/weaveexec/netcheck + cp $(DOCKERTLSARGS_EXE) prog/weaveexec/docker_tls_args cp $(DOCKER_DISTRIB) prog/weaveexec/docker.tgz $(SUDO) docker build -t $(WEAVEEXEC_IMAGE) prog/weaveexec touch $@ diff --git a/prog/docker_tls_args/main.go b/prog/docker_tls_args/main.go new file mode 100644 index 00000000..6560a3ea --- /dev/null +++ b/prog/docker_tls_args/main.go @@ -0,0 +1,77 @@ +// docker_tls_args: find the docker daemon's tls args +// This reimplements pgrep, because pgrep will only look in /proc, but not in +// $PROCFS. +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +func main() { + procRoot := os.Getenv("PROCFS") + if procRoot == "" { + procRoot = "/proc" + } + + dirEntries, err := ioutil.ReadDir(procRoot) + checkErr(err) + + for _, dirEntry := range dirEntries { + dirName := dirEntry.Name() + if _, err := strconv.Atoi(dirName); err != nil { + continue + } + + if comm, err := ioutil.ReadFile(filepath.Join(procRoot, dirName, "comm")); err != nil || string(comm) != "docker\n" { + continue + } + + cmdline, err := ioutil.ReadFile(filepath.Join(procRoot, dirName, "cmdline")) + if err != nil { + continue + } + + isDaemon := false + tlsArgs := []string{} + args := bytes.Split(cmdline, []byte{'\000'}) + for i := 0; i < len(args); i++ { + arg := string(args[i]) + switch { + case arg == "-d": + isDaemon = true + break + case arg == "--tls", arg == "--tlsverify": + tlsArgs = append(tlsArgs, arg) + case strings.HasPrefix(arg, "--tls"): + tlsArgs = append(tlsArgs, arg) + if len(args) > i+1 && + !strings.Contains(arg, "=") && + !strings.HasPrefix(string(args[i+1]), "-") { + tlsArgs = append(tlsArgs, string(args[i+1])) + i++ + } + } + } + if !isDaemon { + continue + } + + fmt.Println(strings.Join(tlsArgs, " ")) + os.Exit(0) + } + + os.Exit(1) +} + +func checkErr(err error) { + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/prog/weaveexec/Dockerfile b/prog/weaveexec/Dockerfile index 1d35b419..bb189584 100644 --- a/prog/weaveexec/Dockerfile +++ b/prog/weaveexec/Dockerfile @@ -18,6 +18,6 @@ RUN apk add --update \ && rm -rf /var/cache/apk/* ADD ./weave ./sigproxy ./weaveproxy /home/weave/ -ADD ./netcheck ./weavehosts /usr/bin/ +ADD ./netcheck ./weavehosts ./docker_tls_args /usr/bin/ ADD ./weavewait /w/w ADD ./docker.tgz / diff --git a/weave b/weave index 08a040be..70eae910 100755 --- a/weave +++ b/weave @@ -995,11 +995,7 @@ tls_arg() { PROXY_ARGS="$PROXY_ARGS $1 /home/weave/tls/$3.pem" } -proxy_args() { - PROXY_VOLUMES="" - PROXY_ARGS="" - PROXY_TLS_ENABLED="" - PROXY_HOST="" +proxy_parse_args() { while [ $# -gt 0 ]; do case "$1" in -H) @@ -1042,10 +1038,20 @@ proxy_args() { esac shift done +} + +proxy_args() { + PROXY_VOLUMES="" + PROXY_ARGS="" + PROXY_TLS_ENABLED="" + PROXY_HOST="" + proxy_parse_args "$@" if [ -z "$PROXY_HOST" -a -n "$CLIENT_TLS_ENABLED" -a -z "$PROXY_TLS_ENABLED" ] ; then - echo "When launching the proxy via TLS, -H and/or TLS options are required." >&2 - exit 1 + if ! proxy_parse_args $(docker_tls_args) ; then + echo "When launching the proxy via TLS, -H and/or TLS options are required." >&2 + exit 1 + fi fi if [ -z "$PROXY_HOST" ] ; then case "$DOCKER_CLIENT_HOST" in From 0820c484d6872c8c5bdbd161981c0b2b0a8357c8 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Fri, 11 Sep 2015 15:33:23 +0100 Subject: [PATCH 2/3] [proxy] Documenting TLS autoconfig --- site/boot2docker.md | 12 ++++-------- site/proxy.md | 26 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/site/boot2docker.md b/site/boot2docker.md index a3819b66..f964082d 100644 --- a/site/boot2docker.md +++ b/site/boot2docker.md @@ -15,15 +15,11 @@ instructions. First, we need to get Boot2Docker running: Assuming you have fetched the 'weave' script via curl or similar, and it is in the current directory, launch weave on the Boot2Docker VM and -configure our shell. Because Boot2Docker uses TLS, we have to pass a -few extra options when launching the docker API proxy: +configure our shell. Boot2Docker uses TLS, but weave will auto-detect +that, and configure things appropriately. - host1$ ./weave launch-router - host1$ ./weave launch-proxy --tls \ - --tlscacert /var/lib/boot2docker/tls/ca.pem \ - --tlscert /var/lib/boot2docker/tls/server.pem \ - --tlskey /var/lib/boot2docker/tls/serverkey.pem - host1$ eval "$(./weave env)" + host1$ weave launch + host1$ eval "$(weave env)" Now, we can use the docker command to run our containers, as shown in the [proxy documentation](proxy.html): diff --git a/site/proxy.md b/site/proxy.md index 647bb098..a0c7795f 100644 --- a/site/proxy.md +++ b/site/proxy.md @@ -45,8 +45,9 @@ argument, e.g. host1$ weave launch-proxy -H tcp://127.0.0.1:9999 -When launching the proxy via TLS, `-H` and/or [TLS options](#tls) are -required. +If no TLS or listening interfaces are set, TLS will be autoconfigured +based on the docker daemon's settings, and listening interfaces will +be autoconfigured based on your docker client's settings. Multiple `-H` arguments can be specified. If you are working with a remote docker daemon, then any firewalls inbetween need to be @@ -204,13 +205,20 @@ to the proxy, the specified label has precedence over the container's name. ## Securing the docker communication with TLS -If you are -[connecting to the docker daemon with TLS](https://docs.docker.com/articles/https/), -you will probably want to do the same when connecting to the -proxy. That is accomplished by launching the proxy with the same -TLS-related command-line flags as supplied to the docker daemon. For -example, if you have generated your certificates and keys into the -docker host's `/tls` directory, we can launch the proxy with: +If you are [connecting to the docker daemon with +TLS](https://docs.docker.com/articles/https/), you will probably want +to do the same when connecting to the proxy. The proxy will +automatically detect the docker daemon's TLS configuration, and +attempt to duplicate it. In the standard auto-detection case you will +be able to launch a TLS-enabled proxy with: + + host1$ weave launch-proxy + +You can also manually configure the proxy's TLS. This is accomplished +by launching the proxy with the same TLS-related command-line flags as +supplied to the docker daemon. For example, if you have generated your +certificates and keys into the docker host's `/tls` directory, we can +launch the proxy with: host1$ weave launch-proxy --tls-verify --tls-cacert=/tls/ca.pem \ --tls-cert=/tls/server-cert.pem --tls-key=/tls/server-key.pem From 0a475bd4cc9ee276b245bd5c6f0bca12e8c4a1e5 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Wed, 16 Sep 2015 13:08:56 +0100 Subject: [PATCH 3/3] docker_tls_args should look for '-d' or 'daemon' to handle docker 1.8 change --- prog/docker_tls_args/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prog/docker_tls_args/main.go b/prog/docker_tls_args/main.go index 6560a3ea..37c747a5 100644 --- a/prog/docker_tls_args/main.go +++ b/prog/docker_tls_args/main.go @@ -43,7 +43,7 @@ func main() { for i := 0; i < len(args); i++ { arg := string(args[i]) switch { - case arg == "-d": + case arg == "-d" || arg == "daemon": isDaemon = true break case arg == "--tls", arg == "--tlsverify":