Because I just used it somewhere else and it would be nice if I didn't have to copy and paste the code.
Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -30,6 +30,7 @@ import ( |
| 30 | 30 |
"github.com/docker/docker/pkg/parsers/filters" |
| 31 | 31 |
"github.com/docker/docker/pkg/parsers/kernel" |
| 32 | 32 |
"github.com/docker/docker/pkg/signal" |
| 33 |
+ "github.com/docker/docker/pkg/sockets" |
|
| 33 | 34 |
"github.com/docker/docker/pkg/stdcopy" |
| 34 | 35 |
"github.com/docker/docker/pkg/streamformatter" |
| 35 | 36 |
"github.com/docker/docker/pkg/version" |
| ... | ... |
@@ -1402,6 +1403,26 @@ func (s *Server) ping(version version.Version, w http.ResponseWriter, r *http.Re |
| 1402 | 1402 |
return err |
| 1403 | 1403 |
} |
| 1404 | 1404 |
|
| 1405 |
+func (s *Server) initTcpSocket(addr string) (l net.Listener, err error) {
|
|
| 1406 |
+ if !s.cfg.TlsVerify {
|
|
| 1407 |
+ logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
|
| 1408 |
+ } |
|
| 1409 |
+ |
|
| 1410 |
+ var c *sockets.TlsConfig |
|
| 1411 |
+ if s.cfg.Tls || s.cfg.TlsVerify {
|
|
| 1412 |
+ c = sockets.NewTlsConfig(s.cfg.TlsCert, s.cfg.TlsKey, s.cfg.TlsCa, s.cfg.TlsVerify) |
|
| 1413 |
+ } |
|
| 1414 |
+ |
|
| 1415 |
+ if l, err = sockets.NewTcpSocket(addr, c, s.start); err != nil {
|
|
| 1416 |
+ return nil, err |
|
| 1417 |
+ } |
|
| 1418 |
+ if err := allocateDaemonPort(addr); err != nil {
|
|
| 1419 |
+ return nil, err |
|
| 1420 |
+ } |
|
| 1421 |
+ |
|
| 1422 |
+ return |
|
| 1423 |
+} |
|
| 1424 |
+ |
|
| 1405 | 1425 |
func makeHttpHandler(logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, corsHeaders string, dockerVersion version.Version) http.HandlerFunc {
|
| 1406 | 1426 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 1407 | 1427 |
// log the request |
| ... | ... |
@@ -7,8 +7,8 @@ import ( |
| 7 | 7 |
"net" |
| 8 | 8 |
"net/http" |
| 9 | 9 |
|
| 10 |
- "github.com/Sirupsen/logrus" |
|
| 11 | 10 |
"github.com/docker/docker/daemon" |
| 11 |
+ "github.com/docker/docker/pkg/sockets" |
|
| 12 | 12 |
"github.com/docker/docker/pkg/systemd" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -45,17 +45,12 @@ func (s *Server) newServer(proto, addr string) (serverCloser, error) {
|
| 45 | 45 |
} |
| 46 | 46 |
return nil, nil |
| 47 | 47 |
case "tcp": |
| 48 |
- if !s.cfg.TlsVerify {
|
|
| 49 |
- logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
|
| 50 |
- } |
|
| 51 |
- if l, err = NewTcpSocket(addr, tlsConfigFromServerConfig(s.cfg), s.start); err != nil {
|
|
| 52 |
- return nil, err |
|
| 53 |
- } |
|
| 54 |
- if err := allocateDaemonPort(addr); err != nil {
|
|
| 48 |
+ l, err = s.initTcpSocket(addr) |
|
| 49 |
+ if err != nil {
|
|
| 55 | 50 |
return nil, err |
| 56 | 51 |
} |
| 57 | 52 |
case "unix": |
| 58 |
- if l, err = NewUnixSocket(addr, s.cfg.SocketGroup, s.start); err != nil {
|
|
| 53 |
+ if l, err = sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start); err != nil {
|
|
| 59 | 54 |
return nil, err |
| 60 | 55 |
} |
| 61 | 56 |
default: |
| ... | ... |
@@ -7,7 +7,6 @@ import ( |
| 7 | 7 |
"net" |
| 8 | 8 |
"net/http" |
| 9 | 9 |
|
| 10 |
- "github.com/Sirupsen/logrus" |
|
| 11 | 10 |
"github.com/docker/docker/daemon" |
| 12 | 11 |
) |
| 13 | 12 |
|
| ... | ... |
@@ -19,13 +18,8 @@ func (s *Server) newServer(proto, addr string) (Server, error) {
|
| 19 | 19 |
) |
| 20 | 20 |
switch proto {
|
| 21 | 21 |
case "tcp": |
| 22 |
- if !s.cfg.TlsVerify {
|
|
| 23 |
- logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
|
| 24 |
- } |
|
| 25 |
- if l, err = NewTcpSocket(addr, tlsConfigFromServerConfig(s.cfg)); err != nil {
|
|
| 26 |
- return nil, err |
|
| 27 |
- } |
|
| 28 |
- if err := allocateDaemonPort(addr); err != nil {
|
|
| 22 |
+ l, err = s.initTcpSocket(addr) |
|
| 23 |
+ if err != nil {
|
|
| 29 | 24 |
return nil, err |
| 30 | 25 |
} |
| 31 | 26 |
default: |
| 32 | 27 |
deleted file mode 100644 |
| ... | ... |
@@ -1,73 +0,0 @@ |
| 1 |
-package server |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "crypto/tls" |
|
| 5 |
- "crypto/x509" |
|
| 6 |
- "fmt" |
|
| 7 |
- "io/ioutil" |
|
| 8 |
- "net" |
|
| 9 |
- "os" |
|
| 10 |
- |
|
| 11 |
- "github.com/docker/docker/pkg/listenbuffer" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-type tlsConfig struct {
|
|
| 15 |
- CA string |
|
| 16 |
- Certificate string |
|
| 17 |
- Key string |
|
| 18 |
- Verify bool |
|
| 19 |
-} |
|
| 20 |
- |
|
| 21 |
-func tlsConfigFromServerConfig(conf *ServerConfig) *tlsConfig {
|
|
| 22 |
- verify := conf.TlsVerify |
|
| 23 |
- if !conf.Tls && !conf.TlsVerify {
|
|
| 24 |
- return nil |
|
| 25 |
- } |
|
| 26 |
- return &tlsConfig{
|
|
| 27 |
- Verify: verify, |
|
| 28 |
- Certificate: conf.TlsCert, |
|
| 29 |
- Key: conf.TlsKey, |
|
| 30 |
- CA: conf.TlsCa, |
|
| 31 |
- } |
|
| 32 |
-} |
|
| 33 |
- |
|
| 34 |
-func NewTcpSocket(addr string, config *tlsConfig, activate <-chan struct{}) (net.Listener, error) {
|
|
| 35 |
- l, err := listenbuffer.NewListenBuffer("tcp", addr, activate)
|
|
| 36 |
- if err != nil {
|
|
| 37 |
- return nil, err |
|
| 38 |
- } |
|
| 39 |
- if config != nil {
|
|
| 40 |
- if l, err = setupTls(l, config); err != nil {
|
|
| 41 |
- return nil, err |
|
| 42 |
- } |
|
| 43 |
- } |
|
| 44 |
- return l, nil |
|
| 45 |
-} |
|
| 46 |
- |
|
| 47 |
-func setupTls(l net.Listener, config *tlsConfig) (net.Listener, error) {
|
|
| 48 |
- tlsCert, err := tls.LoadX509KeyPair(config.Certificate, config.Key) |
|
| 49 |
- if err != nil {
|
|
| 50 |
- if os.IsNotExist(err) {
|
|
| 51 |
- return nil, fmt.Errorf("Could not load X509 key pair (%s, %s): %v", config.Certificate, config.Key, err)
|
|
| 52 |
- } |
|
| 53 |
- return nil, fmt.Errorf("Error reading X509 key pair (%s, %s): %q. Make sure the key is encrypted.",
|
|
| 54 |
- config.Certificate, config.Key, err) |
|
| 55 |
- } |
|
| 56 |
- tlsConfig := &tls.Config{
|
|
| 57 |
- NextProtos: []string{"http/1.1"},
|
|
| 58 |
- Certificates: []tls.Certificate{tlsCert},
|
|
| 59 |
- // Avoid fallback on insecure SSL protocols |
|
| 60 |
- MinVersion: tls.VersionTLS10, |
|
| 61 |
- } |
|
| 62 |
- if config.CA != "" {
|
|
| 63 |
- certPool := x509.NewCertPool() |
|
| 64 |
- file, err := ioutil.ReadFile(config.CA) |
|
| 65 |
- if err != nil {
|
|
| 66 |
- return nil, fmt.Errorf("Could not read CA certificate: %v", err)
|
|
| 67 |
- } |
|
| 68 |
- certPool.AppendCertsFromPEM(file) |
|
| 69 |
- tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert |
|
| 70 |
- tlsConfig.ClientCAs = certPool |
|
| 71 |
- } |
|
| 72 |
- return tls.NewListener(l, tlsConfig), nil |
|
| 73 |
-} |
| 74 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,80 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package server |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- "net" |
|
| 8 |
- "os" |
|
| 9 |
- "strconv" |
|
| 10 |
- "syscall" |
|
| 11 |
- |
|
| 12 |
- "github.com/Sirupsen/logrus" |
|
| 13 |
- "github.com/docker/docker/pkg/listenbuffer" |
|
| 14 |
- "github.com/docker/libcontainer/user" |
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-func NewUnixSocket(path, group string, activate <-chan struct{}) (net.Listener, error) {
|
|
| 18 |
- if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
|
|
| 19 |
- return nil, err |
|
| 20 |
- } |
|
| 21 |
- mask := syscall.Umask(0777) |
|
| 22 |
- defer syscall.Umask(mask) |
|
| 23 |
- l, err := listenbuffer.NewListenBuffer("unix", path, activate)
|
|
| 24 |
- if err != nil {
|
|
| 25 |
- return nil, err |
|
| 26 |
- } |
|
| 27 |
- if err := setSocketGroup(path, group); err != nil {
|
|
| 28 |
- l.Close() |
|
| 29 |
- return nil, err |
|
| 30 |
- } |
|
| 31 |
- if err := os.Chmod(path, 0660); err != nil {
|
|
| 32 |
- l.Close() |
|
| 33 |
- return nil, err |
|
| 34 |
- } |
|
| 35 |
- return l, nil |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func setSocketGroup(path, group string) error {
|
|
| 39 |
- if group == "" {
|
|
| 40 |
- return nil |
|
| 41 |
- } |
|
| 42 |
- if err := changeGroup(path, group); err != nil {
|
|
| 43 |
- if group != "docker" {
|
|
| 44 |
- return err |
|
| 45 |
- } |
|
| 46 |
- logrus.Debugf("Warning: could not change group %s to docker: %v", path, err)
|
|
| 47 |
- } |
|
| 48 |
- return nil |
|
| 49 |
-} |
|
| 50 |
- |
|
| 51 |
-func changeGroup(path string, nameOrGid string) error {
|
|
| 52 |
- gid, err := lookupGidByName(nameOrGid) |
|
| 53 |
- if err != nil {
|
|
| 54 |
- return err |
|
| 55 |
- } |
|
| 56 |
- logrus.Debugf("%s group found. gid: %d", nameOrGid, gid)
|
|
| 57 |
- return os.Chown(path, 0, gid) |
|
| 58 |
-} |
|
| 59 |
- |
|
| 60 |
-func lookupGidByName(nameOrGid string) (int, error) {
|
|
| 61 |
- groupFile, err := user.GetGroupPath() |
|
| 62 |
- if err != nil {
|
|
| 63 |
- return -1, err |
|
| 64 |
- } |
|
| 65 |
- groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool {
|
|
| 66 |
- return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid |
|
| 67 |
- }) |
|
| 68 |
- if err != nil {
|
|
| 69 |
- return -1, err |
|
| 70 |
- } |
|
| 71 |
- if groups != nil && len(groups) > 0 {
|
|
| 72 |
- return groups[0].Gid, nil |
|
| 73 |
- } |
|
| 74 |
- gid, err := strconv.Atoi(nameOrGid) |
|
| 75 |
- if err == nil {
|
|
| 76 |
- logrus.Warnf("Could not find GID %d", gid)
|
|
| 77 |
- return gid, nil |
|
| 78 |
- } |
|
| 79 |
- return -1, fmt.Errorf("Group %s not found", nameOrGid)
|
|
| 80 |
-} |
| 82 | 2 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,69 @@ |
| 0 |
+package sockets |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "crypto/tls" |
|
| 4 |
+ "crypto/x509" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io/ioutil" |
|
| 7 |
+ "net" |
|
| 8 |
+ "os" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/docker/docker/pkg/listenbuffer" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+type TlsConfig struct {
|
|
| 14 |
+ CA string |
|
| 15 |
+ Certificate string |
|
| 16 |
+ Key string |
|
| 17 |
+ Verify bool |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func NewTlsConfig(tlsCert, tlsKey, tlsCA string, verify bool) *TlsConfig {
|
|
| 21 |
+ return &TlsConfig{
|
|
| 22 |
+ Verify: verify, |
|
| 23 |
+ Certificate: tlsCert, |
|
| 24 |
+ Key: tlsKey, |
|
| 25 |
+ CA: tlsCA, |
|
| 26 |
+ } |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func NewTcpSocket(addr string, config *TlsConfig, activate <-chan struct{}) (net.Listener, error) {
|
|
| 30 |
+ l, err := listenbuffer.NewListenBuffer("tcp", addr, activate)
|
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return nil, err |
|
| 33 |
+ } |
|
| 34 |
+ if config != nil {
|
|
| 35 |
+ if l, err = setupTls(l, config); err != nil {
|
|
| 36 |
+ return nil, err |
|
| 37 |
+ } |
|
| 38 |
+ } |
|
| 39 |
+ return l, nil |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func setupTls(l net.Listener, config *TlsConfig) (net.Listener, error) {
|
|
| 43 |
+ tlsCert, err := tls.LoadX509KeyPair(config.Certificate, config.Key) |
|
| 44 |
+ if err != nil {
|
|
| 45 |
+ if os.IsNotExist(err) {
|
|
| 46 |
+ return nil, fmt.Errorf("Could not load X509 key pair (%s, %s): %v", config.Certificate, config.Key, err)
|
|
| 47 |
+ } |
|
| 48 |
+ return nil, fmt.Errorf("Error reading X509 key pair (%s, %s): %q. Make sure the key is encrypted.",
|
|
| 49 |
+ config.Certificate, config.Key, err) |
|
| 50 |
+ } |
|
| 51 |
+ tlsConfig := &tls.Config{
|
|
| 52 |
+ NextProtos: []string{"http/1.1"},
|
|
| 53 |
+ Certificates: []tls.Certificate{tlsCert},
|
|
| 54 |
+ // Avoid fallback on insecure SSL protocols |
|
| 55 |
+ MinVersion: tls.VersionTLS10, |
|
| 56 |
+ } |
|
| 57 |
+ if config.CA != "" {
|
|
| 58 |
+ certPool := x509.NewCertPool() |
|
| 59 |
+ file, err := ioutil.ReadFile(config.CA) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return nil, fmt.Errorf("Could not read CA certificate: %v", err)
|
|
| 62 |
+ } |
|
| 63 |
+ certPool.AppendCertsFromPEM(file) |
|
| 64 |
+ tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert |
|
| 65 |
+ tlsConfig.ClientCAs = certPool |
|
| 66 |
+ } |
|
| 67 |
+ return tls.NewListener(l, tlsConfig), nil |
|
| 68 |
+} |
| 0 | 69 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,80 @@ |
| 0 |
+// +build linux |
|
| 1 |
+ |
|
| 2 |
+package sockets |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "net" |
|
| 7 |
+ "os" |
|
| 8 |
+ "strconv" |
|
| 9 |
+ "syscall" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/docker/docker/pkg/listenbuffer" |
|
| 13 |
+ "github.com/docker/libcontainer/user" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func NewUnixSocket(path, group string, activate <-chan struct{}) (net.Listener, error) {
|
|
| 17 |
+ if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
|
|
| 18 |
+ return nil, err |
|
| 19 |
+ } |
|
| 20 |
+ mask := syscall.Umask(0777) |
|
| 21 |
+ defer syscall.Umask(mask) |
|
| 22 |
+ l, err := listenbuffer.NewListenBuffer("unix", path, activate)
|
|
| 23 |
+ if err != nil {
|
|
| 24 |
+ return nil, err |
|
| 25 |
+ } |
|
| 26 |
+ if err := setSocketGroup(path, group); err != nil {
|
|
| 27 |
+ l.Close() |
|
| 28 |
+ return nil, err |
|
| 29 |
+ } |
|
| 30 |
+ if err := os.Chmod(path, 0660); err != nil {
|
|
| 31 |
+ l.Close() |
|
| 32 |
+ return nil, err |
|
| 33 |
+ } |
|
| 34 |
+ return l, nil |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func setSocketGroup(path, group string) error {
|
|
| 38 |
+ if group == "" {
|
|
| 39 |
+ return nil |
|
| 40 |
+ } |
|
| 41 |
+ if err := changeGroup(path, group); err != nil {
|
|
| 42 |
+ if group != "docker" {
|
|
| 43 |
+ return err |
|
| 44 |
+ } |
|
| 45 |
+ logrus.Debugf("Warning: could not change group %s to docker: %v", path, err)
|
|
| 46 |
+ } |
|
| 47 |
+ return nil |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+func changeGroup(path string, nameOrGid string) error {
|
|
| 51 |
+ gid, err := lookupGidByName(nameOrGid) |
|
| 52 |
+ if err != nil {
|
|
| 53 |
+ return err |
|
| 54 |
+ } |
|
| 55 |
+ logrus.Debugf("%s group found. gid: %d", nameOrGid, gid)
|
|
| 56 |
+ return os.Chown(path, 0, gid) |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func lookupGidByName(nameOrGid string) (int, error) {
|
|
| 60 |
+ groupFile, err := user.GetGroupPath() |
|
| 61 |
+ if err != nil {
|
|
| 62 |
+ return -1, err |
|
| 63 |
+ } |
|
| 64 |
+ groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool {
|
|
| 65 |
+ return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid |
|
| 66 |
+ }) |
|
| 67 |
+ if err != nil {
|
|
| 68 |
+ return -1, err |
|
| 69 |
+ } |
|
| 70 |
+ if groups != nil && len(groups) > 0 {
|
|
| 71 |
+ return groups[0].Gid, nil |
|
| 72 |
+ } |
|
| 73 |
+ gid, err := strconv.Atoi(nameOrGid) |
|
| 74 |
+ if err == nil {
|
|
| 75 |
+ logrus.Warnf("Could not find GID %d", gid)
|
|
| 76 |
+ return gid, nil |
|
| 77 |
+ } |
|
| 78 |
+ return -1, fmt.Errorf("Group %s not found", nameOrGid)
|
|
| 79 |
+} |