From 8d33c2c68026e2da403d8d31a30942ae80ee3d35 Mon Sep 17 00:00:00 2001 From: "Jonathan Leibiusky @xetorthio" Date: Fri, 15 Sep 2017 21:28:27 -0300 Subject: [PATCH] Proxy both http and https to docker daemon --- docker/factory.go | 61 ++++++++++++++++++++++++++++- docker/local_cached_factory.go | 43 ++------------------ dockerfiles/dind/Dockerfile.dind-ee | 4 +- dockerfiles/dind/ee/cert.pem | 29 ++++++++++++++ dockerfiles/dind/ee/daemon.json | 10 +++++ dockerfiles/dind/ee/key.pem | 51 ++++++++++++++++++++++++ provisioner/dind.go | 1 + provisioner/windows.go | 1 + 8 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 dockerfiles/dind/ee/cert.pem create mode 100644 dockerfiles/dind/ee/daemon.json create mode 100644 dockerfiles/dind/ee/key.pem diff --git a/docker/factory.go b/docker/factory.go index d5ebd97..2b4bc74 100644 --- a/docker/factory.go +++ b/docker/factory.go @@ -1,8 +1,67 @@ package docker -import "github.com/play-with-docker/play-with-docker/pwd/types" +import ( + "crypto/tls" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "github.com/docker/docker/api" + "github.com/docker/docker/client" + "github.com/docker/go-connections/tlsconfig" + "github.com/play-with-docker/play-with-docker/pwd/types" + "github.com/play-with-docker/play-with-docker/router" +) type FactoryApi interface { GetForSession(sessionId string) (DockerApi, error) GetForInstance(instance *types.Instance) (DockerApi, error) } + +func NewClient(instance *types.Instance, proxyHost string) (*client.Client, error) { + host := router.EncodeHost(instance.SessionId, instance.IP, router.HostOpts{EncodedPort: 2375}) + var durl string + + var tlsConfig *tls.Config + if (len(instance.Cert) > 0 && len(instance.Key) > 0) || instance.Tls { + tlsConfig = tlsconfig.ClientDefault() + tlsConfig.InsecureSkipVerify = true + tlsConfig.ServerName = host + if len(instance.Cert) > 0 && len(instance.Key) > 0 { + tlsCert, err := tls.X509KeyPair(instance.Cert, instance.Key) + if err != nil { + return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err) + } + tlsConfig.Certificates = []tls.Certificate{tlsCert} + } + } + + transport := &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 1 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + MaxIdleConnsPerHost: 5, + } + + if tlsConfig != nil { + transport.TLSClientConfig = tlsConfig + durl = fmt.Sprintf("https://%s", proxyHost) + } else { + transport.Proxy = http.ProxyURL(&url.URL{Host: proxyHost}) + durl = fmt.Sprintf("http://%s", host) + } + + cli := &http.Client{ + Transport: transport, + } + + dc, err := client.NewClient(durl, api.DefaultVersion, cli, nil) + if err != nil { + return nil, fmt.Errorf("Could not connect to DinD docker daemon", err) + } + + return dc, nil +} diff --git a/docker/local_cached_factory.go b/docker/local_cached_factory.go index 2255278..9fa407c 100644 --- a/docker/local_cached_factory.go +++ b/docker/local_cached_factory.go @@ -2,20 +2,13 @@ package docker import ( "context" - "crypto/tls" "fmt" "log" - "net" - "net/http" - "net/url" "sync" "time" - "github.com/docker/docker/api" "github.com/docker/docker/client" - "github.com/docker/go-connections/tlsconfig" "github.com/play-with-docker/play-with-docker/pwd/types" - "github.com/play-with-docker/play-with-docker/router" "github.com/play-with-docker/play-with-docker/storage" ) @@ -80,39 +73,9 @@ func (f *localCachedFactory) GetForInstance(instance *types.Instance) (DockerApi } } - // Need to create client to the DinD docker daemon - // We check if the client needs to use TLS - var tlsConfig *tls.Config - if (len(instance.Cert) > 0 && len(instance.Key) > 0) || instance.Tls { - tlsConfig = tlsconfig.ClientDefault() - tlsConfig.InsecureSkipVerify = true - if len(instance.Cert) > 0 && len(instance.Key) > 0 { - tlsCert, err := tls.X509KeyPair(instance.Cert, instance.Key) - if err != nil { - return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err) - } - tlsConfig.Certificates = []tls.Certificate{tlsCert} - } - } - - proxyUrl, _ := url.Parse("http://l2:443") - transport := &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: 1 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - MaxIdleConnsPerHost: 5, - Proxy: http.ProxyURL(proxyUrl), - } - if tlsConfig != nil { - transport.TLSClientConfig = tlsConfig - } - cli := &http.Client{ - Transport: transport, - } - dc, err := client.NewClient(fmt.Sprintf("http://%s", router.EncodeHost(instance.SessionId, instance.IP, router.HostOpts{EncodedPort: 2375})), api.DefaultVersion, cli, nil) + dc, err := NewClient(instance, "l2:443") if err != nil { - return nil, fmt.Errorf("Could not connect to DinD docker daemon", err) + return nil, err } err = f.check(dc) if err != nil { @@ -129,7 +92,7 @@ func (f *localCachedFactory) check(c *client.Client) error { for i := 0; i < 5; i++ { _, err := c.Ping(context.Background()) if err != nil { - log.Printf("Connection to [%s] has failed, maybe instance is not ready yet, sleeping and retrying in 1 second. Try #%d\n", c.DaemonHost(), i+1) + log.Printf("Connection to [%s] has failed, maybe instance is not ready yet, sleeping and retrying in 1 second. Try #%d. Got: %v\n", c.DaemonHost(), i+1, err) time.Sleep(time.Second) continue } diff --git a/dockerfiles/dind/Dockerfile.dind-ee b/dockerfiles/dind/Dockerfile.dind-ee index 5a22b7a..5c3446e 100644 --- a/dockerfiles/dind/Dockerfile.dind-ee +++ b/dockerfiles/dind/Dockerfile.dind-ee @@ -19,7 +19,9 @@ RUN rm /sbin/modprobe && echo '#!/bin/true' >/sbin/modprobe && chmod +x /sbin/mo COPY ["docker-prompt", "ucp.sh", "/usr/local/bin/"] COPY [".vimrc",".profile", ".inputrc", ".gitconfig", "workshop.lic", "./root/"] COPY ["motd", "/etc/motd"] -COPY ["daemon.json", "/etc/docker/"] +COPY ["ee/daemon.json", "/etc/docker/"] +COPY ["ee/cert.pem", "/var/run/pwd/certs/"] +COPY ["ee/key.pem", "/var/run/pwd/certs/"] # Move to our home WORKDIR /root diff --git a/dockerfiles/dind/ee/cert.pem b/dockerfiles/dind/ee/cert.pem new file mode 100644 index 0000000..e600f76 --- /dev/null +++ b/dockerfiles/dind/ee/cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE9jCCAt6gAwIBAgIQSCiXatddwed3bL9M9bierjANBgkqhkiG9w0BAQsFADAO +MQwwCgYDVQQKEwNVQ1AwHhcNMTcwOTE1MjAzMzAwWhcNMjAwODMwMjAzMzAwWjAO +MQwwCgYDVQQKEwNVQ1AwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCq +prmPRweArtZQ6HHDeYCSC3WxQOy6hakc3VZa6JEldbEoVjOc7MqZNPvTIp8b/W8H +O10ibEGZ03vyeq10UsiFQiYmdhn1SqEilZnFSo892PSpGaN7VO325uUnIccJqc3O +0YOdvNCdp9roZZ/K7z9nuC37cLy6+Lq2oLr1WYAxncJHedUi3LQCC+2qEBIVL+md +9yE8amFrYbDhbNqmIcAJ2KmkqBPa0Pa+Qe1FxqQI5zJOT5rOJgF3JbWeqFpm0Zjx +CPTt0cPY4lyQ2U9lyMXJmS4+R0wekkZXywaU1mJi3JJIlMSBMWmWoTrx5mLVWOLv +u44hYerfOmN+ImXRWq4NAPLi4722/OLzCmFn81fdUHOFyxg2Tr23b6I6sMyUfLJ0 +lqS+thJ7N/tcQe3nTeQm9dcruDbJpjJQrQkjq9CFFsxNEXBT6EFMRp8oDutOAyHf +guVeqdH5kz6vprNiLfSTqqZSEeQokRkHTyxpZ4grBBCiocsAxm8yLNqhcg3w44CN +9G/3pylgu7xYSEXHYnnlxsk0MHxDFZ4NTo0UBuyIuozoePIS63GvsyBsBzKzO/RZ +NsnPm3klZ4QnT3dIe0eRtCyu/prRmEMD/zC20fRcAuiG7jyV9NB/9mbLeDjAAngW +1UhrWpAMiObQZN4h5+ofc0EXFHVvOWaqBmYXlNlEeQIDAQABo1AwTjAOBgNVHQ8B +Af8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB +/wQCMAAwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAgEAFT1PFimD +KGg8fVjuUO9IXf12LA7c+M6Eltyz22Ffxgopl1eHi4xHEfU94ueUAmODrag7Rc4E +VmvrMFIsuFrX/xYjiu2gpHPOP2nQjNRAwKDU0gr2bZ+y98EBtlYO/aFMmYCxJr7B +6esyA7I/cwLTxaNoTh67VTdPhfDmuEshoQn7Mtop38suevU5YBMTmUl7cp8bVdib +j7UkTq0oRKmAchMAz3W0TgGw9ZKJzU6zEck/3Csz5RWlTI9HV7R7J8aGEIeHGf/i +G+tfg0T8h+rQPkyCic5DIYuQzZ/P9pfJkedZuQU/mu0U/0IsNdkv9NX/4RQazu/Q +OzQ71FOO2HR/S3hcLzS1Iy2zrHbARwji/Sr95gVE1Z4QCK2xSvyy9aqzHwRfc4SX +AzaJhkACCnY7VDK6WJW7jnfkYco+l0tczDkyPjE7h3wP35tCuAZAvGkcrIbBL4oR +8bnwYAOqiG0cPBmFDBYW7v19qIspw5XDjfMu4YEHon7pYdiKK0Brf0iL+Ep4b1oB +8uvAysbc2Z/gIj1AsfnwSnrzcvzO6H1oCye277cSn2Z/ebiBaQi+kR3mubX96aPy +bFc9Xb11/y0Y7kYmJ3ifHDJkWerpz5bWEm2KDq1qsFRH9zUMEVfJAXThITawqfuG +3UBYWv8RePLnRbbnPuSaO9slNCoKl3NLqyk= +-----END CERTIFICATE----- diff --git a/dockerfiles/dind/ee/daemon.json b/dockerfiles/dind/ee/daemon.json new file mode 100644 index 0000000..8b2b06f --- /dev/null +++ b/dockerfiles/dind/ee/daemon.json @@ -0,0 +1,10 @@ +{ + "experimental": true, + "debug": true, + "log-level": "info", + "insecure-registries": ["127.0.0.1"], + "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"], + "tls": true, + "tlscert": "/var/run/pwd/certs/cert.pem", + "tlskey": "/var/run/pwd/certs/key.pem" +} diff --git a/dockerfiles/dind/ee/key.pem b/dockerfiles/dind/ee/key.pem new file mode 100644 index 0000000..dbae394 --- /dev/null +++ b/dockerfiles/dind/ee/key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/provisioner/dind.go b/provisioner/dind.go index 21e6497..3f94d0a 100644 --- a/provisioner/dind.go +++ b/provisioner/dind.go @@ -99,6 +99,7 @@ func (d *DinD) InstanceNew(session *types.Session, conf types.InstanceConfig) (* instance.ServerCert = conf.ServerCert instance.ServerKey = conf.ServerKey instance.CACert = conf.CACert + instance.Tls = conf.Tls instance.ProxyHost = router.EncodeHost(session.Id, instance.RoutableIP, router.HostOpts{}) instance.SessionHost = session.Host diff --git a/provisioner/windows.go b/provisioner/windows.go index 636b9f8..6450cdb 100644 --- a/provisioner/windows.go +++ b/provisioner/windows.go @@ -85,6 +85,7 @@ func (d *windows) InstanceNew(session *types.Session, conf types.InstanceConfig) instance.ServerCert = conf.ServerCert instance.ServerKey = conf.ServerKey instance.CACert = conf.CACert + instance.Tls = conf.Tls instance.ProxyHost = router.EncodeHost(session.Id, instance.RoutableIP, router.HostOpts{}) instance.SessionHost = session.Host