docker / machine

Machine management for a container-centric world
https://docs.docker.com/machine/
Apache License 2.0
6.63k stars 1.97k forks source link

CN+SANs of Docker daemon cert created by `docker-machine create -d virtualbox` differ from cert created by `/etc/init.d/docker` #2018

Open onejli opened 9 years ago

onejli commented 9 years ago

docker-machine create -d virtualbox creates a certificate that only binds to the ip address of the host-only VirtualBox network adapter. But, /etc/init.d/docker attempts (and fails) to create a cert that binds to the ip addresses of all interfaces of the host.

$ docker-machine -v
docker-machine version 0.4.1 (e2c88d6)

$ docker-machine create -d virtualbox foo
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env foo

$ docker-machine ssh foo "openssl x509 -noout -text -in /var/lib/boot2docker/server.pem"
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            fe:f6:0b:74:77:3e:a1:63:10:5f:21:77:fa:8e:20:0f
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=jonathan.li
        Validity
            Not Before: Oct 18 00:19:00 2015 GMT
            Not After : Oct  2 00:19:00 2018 GMT
        Subject: O=foo
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    <SNIP>
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Key Agreement
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: 
                IP Address:192.168.99.101
    Signature Algorithm: sha256WithRSAEncryption
         <SNIP>

Looking at the debug output for the same command, I see that /etc/init.d/docker attempts to (re)create a cert that includes all interfaces, but fails due to the existence of the cert that was generated on the physical host and copied into the VM earlier during the provisioning process.

$ docker-machine -D create -d virtualbox foo
<SNIP>
generating server cert: /Users/jonathan.li/.docker/machine/machines/foo/server.pem ca-key=/Users/jonathan.li/.docker/machine/certs/ca.pem private-key=/Users/jonathan.li/.docker/machine/certs/ca-key.pem org=foo
Using SSH client type: external
About to run SSH command:
sudo /etc/init.d/docker stop
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost sudo /etc/init.d/docker stop] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: 
<SNIP>
Using SSH client type: external
About to run SSH command:
printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/server.pem
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/server.pem] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: -----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
<SNIP>
Using SSH client type: external
About to run SSH command:
sudo /etc/init.d/docker start
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost sudo /etc/init.d/docker start] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: Need TLS certs for foo,127.0.0.1,10.0.2.15,192.168.99.101
-------------------
Generate server cert
/usr/local/bin/generate_cert --host=foo,127.0.0.1,10.0.2.15,192.168.99.101 --ca=/var/lib/boot2docker/ca.pem --ca-key=/var/lib/boot2docker/tls/cakey.pem --cert=/var/lib/boot2docker/server.pem --key=/var/lib/boot2docker/server-key.pem --org=Boot2Docker
2015/10/18 00:20:20 Preventing overwrite: the following files already exist: "/var/lib/boot2docker/server.pem" "/var/lib/boot2docker/server-key.pem". To overwrite files, add `--overwrite`.

Daemon not responding yet: dial tcp 192.168.99.101:2376: connection refused
To see how to connect Docker to this machine, run: docker-machine env default

FWIW the Docker daemon emits this message at startup which seems to indicate that the call to generate_cert in /etc/init.d/docker is preferred to the (more restrictive) certs currently generated by docker-machine create -d virtualbox.

$ docker-machine ssh foo "sudo /etc/init.d/docker restart"
Need TLS certs for foo,127.0.0.1,10.0.2.15,192.168.99.101
-------------------

The cert generated by the call to /usr/local/bin/generate_cert in /etc/init.d/docker would result in something that looks like this:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ed:8b:4a:aa:fd:1a:2e:de:b3:0d:f3:a9:f2:4e:fb:0c
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=jonathan.li
        Validity
            Not Before: Oct 20 02:51:14 2015 GMT
            Not After : Oct 19 02:51:14 2016 GMT
        Subject: O=Boot2Docker
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    <SNIP>
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: 
                DNS:foo, IP Address:127.0.0.1, IP Address:10.0.2.15, IP Address:192.168.99.101
    Signature Algorithm: sha256WithRSAEncryption
         <SNIP>

Unfortunately, it's not as simple as re-running the /usr/local/bin/generate_cert command with the --overwrite flag. The docker-machine provisioning pushes everything (i.e., ca.pem, server.pem, and server-key.pem) except for ca-key.pem into the vm.

Using SSH client type: external
About to run SSH command:
printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/ca.pem
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/ca.pem] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: -----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----

Using SSH client type: external
About to run SSH command:
printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/server.pem
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost printf '%s' '-----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----
' | sudo tee /var/lib/boot2docker/server.pem] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: -----BEGIN CERTIFICATE-----
<SNIP>
-----END CERTIFICATE-----

Using SSH client type: external
About to run SSH command:
printf '%s' '-----BEGIN RSA PRIVATE KEY-----
<SNIP>
-----END RSA PRIVATE KEY-----
' | sudo tee /var/lib/boot2docker/server-key.pem
&{/usr/bin/ssh [/usr/bin/ssh -o PasswordAuthentication=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -i /Users/jonathan.li/.docker/machine/machines/foo/id_rsa -p 58668 docker@localhost printf '%s' '-----BEGIN RSA PRIVATE KEY-----
<SNIP>
-----END RSA PRIVATE KEY-----
' | sudo tee /var/lib/boot2docker/server-key.pem] []  <nil> <nil> <nil> [] <nil> <nil> <nil> <nil> false [] [] [] [] <nil>}
SSH cmd err, output: <nil>: -----BEGIN RSA PRIVATE KEY-----
<SNIP>
-----END RSA PRIVATE KEY-----
nathanleclaire commented 9 years ago

Yeah, really we need to take out the server cert generation code, which is how things used to be done before the docker-machine days. cc @SvenDowideit @tianon

tianon commented 9 years ago

The Docker daemon creates certs now? :smile:

nathanleclaire commented 9 years ago

boot2docker init scripts silly ;P

tianon commented 9 years ago

I was honestly hoping we could stop having boot2docker do specific things with TLS, especially since they're necessary for the general case of other non-boot2docker OSes too -- any thoughts on that?

nathanleclaire commented 9 years ago

I was honestly hoping we could stop having boot2docker do specific things with TLS, especially since they're necessary for the general case of other non-boot2docker OSes too -- any thoughts on that?

Yeah, I'd say it should be taken out at this point.

tianon commented 9 years ago

Doh, I totally misunderstood your original comment -- yes, let's axe it. I'll work up a PR now. :smile:

nathanleclaire commented 9 years ago

Cool :+1:

tianon commented 9 years ago

Hmm, the provisioner here in Machine is still using quite a bit of this init script code, so this isn't going to be quite as many lines of removal as I'd like, but I suppose we can stop having it do generation at least.

For reference, here's the patch I was hoping we'd be able to apply: :smile:

diff --git a/rootfs/rootfs/usr/local/etc/init.d/docker b/rootfs/rootfs/usr/local/etc/init.d/docker
index 65a287e..e7cb342 100644
--- a/rootfs/rootfs/usr/local/etc/init.d/docker
+++ b/rootfs/rootfs/usr/local/etc/init.d/docker
@@ -6,78 +6,15 @@
 test -f '/var/lib/boot2docker/profile' && . '/var/lib/boot2docker/profile'

 : ${DOCKER_HOST:='-H tcp://0.0.0.0:2375'}
-: ${DOCKER_TLS:=auto}
 : ${DOCKER_STORAGE:=auto}
 : ${DOCKER_DIR:=/var/lib/docker}
 : ${DOCKER_ULIMITS:=1048576}
 : ${DOCKER_LOGFILE:=/var/lib/boot2docker/docker.log}

-: ${CERTDIR:=/var/lib/boot2docker/tls/}
-: ${CERT_INTERFACES:='eth0 eth1'}
-: ${CACERT:="${CERTDIR}ca.pem"}
-: ${CAKEY:="${CERTDIR}cakey.pem"}
-: ${SERVERCERT:="${CERTDIR}server.pem"}
-: ${SERVERKEY:="${CERTDIR}serverkey.pem"}
-: ${CERT:="${CERTDIR}cert.pem"}
-: ${KEY:="${CERTDIR}key.pem"}
-: ${ORG:=Boot2Docker}
-: ${SERVERORG:="${ORG}"}
-: ${CAORG:="${ORG}CA"} # Append 'CA'; see <http://rt.openssl.org/Ticket/History.html?use r=guest&pass=guest&id=3979>
-
 # Add /usr/local/sbin to the path.
 export PATH=${PATH}:/usr/local/sbin

 start() {
-    # Not enabling Docker daemon TLS by default.
-    if [ "$DOCKER_TLS" != "no" ]; then
-        CERTHOSTNAMES="$(hostname -s),$(hostname -i)"
-        for interface in ${CERT_INTERFACES}; do
-          IPS=$(ip addr show ${interface} |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p')
-          for ip in $IPS; do
-            CERTHOSTNAMES="$CERTHOSTNAMES,$ip"
-          done
-        done
-        echo "Need TLS certs for $CERTHOSTNAMES"
-        echo "-------------------"
-
-        mkdir -p "$CERTDIR"
-        chmod 700 "$CERTDIR"
-        if [ ! -f "$CACERT" ] || [ ! -f "$CAKEY" ]; then
-            echo "Generating CA cert"
-            /usr/local/bin/generate_cert --cert="$CACERT" --key="$CAKEY" --org="$CAORG"
-            rm "$SERVERCERT" "$SERVERKEY" "$CERT" "$KEY" "$CERTDIR/hostnames"
-        fi
-
-        CERTSEXISTFOR=$(cat "$CERTDIR/hostnames" 2>/dev/null)
-        if [ "$CERTHOSTNAMES" != "$CERTSEXISTFOR" ]; then
-            echo "Generate server cert"
-            echo /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            echo "$CERTHOSTNAMES" > "$CERTDIR/hostnames"
-        fi
-
-        if [ ! -f "$CERT" ] || [ ! -f "$KEY" ]; then
-            echo "Generating client cert"
-            /usr/local/bin/generate_cert --ca="$CACERT" --ca-key="$CAKEY" --cert="$CERT" --key="$KEY" --org="$ORG"
-        fi
-
-        if [ "$DOCKER_TLS" == "auto" ]; then
-            DOCKER_HOST='-H tcp://0.0.0.0:2376'
-            EXTRA_ARGS="$EXTRA_ARGS --tlsverify --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        elif [ "$DOCKER_TLS" != "no" ]; then
-            EXTRA_ARGS="$EXTRA_ARGS $DOCKER_TLS --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        fi
-
-        # now make the client certificates available to the docker user
-        USERCFG="/home/docker/.docker"
-        mkdir -p "$USERCFG"
-        chmod 700 "$USERCFG"
-        cp "$CACERT" "$USERCFG"
-        cp "$CERT" "$USERCFG"
-        cp "$KEY" "$USERCFG"
-        chown -R docker:staff "$USERCFG"
-    fi
-
     mkdir -p "$DOCKER_DIR"

     if [ "$DOCKER_STORAGE" = 'auto' ]; then
nathanleclaire commented 9 years ago

Interesting -- which bits are we relying on?

tianon commented 9 years ago

https://github.com/docker/machine/blob/9f01770d7e0a21ae7fda67619e321e91e98ed446/libmachine/provision/boot2docker.go#L149-L166

CACERT={{.AuthOptions.CaCertRemotePath}}
DOCKER_HOST='-H tcp://0.0.0.0:{{.DockerPort}}'
DOCKER_STORAGE={{.EngineOptions.StorageDriver}}
DOCKER_TLS=auto
SERVERKEY={{.AuthOptions.ServerKeyRemotePath}}
SERVERCERT={{.AuthOptions.ServerCertRemotePath}}
tianon commented 9 years ago

I'm working on a slightly less trim patch.

nathanleclaire commented 9 years ago

Nice -- I see, it's the whole EXTRA_ARGS generation bit in there which is problematic.

tianon commented 9 years ago

Does this seem more sane?

diff --git a/rootfs/rootfs/usr/local/etc/init.d/docker b/rootfs/rootfs/usr/local/etc/init.d/docker
index 65a287e..5bfeb93 100644
--- a/rootfs/rootfs/usr/local/etc/init.d/docker
+++ b/rootfs/rootfs/usr/local/etc/init.d/docker
@@ -6,77 +6,39 @@
 test -f '/var/lib/boot2docker/profile' && . '/var/lib/boot2docker/profile'

 : ${DOCKER_HOST:='-H tcp://0.0.0.0:2375'}
-: ${DOCKER_TLS:=auto}
 : ${DOCKER_STORAGE:=auto}
 : ${DOCKER_DIR:=/var/lib/docker}
 : ${DOCKER_ULIMITS:=1048576}
 : ${DOCKER_LOGFILE:=/var/lib/boot2docker/docker.log}

-: ${CERTDIR:=/var/lib/boot2docker/tls/}
-: ${CERT_INTERFACES:='eth0 eth1'}
+: ${DOCKER_TLS:=auto}
 : ${CACERT:="${CERTDIR}ca.pem"}
-: ${CAKEY:="${CERTDIR}cakey.pem"}
 : ${SERVERCERT:="${CERTDIR}server.pem"}
 : ${SERVERKEY:="${CERTDIR}serverkey.pem"}
-: ${CERT:="${CERTDIR}cert.pem"}
-: ${KEY:="${CERTDIR}key.pem"}
-: ${ORG:=Boot2Docker}
-: ${SERVERORG:="${ORG}"}
-: ${CAORG:="${ORG}CA"} # Append 'CA'; see <http://rt.openssl.org/Ticket/History.html?use r=guest&pass=guest&id=3979>

 # Add /usr/local/sbin to the path.
 export PATH=${PATH}:/usr/local/sbin

 start() {
-    # Not enabling Docker daemon TLS by default.
-    if [ "$DOCKER_TLS" != "no" ]; then
-        CERTHOSTNAMES="$(hostname -s),$(hostname -i)"
-        for interface in ${CERT_INTERFACES}; do
-          IPS=$(ip addr show ${interface} |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p')
-          for ip in $IPS; do
-            CERTHOSTNAMES="$CERTHOSTNAMES,$ip"
-          done
-        done
-        echo "Need TLS certs for $CERTHOSTNAMES"
-        echo "-------------------"
-        mkdir -p "$CERTDIR"
-        chmod 700 "$CERTDIR"
-        if [ ! -f "$CACERT" ] || [ ! -f "$CAKEY" ]; then
-            echo "Generating CA cert"
-            /usr/local/bin/generate_cert --cert="$CACERT" --key="$CAKEY" --org="$CAORG"
-            rm "$SERVERCERT" "$SERVERKEY" "$CERT" "$KEY" "$CERTDIR/hostnames"
-        fi
-
-        CERTSEXISTFOR=$(cat "$CERTDIR/hostnames" 2>/dev/null)
-        if [ "$CERTHOSTNAMES" != "$CERTSEXISTFOR" ]; then
-            echo "Generate server cert"
-            echo /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            echo "$CERTHOSTNAMES" > "$CERTDIR/hostnames"
-        fi
-
-        if [ ! -f "$CERT" ] || [ ! -f "$KEY" ]; then
-            echo "Generating client cert"
-            /usr/local/bin/generate_cert --ca="$CACERT" --ca-key="$CAKEY" --cert="$CERT" --key="$KEY" --org="$ORG"
-        fi
-
-        if [ "$DOCKER_TLS" == "auto" ]; then
-            DOCKER_HOST='-H tcp://0.0.0.0:2376'
-            EXTRA_ARGS="$EXTRA_ARGS --tlsverify --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        elif [ "$DOCKER_TLS" != "no" ]; then
-            EXTRA_ARGS="$EXTRA_ARGS $DOCKER_TLS --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        fi
-
-        # now make the client certificates available to the docker user
-        USERCFG="/home/docker/.docker"
-        mkdir -p "$USERCFG"
-        chmod 700 "$USERCFG"
-        cp "$CACERT" "$USERCFG"
-        cp "$CERT" "$USERCFG"
-        cp "$KEY" "$USERCFG"
-        chown -R docker:staff "$USERCFG"
-    fi
+   if [ "$DOCKER_TLS" = 'no' ]; then
+       EXTRA_ARGS="$EXTRA_ARGS -H tcp://0.0.0.0:2375"
+   else
+       EXTRA_ARGS="$EXTRA_ARGS -H tcp://0.0.0.0:2376"
+       if [ "$DOCKER_TLS" = 'auto' ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlsverify"
+       else
+           EXTRA_ARGS="$EXTRA_ARGS $DOCKER_TLS"
+       fi
+       if [ -f "$CACERT" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlscacert=$CACERT"
+       fi
+       if [ -f "$SERVERCERT" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlscert=$SERVERCERT"
+       fi
+       if [ -f "$SERVERKEY" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlskey=$SERVERKEY"
+       fi
+   fi

     mkdir -p "$DOCKER_DIR"
tianon commented 9 years ago

I tried to replicate the existing logic as closely as possible minus the explicit certificate generation.

tianon commented 9 years ago

Shoot, I guess that won't work in the case of no cert files, one sec.

tianon commented 9 years ago

Ok, more iteration:

diff --git a/rootfs/rootfs/usr/local/etc/init.d/docker b/rootfs/rootfs/usr/local/etc/init.d/docker
index 65a287e..44dcffd 100644
--- a/rootfs/rootfs/usr/local/etc/init.d/docker
+++ b/rootfs/rootfs/usr/local/etc/init.d/docker
@@ -6,77 +6,38 @@
 test -f '/var/lib/boot2docker/profile' && . '/var/lib/boot2docker/profile'

 : ${DOCKER_HOST:='-H tcp://0.0.0.0:2375'}
-: ${DOCKER_TLS:=auto}
 : ${DOCKER_STORAGE:=auto}
 : ${DOCKER_DIR:=/var/lib/docker}
 : ${DOCKER_ULIMITS:=1048576}
 : ${DOCKER_LOGFILE:=/var/lib/boot2docker/docker.log}

-: ${CERTDIR:=/var/lib/boot2docker/tls/}
-: ${CERT_INTERFACES:='eth0 eth1'}
+: ${DOCKER_TLS:=auto} # 'no' or 'auto'
 : ${CACERT:="${CERTDIR}ca.pem"}
-: ${CAKEY:="${CERTDIR}cakey.pem"}
 : ${SERVERCERT:="${CERTDIR}server.pem"}
 : ${SERVERKEY:="${CERTDIR}serverkey.pem"}
-: ${CERT:="${CERTDIR}cert.pem"}
-: ${KEY:="${CERTDIR}key.pem"}
-: ${ORG:=Boot2Docker}
-: ${SERVERORG:="${ORG}"}
-: ${CAORG:="${ORG}CA"} # Append 'CA'; see <http://rt.openssl.org/Ticket/History.html?use r=guest&pass=guest&id=3979>

 # Add /usr/local/sbin to the path.
 export PATH=${PATH}:/usr/local/sbin

 start() {
-    # Not enabling Docker daemon TLS by default.
-    if [ "$DOCKER_TLS" != "no" ]; then
-        CERTHOSTNAMES="$(hostname -s),$(hostname -i)"
-        for interface in ${CERT_INTERFACES}; do
-          IPS=$(ip addr show ${interface} |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p')
-          for ip in $IPS; do
-            CERTHOSTNAMES="$CERTHOSTNAMES,$ip"
-          done
-        done
-        echo "Need TLS certs for $CERTHOSTNAMES"
-
-        mkdir -p "$CERTDIR"
-        chmod 700 "$CERTDIR"
-        if [ ! -f "$CACERT" ] || [ ! -f "$CAKEY" ]; then
-            echo "Generating CA cert"
-            /usr/local/bin/generate_cert --cert="$CACERT" --key="$CAKEY" --org="$CAORG"
-            rm "$SERVERCERT" "$SERVERKEY" "$CERT" "$KEY" "$CERTDIR/hostnames"
-        fi
-
-        CERTSEXISTFOR=$(cat "$CERTDIR/hostnames" 2>/dev/null)
-        if [ "$CERTHOSTNAMES" != "$CERTSEXISTFOR" ]; then
-            echo "Generate server cert"
-            echo /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            /usr/local/bin/generate_cert --host="$CERTHOSTNAMES" --ca="$CACERT" --ca-key="$CAKEY" --cert="$SERVERCERT" --key="$SERVERKEY" --org="$SERVERORG"
-            echo "$CERTHOSTNAMES" > "$CERTDIR/hostnames"
-        fi
-
-        if [ ! -f "$CERT" ] || [ ! -f "$KEY" ]; then
-            echo "Generating client cert"
-            /usr/local/bin/generate_cert --ca="$CACERT" --ca-key="$CAKEY" --cert="$CERT" --key="$KEY" --org="$ORG"
-        fi
-
-        if [ "$DOCKER_TLS" == "auto" ]; then
-            DOCKER_HOST='-H tcp://0.0.0.0:2376'
-            EXTRA_ARGS="$EXTRA_ARGS --tlsverify --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        elif [ "$DOCKER_TLS" != "no" ]; then
-            EXTRA_ARGS="$EXTRA_ARGS $DOCKER_TLS --tlscacert=$CACERT --tlscert=$SERVERCERT --tlskey=$SERVERKEY"
-        fi
-
-        # now make the client certificates available to the docker user
-        USERCFG="/home/docker/.docker"
-        mkdir -p "$USERCFG"
-        chmod 700 "$USERCFG"
-        cp "$CACERT" "$USERCFG"
-        cp "$CERT" "$USERCFG"
-        cp "$KEY" "$USERCFG"
-        chown -R docker:staff "$USERCFG"
-    fi
+   HAVE_TLS_FILES=
+   if [ -f "$CACERT" -o -f "$SERVERCERT" -o -f "$SERVERKEY" ]; then
+       HAVE_TLS_FILES=1
+   fi
+   if [ "$DOCKER_TLS" = 'no' -o -z "$HAVE_TLS_FILES" ]; then
+       EXTRA_ARGS="$EXTRA_ARGS -H tcp://0.0.0.0:2375"
+   else
+       EXTRA_ARGS="$EXTRA_ARGS -H tcp://0.0.0.0:2376 --tlsverify"
+       if [ -f "$CACERT" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlscacert=$CACERT"
+       fi
+       if [ -f "$SERVERCERT" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlscert=$SERVERCERT"
+       fi
+       if [ -f "$SERVERKEY" ]; then
+           EXTRA_ARGS="$EXTRA_ARGS --tlskey=$SERVERKEY"
+       fi
+   fi

     mkdir -p "$DOCKER_DIR"
nathanleclaire commented 9 years ago

@tianon If you throw it into a PR on boot2docker/boot2docker, I'm happy to bake some ISOs and try it out with Machine!

tianon commented 9 years ago

Sounds good, I'm testing it personally now, and when I'm done I'll send a PR. :+1:

onejli commented 9 years ago

Woot! If the goal is to completely remove cert generation from the boot2docker image, you'll probably also want to remove the default CA, cert, key, etc. that are baked into the image.

root@default:~# ls -l /var/lib/boot2docker/tls/
total 28
-rw-r--r--    1 root     root          1046 Oct 20 02:51 ca.pem
-rw-------    1 root     root          1675 Oct 21 02:41 cakey.pem
-rw-r--r--    1 root     root          1070 Oct 18 00:16 cert.pem
-rw-r--r--    1 root     root            43 Oct 18 00:16 hostnames
-rw-------    1 root     root          1679 Oct 18 00:16 key.pem
-rw-r--r--    1 root     root          1099 Oct 18 00:16 server.pem
-rw-------    1 root     root          1675 Oct 18 00:16 serverkey.pem

docker-machine only provisions the following files

/var/lib/boot2docker/ca.pem
/var/lib/boot2docker/server.pem
/var/lib/boot2docker/server-key.pem
SvenDowideit commented 9 years ago

I use Boot2Docker without using docker-machine, on real hardware. Boot2Docker has been a general purpose micro-distro for almost 2 years - if this is intended to change, can we please find a way to alert our users before we surprise them with docker-machine-ism's (again)

i agree that my use-case is a tiny minority - so if that decision is activly made, I can trivially go back to maintaining something that suits my need.