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 's/^::1.*//' /etc/hosts.bak > /etc/hosts && \
|
||||||
sed -i "s/\DOCKER_STORAGE_DRIVER/$DOCKER_STORAGE_DRIVER/" /etc/docker/daemon.json && \
|
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/\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 && \
|
umount /var/lib/docker && mount -t securityfs none /sys/kernel/security && \
|
||||||
dockerd &>/docker.log & \
|
dockerd &>/docker.log & \
|
||||||
while true ; do script -q -c "/bin/bash -l" /dev/null ; done
|
while true ; do script -q -c "/bin/bash -l" /dev/null ; done
|
||||||
|
|||||||
@@ -6,5 +6,9 @@
|
|||||||
"insecure-registries": ["127.0.0.1"],
|
"insecure-registries": ["127.0.0.1"],
|
||||||
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"],
|
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"],
|
||||||
"storage-driver": "DOCKER_STORAGE_DRIVER",
|
"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"
|
"strings"
|
||||||
|
|
||||||
vhost "github.com/inconshreveable/go-vhost"
|
vhost "github.com/inconshreveable/go-vhost"
|
||||||
|
"github.com/play-with-docker/play-with-docker/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartTLSProxy(port string) {
|
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 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))
|
tlsListener, tlsErr := net.Listen("tcp", fmt.Sprintf(":%s", port))
|
||||||
log.Println("Listening on port " + port)
|
log.Println("Listening on port " + port)
|
||||||
@@ -37,26 +39,42 @@ func StartTLSProxy(port string) {
|
|||||||
}
|
}
|
||||||
defer vhostConn.Close()
|
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
|
var targetIP string
|
||||||
targetPort := "443"
|
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 {
|
if len(match) == 3 {
|
||||||
targetPort = match[2]
|
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)
|
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
|
// Write certs to container cert dir
|
||||||
if len(conf.ServerCert) > 0 {
|
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 {
|
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 len(conf.CACert) > 0 {
|
||||||
// if ca cert is specified, verify that clients that connects present a certificate signed by the CA
|
// 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 len(conf.ServerCert) > 0 || len(conf.ServerKey) > 0 || len(conf.CACert) > 0 {
|
||||||
// if any of the certs is specified, enable TLS
|
// 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 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 {
|
func copyIfSet(content []byte, fileName, path, containerName string) error {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -38,11 +37,13 @@ type Instance struct {
|
|||||||
Mem string `json:"mem"`
|
Mem string `json:"mem"`
|
||||||
Cpu string `json:"cpu"`
|
Cpu string `json:"cpu"`
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
Ports UInt16Slice
|
|
||||||
tempPorts []uint16 `json:"-"`
|
tempPorts []uint16 `json:"-"`
|
||||||
ServerCert []byte `json:"server_cert"`
|
ServerCert []byte `json:"server_cert"`
|
||||||
ServerKey []byte `json:"server_key"`
|
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 {
|
type InstanceConfig struct {
|
||||||
@@ -51,6 +52,8 @@ type InstanceConfig struct {
|
|||||||
ServerCert []byte
|
ServerCert []byte
|
||||||
ServerKey []byte
|
ServerKey []byte
|
||||||
CACert []byte
|
CACert []byte
|
||||||
|
Cert []byte
|
||||||
|
Key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) setUsedPort(port uint16) {
|
func (i *Instance) setUsedPort(port uint16) {
|
||||||
@@ -65,25 +68,6 @@ func (i *Instance) setUsedPort(port uint16) {
|
|||||||
i.tempPorts = append(i.tempPorts, port)
|
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 {
|
func (i *Instance) IsConnected() bool {
|
||||||
return i.conn != nil
|
return i.conn != nil
|
||||||
|
|
||||||
@@ -119,7 +103,11 @@ func NewInstance(session *Session, conf InstanceConfig) (*Instance, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
instance.Alias = conf.Alias
|
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
|
instance.session = session
|
||||||
|
|
||||||
if session.Instances == nil {
|
if session.Instances == nil {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@@ -15,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/docker/api"
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/docker/go-connections/tlsconfig"
|
||||||
"github.com/googollee/go-socket.io"
|
"github.com/googollee/go-socket.io"
|
||||||
"github.com/play-with-docker/play-with-docker/config"
|
"github.com/play-with-docker/play-with-docker/config"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
@@ -99,11 +101,27 @@ func (s *Session) SchedulePeriodicTasks() {
|
|||||||
if i.dockerClient == nil {
|
if i.dockerClient == nil {
|
||||||
// Need to create client to the DinD docker daemon
|
// 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{
|
transport := &http.Transport{
|
||||||
DialContext: (&net.Dialer{
|
DialContext: (&net.Dialer{
|
||||||
Timeout: 1 * time.Second,
|
Timeout: 1 * time.Second,
|
||||||
KeepAlive: 30 * time.Second,
|
KeepAlive: 30 * time.Second,
|
||||||
}).DialContext}
|
}).DialContext}
|
||||||
|
if tlsConfig != nil {
|
||||||
|
transport.TLSClientConfig = tlsConfig
|
||||||
|
}
|
||||||
cli := &http.Client{
|
cli := &http.Client{
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
}
|
}
|
||||||
@@ -313,14 +331,6 @@ func LoadSessionsFromDisk() error {
|
|||||||
for _, i := range s.Instances {
|
for _, i := range s.Instances {
|
||||||
// wire the session back to the instance
|
// wire the session back to the instance
|
||||||
i.session = s
|
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
|
// Connect PWD daemon to the new network
|
||||||
|
|||||||
Reference in New Issue
Block a user