Fix bugs introduced mainly to docker-machine driver when we added TLS proxy
This commit is contained in:
@@ -45,6 +45,10 @@ CMD cat /etc/hosts >/etc/hosts.bak && \
|
||||
sed 's/^::1.*//' /etc/hosts.bak > /etc/hosts && \
|
||||
sed -i "s/\DOCKER_STORAGE_DRIVER/$DOCKER_STORAGE_DRIVER/" /etc/docker/daemon.json && \
|
||||
sed -i "s/\PWD_IP_ADDRESS/$PWD_IP_ADDRESS/" /etc/docker/daemon.json && \
|
||||
sed -i "s/\DOCKER_TLSENABLE/$DOCKER_TLSENABLE/" /etc/docker/daemon.json && \
|
||||
sed -i "s/\DOCKER_TLSCACERT/$DOCKER_TLSCACERT/" /etc/docker/daemon.json && \
|
||||
sed -i "s/\DOCKER_TLSCERT/$DOCKER_TLSCERT/" /etc/docker/daemon.json && \
|
||||
sed -i "s/\DOCKER_TLSKEY/$DOCKER_TLSKEY/" /etc/docker/daemon.json && \
|
||||
umount /var/lib/docker && mount -t securityfs none /sys/kernel/security && \
|
||||
dockerd &>/docker.log & \
|
||||
while true ; do script -q -c "/bin/bash -l" /dev/null ; done
|
||||
|
||||
@@ -6,5 +6,9 @@
|
||||
"insecure-registries": ["127.0.0.1"],
|
||||
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"],
|
||||
"storage-driver": "DOCKER_STORAGE_DRIVER",
|
||||
"dns": ["PWD_IP_ADDRESS", "8.8.8.8"]
|
||||
"dns": ["PWD_IP_ADDRESS", "8.8.8.8"],
|
||||
"tls": DOCKER_TLSENABLE,
|
||||
"tlscacert": "DOCKER_TLSCACERT",
|
||||
"tlscert": "DOCKER_TLSCERT",
|
||||
"tlskey": "DOCKER_TLSKEY"
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/play-with-docker/play-with-docker/services"
|
||||
)
|
||||
|
||||
func SetKeys(rw http.ResponseWriter, req *http.Request) {
|
||||
vars := mux.Vars(req)
|
||||
sessionId := vars["sessionId"]
|
||||
instanceName := vars["instanceName"]
|
||||
|
||||
type certs struct {
|
||||
ServerCert []byte `json:"server_cert"`
|
||||
ServerKey []byte `json:"server_key"`
|
||||
}
|
||||
|
||||
var c certs
|
||||
jsonErr := json.NewDecoder(req.Body).Decode(&c)
|
||||
if jsonErr != nil {
|
||||
log.Println(jsonErr)
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
s := services.GetSession(sessionId)
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
i := services.GetInstance(s, instanceName)
|
||||
|
||||
_, err := i.SetCertificate(c.ServerCert, c.ServerKey)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
log.Printf("Set keys for instance %s\n", instanceName)
|
||||
}
|
||||
@@ -9,10 +9,12 @@ import (
|
||||
"strings"
|
||||
|
||||
vhost "github.com/inconshreveable/go-vhost"
|
||||
"github.com/play-with-docker/play-with-docker/services"
|
||||
)
|
||||
|
||||
func StartTLSProxy(port string) {
|
||||
var validProxyHost = regexp.MustCompile(`^.*pwd([0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3})(?:-?([0-9]{1,5}))?\..*$`)
|
||||
var validAliasProxyHost = regexp.MustCompile(`^.*pwd([0-9|a-z|A-Z]*)-([0-9|a-z|A-Z]{8})(?:-?([0-9]{1,5}))?\..*$`)
|
||||
|
||||
tlsListener, tlsErr := net.Listen("tcp", fmt.Sprintf(":%s", port))
|
||||
log.Println("Listening on port " + port)
|
||||
@@ -37,26 +39,42 @@ func StartTLSProxy(port string) {
|
||||
}
|
||||
defer vhostConn.Close()
|
||||
|
||||
host := vhostConn.ClientHelloMsg.ServerName
|
||||
match := validProxyHost.FindStringSubmatch(host)
|
||||
if len(match) < 2 {
|
||||
// Not a valid proxy host, just close connection.
|
||||
return
|
||||
}
|
||||
|
||||
var targetIP string
|
||||
targetPort := "443"
|
||||
|
||||
host := vhostConn.ClientHelloMsg.ServerName
|
||||
match := validProxyHost.FindStringSubmatch(host)
|
||||
if len(match) < 2 {
|
||||
// Not a valid proxy host, try alias hosts
|
||||
match := validAliasProxyHost.FindStringSubmatch(host)
|
||||
if len(match) < 4 {
|
||||
// Not valid, just close the connection
|
||||
return
|
||||
} else {
|
||||
alias := match[1]
|
||||
sessionPrefix := match[2]
|
||||
instance := services.FindInstanceByAlias(sessionPrefix, alias)
|
||||
if instance != nil {
|
||||
targetIP = instance.IP
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if len(match) == 4 {
|
||||
targetPort = match[3]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Valid proxy host
|
||||
ip := strings.Replace(match[1], "-", ".", -1)
|
||||
if net.ParseIP(ip) == nil {
|
||||
// Not a valid IP, so treat this is a hostname.
|
||||
return
|
||||
} else {
|
||||
targetIP = ip
|
||||
}
|
||||
if len(match) == 3 {
|
||||
targetPort = match[2]
|
||||
}
|
||||
|
||||
ip := strings.Replace(match[1], "-", ".", -1)
|
||||
|
||||
if net.ParseIP(ip) == nil {
|
||||
// Not a valid IP, so treat this is a hostname.
|
||||
} else {
|
||||
targetIP = ip
|
||||
}
|
||||
|
||||
dest := fmt.Sprintf("%s:%s", targetIP, targetPort)
|
||||
|
||||
@@ -244,14 +244,14 @@ func CreateInstance(session *Session, conf InstanceConfig) (*Instance, error) {
|
||||
|
||||
// Write certs to container cert dir
|
||||
if len(conf.ServerCert) > 0 {
|
||||
env = append(env, "DOCKER_TLSCERT=/var/run/pwd/certs/cert.pem")
|
||||
env = append(env, `DOCKER_TLSCERT=\/var\/run\/pwd\/certs\/cert.pem`)
|
||||
}
|
||||
if len(conf.ServerKey) > 0 {
|
||||
env = append(env, "DOCKER_TLSKEY=/var/run/pwd/certs/key.pem")
|
||||
env = append(env, `DOCKER_TLSKEY=\/var\/run\/pwd\/certs\/key.pem`)
|
||||
}
|
||||
if len(conf.CACert) > 0 {
|
||||
// if ca cert is specified, verify that clients that connects present a certificate signed by the CA
|
||||
env = append(env, "DOCKER_TLSCACERT=/var/run/pwd/certs/ca.pem")
|
||||
env = append(env, `DOCKER_TLSCACERT=\/var\/run\/pwd\/certs\/ca.pem`)
|
||||
}
|
||||
if len(conf.ServerCert) > 0 || len(conf.ServerKey) > 0 || len(conf.CACert) > 0 {
|
||||
// if any of the certs is specified, enable TLS
|
||||
@@ -323,7 +323,11 @@ func CreateInstance(session *Session, conf InstanceConfig) (*Instance, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Instance{Name: containerName, Hostname: cinfo.Config.Hostname, IP: cinfo.NetworkSettings.Networks[session.Id].IPAddress}, nil
|
||||
return &Instance{
|
||||
Name: containerName,
|
||||
Hostname: cinfo.Config.Hostname,
|
||||
IP: cinfo.NetworkSettings.Networks[session.Id].IPAddress,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func copyIfSet(content []byte, fileName, path, containerName string) error {
|
||||
|
||||
@@ -2,7 +2,6 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -38,11 +37,13 @@ type Instance struct {
|
||||
Mem string `json:"mem"`
|
||||
Cpu string `json:"cpu"`
|
||||
Alias string `json:"alias"`
|
||||
Ports UInt16Slice
|
||||
tempPorts []uint16 `json:"-"`
|
||||
ServerCert []byte `json:"server_cert"`
|
||||
ServerKey []byte `json:"server_key"`
|
||||
cert *tls.Certificate `json:"-"`
|
||||
CACert []byte `json:"ca_cert"`
|
||||
Cert []byte `json:"cert"`
|
||||
Key []byte `json:"key"`
|
||||
Ports UInt16Slice
|
||||
}
|
||||
|
||||
type InstanceConfig struct {
|
||||
@@ -51,6 +52,8 @@ type InstanceConfig struct {
|
||||
ServerCert []byte
|
||||
ServerKey []byte
|
||||
CACert []byte
|
||||
Cert []byte
|
||||
Key []byte
|
||||
}
|
||||
|
||||
func (i *Instance) setUsedPort(port uint16) {
|
||||
@@ -65,25 +68,6 @@ func (i *Instance) setUsedPort(port uint16) {
|
||||
i.tempPorts = append(i.tempPorts, port)
|
||||
}
|
||||
|
||||
func (i *Instance) SetCertificate(cert, key []byte) (*tls.Certificate, error) {
|
||||
i.ServerCert = cert
|
||||
i.ServerKey = key
|
||||
c, e := tls.X509KeyPair(i.ServerCert, i.ServerKey)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
i.cert = &c
|
||||
|
||||
// We store sessions as soon as we set instance keys
|
||||
if err := saveSessionsToDisk(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i.cert, nil
|
||||
}
|
||||
func (i *Instance) GetCertificate() *tls.Certificate {
|
||||
return i.cert
|
||||
}
|
||||
|
||||
func (i *Instance) IsConnected() bool {
|
||||
return i.conn != nil
|
||||
|
||||
@@ -119,7 +103,11 @@ func NewInstance(session *Session, conf InstanceConfig) (*Instance, error) {
|
||||
}
|
||||
|
||||
instance.Alias = conf.Alias
|
||||
|
||||
instance.Cert = conf.Cert
|
||||
instance.Key = conf.Key
|
||||
instance.ServerCert = conf.ServerCert
|
||||
instance.ServerKey = conf.ServerKey
|
||||
instance.CACert = conf.CACert
|
||||
instance.session = session
|
||||
|
||||
if session.Instances == nil {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"log"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/googollee/go-socket.io"
|
||||
"github.com/play-with-docker/play-with-docker/config"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -99,11 +101,27 @@ func (s *Session) SchedulePeriodicTasks() {
|
||||
if i.dockerClient == nil {
|
||||
// Need to create client to the DinD docker daemon
|
||||
|
||||
// We check if the client needs to use TLS
|
||||
var tlsConfig *tls.Config
|
||||
if len(i.Cert) > 0 && len(i.Key) > 0 {
|
||||
tlsConfig = tlsconfig.ClientDefault()
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsCert, err := tls.X509KeyPair(i.Cert, i.Key)
|
||||
if err != nil {
|
||||
log.Println("Could not load X509 key pair: %v. Make sure the key is not encrypted", err)
|
||||
continue
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
||||
}
|
||||
|
||||
transport := &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 1 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext}
|
||||
if tlsConfig != nil {
|
||||
transport.TLSClientConfig = tlsConfig
|
||||
}
|
||||
cli := &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
@@ -313,14 +331,6 @@ func LoadSessionsFromDisk() error {
|
||||
for _, i := range s.Instances {
|
||||
// wire the session back to the instance
|
||||
i.session = s
|
||||
|
||||
if i.ServerCert != nil && i.ServerKey != nil {
|
||||
_, err := i.SetCertificate(i.ServerCert, i.ServerKey)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect PWD daemon to the new network
|
||||
|
||||
Reference in New Issue
Block a user