Merge pull request #46799 from thaJeztah/bump_go_connections

vendor: github.com/docker/go-connections fa09c952e3ea (v0.5.0-dev)
This commit is contained in:
Sebastiaan van Stijn 2023-11-11 00:49:56 +01:00 committed by GitHub
commit 3b423ea778
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 60 additions and 132 deletions

View file

@ -38,7 +38,7 @@ func TestNewClientWithOpsFromEnv(t *testing.T) {
envs: map[string]string{ envs: map[string]string{
"DOCKER_CERT_PATH": "invalid/path", "DOCKER_CERT_PATH": "invalid/path",
}, },
expectedError: "Could not load X509 key pair: open invalid/path/cert.pem: no such file or directory", expectedError: "could not load X509 key pair: open invalid/path/cert.pem: no such file or directory",
}, },
{ {
doc: "default api version with cert path", doc: "default api version with cert path",

View file

@ -1198,7 +1198,7 @@ func (s *DockerDaemonSuite) TestHTTPSRun(c *testing.T) {
// TestTLSVerify verifies that --tlsverify=false turns on tls // TestTLSVerify verifies that --tlsverify=false turns on tls
func (s *DockerDaemonSuite) TestTLSVerify(c *testing.T) { func (s *DockerDaemonSuite) TestTLSVerify(c *testing.T) {
out, err := exec.Command(dockerdBinary, "--tlsverify=false").CombinedOutput() out, err := exec.Command(dockerdBinary, "--tlsverify=false").CombinedOutput()
if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") { if err == nil || !strings.Contains(string(out), "could not load X509 key pair") {
c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out)) c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out))
} }
} }

View file

@ -36,7 +36,7 @@ require (
github.com/deckarep/golang-set/v2 v2.3.0 github.com/deckarep/golang-set/v2 v2.3.0
github.com/distribution/reference v0.5.0 github.com/distribution/reference v0.5.0
github.com/docker/distribution v2.8.3+incompatible github.com/docker/distribution v2.8.3+incompatible
github.com/docker/go-connections v0.4.1-0.20231031175723-0b8c1f4e07a0 github.com/docker/go-connections v0.4.1-0.20231110212414-fa09c952e3ea
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c
github.com/docker/go-metrics v0.0.1 github.com/docker/go-metrics v0.0.1
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0

View file

@ -412,8 +412,8 @@ github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompati
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.4.1-0.20231031175723-0b8c1f4e07a0 h1:dPD5pdqsujF9jz2NQMQCDzrBSAF3M6kIxmfU98IOp9c= github.com/docker/go-connections v0.4.1-0.20231110212414-fa09c952e3ea h1:+4n+kUVbPdu6qMI9SUnSKMC+D50gNW4L7Lhk9tI2lVo=
github.com/docker/go-connections v0.4.1-0.20231031175723-0b8c1f4e07a0/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q= github.com/docker/go-connections v0.4.1-0.20231110212414-fa09c952e3ea/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=

View file

@ -177,27 +177,27 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
// Strip [] from IPV6 addresses // Strip [] from IPV6 addresses
rawIP, _, err := net.SplitHostPort(ip + ":") rawIP, _, err := net.SplitHostPort(ip + ":")
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid ip address %v: %s", ip, err) return nil, fmt.Errorf("invalid IP address %v: %w", ip, err)
} }
ip = rawIP ip = rawIP
} }
if ip != "" && net.ParseIP(ip) == nil { if ip != "" && net.ParseIP(ip) == nil {
return nil, fmt.Errorf("Invalid ip address: %s", ip) return nil, fmt.Errorf("invalid IP address: %s", ip)
} }
if containerPort == "" { if containerPort == "" {
return nil, fmt.Errorf("No port specified: %s<empty>", rawPort) return nil, fmt.Errorf("no port specified: %s<empty>", rawPort)
} }
startPort, endPort, err := ParsePortRange(containerPort) startPort, endPort, err := ParsePortRange(containerPort)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid containerPort: %s", containerPort) return nil, fmt.Errorf("invalid containerPort: %s", containerPort)
} }
var startHostPort, endHostPort uint64 = 0, 0 var startHostPort, endHostPort uint64 = 0, 0
if len(hostPort) > 0 { if len(hostPort) > 0 {
startHostPort, endHostPort, err = ParsePortRange(hostPort) startHostPort, endHostPort, err = ParsePortRange(hostPort)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid hostPort: %s", hostPort) return nil, fmt.Errorf("invalid hostPort: %s", hostPort)
} }
} }
@ -206,12 +206,12 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
// In this case, use the host port range as the dynamic // In this case, use the host port range as the dynamic
// host port range to allocate into. // host port range to allocate into.
if endPort != startPort { if endPort != startPort {
return nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort) return nil, fmt.Errorf("invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
} }
} }
if !validateProto(strings.ToLower(proto)) { if !validateProto(strings.ToLower(proto)) {
return nil, fmt.Errorf("Invalid proto: %s", proto) return nil, fmt.Errorf("invalid proto: %s", proto)
} }
ports := []PortMapping{} ports := []PortMapping{}

View file

@ -6,34 +6,10 @@ import (
"strings" "strings"
) )
// PartParser parses and validates the specified string (data) using the specified template
// e.g. ip:public:private -> 192.168.0.1:80:8000
// DEPRECATED: do not use, this function may be removed in a future version
func PartParser(template, data string) (map[string]string, error) {
// ip:public:private
var (
templateParts = strings.Split(template, ":")
parts = strings.Split(data, ":")
out = make(map[string]string, len(templateParts))
)
if len(parts) != len(templateParts) {
return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
}
for i, t := range templateParts {
value := ""
if len(parts) > i {
value = parts[i]
}
out[t] = value
}
return out, nil
}
// ParsePortRange parses and validates the specified string as a port-range (8000-9000) // ParsePortRange parses and validates the specified string as a port-range (8000-9000)
func ParsePortRange(ports string) (uint64, uint64, error) { func ParsePortRange(ports string) (uint64, uint64, error) {
if ports == "" { if ports == "" {
return 0, 0, fmt.Errorf("Empty string specified for ports.") return 0, 0, fmt.Errorf("empty string specified for ports")
} }
if !strings.Contains(ports, "-") { if !strings.Contains(ports, "-") {
start, err := strconv.ParseUint(ports, 10, 16) start, err := strconv.ParseUint(ports, 10, 16)
@ -51,7 +27,7 @@ func ParsePortRange(ports string) (uint64, uint64, error) {
return 0, 0, err return 0, 0, err
} }
if end < start { if end < start {
return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports) return 0, 0, fmt.Errorf("invalid range specified for port: %s", ports)
} }
return start, end, nil return start, end, nil
} }

View file

@ -1,4 +1,4 @@
// +build !windows //go:build !windows
package sockets package sockets
@ -15,7 +15,7 @@ const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
func configureUnixTransport(tr *http.Transport, proto, addr string) error { func configureUnixTransport(tr *http.Transport, proto, addr string) error {
if len(addr) > maxUnixSocketPathSize { if len(addr) > maxUnixSocketPathSize {
return fmt.Errorf("Unix socket path %q is too long", addr) return fmt.Errorf("unix socket path %q is too long", addr)
} }
// No need for compression in local communications. // No need for compression in local communications.
tr.DisableCompression = true tr.DisableCompression = true

View file

@ -1,9 +1,9 @@
// +build !windows //go:build !windows
/* /*
Package sockets is a simple unix domain socket wrapper. Package sockets is a simple unix domain socket wrapper.
Usage # Usage
For example: For example:
@ -42,7 +42,7 @@ For example:
if _, err := conn.Read(buf); err != nil { if _, err := conn.Read(buf); err != nil {
panic(err) panic(err)
} else if string(buf) != echoStr { } else if string(buf) != echoStr {
panic(fmt.Errorf("Msg may lost")) panic(fmt.Errorf("msg may lost"))
} }
} }
*/ */
@ -103,7 +103,7 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
// We don't use "defer" here, to reset the umask to its original value as soon // We don't use "defer" here, to reset the umask to its original value as soon
// as possible. Ideally we'd be able to detect if WithChmod() was passed as // as possible. Ideally we'd be able to detect if WithChmod() was passed as
// an option, and skip changing umask if default permissions are used. // an option, and skip changing umask if default permissions are used.
origUmask := syscall.Umask(0777) origUmask := syscall.Umask(0o777)
l, err := net.Listen("unix", path) l, err := net.Listen("unix", path)
syscall.Umask(origUmask) syscall.Umask(origUmask)
if err != nil { if err != nil {
@ -122,5 +122,5 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
// NewUnixSocket creates a unix socket with the specified path and group. // NewUnixSocket creates a unix socket with the specified path and group.
func NewUnixSocket(path string, gid int) (net.Listener, error) { func NewUnixSocket(path string, gid int) (net.Listener, error) {
return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0660)) return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0o660))
} }

View file

@ -1,5 +1,3 @@
// +build go1.7
package tlsconfig package tlsconfig
import ( import (

View file

@ -1,13 +0,0 @@
// +build !go1.7
package tlsconfig
import (
"crypto/x509"
)
// SystemCertPool returns an new empty cert pool,
// accessing system cert pool is supported in go 1.7
func SystemCertPool() (*x509.CertPool, error) {
return x509.NewCertPool(), nil
}

View file

@ -1,6 +1,7 @@
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. // Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
// //
// As a reminder from https://golang.org/pkg/crypto/tls/#Config: // As a reminder from https://golang.org/pkg/crypto/tls/#Config:
//
// A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified. // A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified.
// A Config may be reused; the tls package will also not modify it. // A Config may be reused; the tls package will also not modify it.
package tlsconfig package tlsconfig
@ -9,11 +10,9 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"github.com/pkg/errors"
) )
// Options represents the information needed to create client and server TLS configurations. // Options represents the information needed to create client and server TLS configurations.
@ -36,7 +35,12 @@ type Options struct {
ExclusiveRootPools bool ExclusiveRootPools bool
MinVersion uint16 MinVersion uint16
// If Passphrase is set, it will be used to decrypt a TLS private key // If Passphrase is set, it will be used to decrypt a TLS private key
// if the key is encrypted // if the key is encrypted.
//
// Deprecated: Use of encrypted TLS private keys has been deprecated, and
// will be removed in a future release. Golang has deprecated support for
// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
// design (see https://go-review.googlesource.com/c/go/+/264159).
Passphrase string Passphrase string
} }
@ -99,7 +103,7 @@ func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
return nil, fmt.Errorf("failed to read system certificates: %v", err) return nil, fmt.Errorf("failed to read system certificates: %v", err)
} }
} }
pemData, err := ioutil.ReadFile(caFile) pemData, err := os.ReadFile(caFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err) return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
} }
@ -109,6 +113,15 @@ func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
return certPool, nil return certPool, nil
} }
// allTLSVersions lists all the TLS versions and is used by the code that validates
// a uint16 value as a TLS version.
var allTLSVersions = map[uint16]struct{}{
tls.VersionTLS10: {},
tls.VersionTLS11: {},
tls.VersionTLS12: {},
tls.VersionTLS13: {},
}
// isValidMinVersion checks that the input value is a valid tls minimum version // isValidMinVersion checks that the input value is a valid tls minimum version
func isValidMinVersion(version uint16) bool { func isValidMinVersion(version uint16) bool {
_, ok := allTLSVersions[version] _, ok := allTLSVersions[version]
@ -120,10 +133,10 @@ func isValidMinVersion(version uint16) bool {
func adjustMinVersion(options Options, config *tls.Config) error { func adjustMinVersion(options Options, config *tls.Config) error {
if options.MinVersion > 0 { if options.MinVersion > 0 {
if !isValidMinVersion(options.MinVersion) { if !isValidMinVersion(options.MinVersion) {
return fmt.Errorf("Invalid minimum TLS version: %x", options.MinVersion) return fmt.Errorf("invalid minimum TLS version: %x", options.MinVersion)
} }
if options.MinVersion < config.MinVersion { if options.MinVersion < config.MinVersion {
return fmt.Errorf("Requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion) return fmt.Errorf("requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion)
} }
config.MinVersion = options.MinVersion config.MinVersion = options.MinVersion
} }
@ -132,9 +145,14 @@ func adjustMinVersion(options Options, config *tls.Config) error {
} }
// IsErrEncryptedKey returns true if the 'err' is an error of incorrect // IsErrEncryptedKey returns true if the 'err' is an error of incorrect
// password when trying to decrypt a TLS private key // password when trying to decrypt a TLS private key.
//
// Deprecated: Use of encrypted TLS private keys has been deprecated, and
// will be removed in a future release. Golang has deprecated support for
// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
// design (see https://go-review.googlesource.com/c/go/+/264159).
func IsErrEncryptedKey(err error) bool { func IsErrEncryptedKey(err error) bool {
return errors.Cause(err) == x509.IncorrectPasswordError return errors.Is(err, x509.IncorrectPasswordError)
} }
// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format. // getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format.
@ -151,7 +169,7 @@ func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) {
if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // Ignore SA1019 (IsEncryptedPEMBlock is deprecated) if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // Ignore SA1019 (IsEncryptedPEMBlock is deprecated)
keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) //nolint:staticcheck // Ignore SA1019 (DecryptPEMBlock is deprecated) keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) //nolint:staticcheck // Ignore SA1019 (DecryptPEMBlock is deprecated)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it") return nil, fmt.Errorf("private key is encrypted, but could not decrypt it: %w", err)
} }
keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes}) keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes})
} }
@ -167,26 +185,24 @@ func getCert(options Options) ([]tls.Certificate, error) {
return nil, nil return nil, nil
} }
errMessage := "Could not load X509 key pair" cert, err := os.ReadFile(options.CertFile)
cert, err := ioutil.ReadFile(options.CertFile)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMessage) return nil, err
} }
prKeyBytes, err := ioutil.ReadFile(options.KeyFile) prKeyBytes, err := os.ReadFile(options.KeyFile)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMessage) return nil, err
} }
prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase) prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMessage) return nil, err
} }
tlsCert, err := tls.X509KeyPair(cert, prKeyBytes) tlsCert, err := tls.X509KeyPair(cert, prKeyBytes)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMessage) return nil, err
} }
return []tls.Certificate{tlsCert}, nil return []tls.Certificate{tlsCert}, nil
@ -206,7 +222,7 @@ func Client(options Options) (*tls.Config, error) {
tlsCerts, err := getCert(options) tlsCerts, err := getCert(options)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("could not load X509 key pair: %w", err)
} }
tlsConfig.Certificates = tlsCerts tlsConfig.Certificates = tlsCerts
@ -224,9 +240,9 @@ func Server(options Options) (*tls.Config, error) {
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err) return nil, fmt.Errorf("could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err)
} }
return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err) return nil, fmt.Errorf("error reading X509 key pair - make sure the key is not encrypted (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err)
} }
tlsConfig.Certificates = []tls.Certificate{tlsCert} tlsConfig.Certificates = []tls.Certificate{tlsCert}
if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" { if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" {

View file

@ -1,7 +1,4 @@
// +build go1.5
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. // Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
//
package tlsconfig package tlsconfig
import ( import (

View file

@ -1,15 +0,0 @@
// +build !go1.5
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
//
package tlsconfig
import (
"crypto/tls"
)
// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
var clientCipherSuites = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}

View file

@ -1,16 +0,0 @@
// +build go1.13
package tlsconfig
import (
"crypto/tls"
)
// allTLSVersions lists all the TLS versions and is used by the code that validates
// a uint16 value as a TLS version.
var allTLSVersions = map[uint16]struct{}{
tls.VersionTLS10: {},
tls.VersionTLS11: {},
tls.VersionTLS12: {},
tls.VersionTLS13: {},
}

View file

@ -1,15 +0,0 @@
// +build !go1.13
package tlsconfig
import (
"crypto/tls"
)
// allTLSVersions lists all the TLS versions and is used by the code that validates
// a uint16 value as a TLS version.
var allTLSVersions = map[uint16]struct{}{
tls.VersionTLS10: {},
tls.VersionTLS11: {},
tls.VersionTLS12: {},
}

4
vendor/modules.txt vendored
View file

@ -431,8 +431,8 @@ github.com/docker/distribution/registry/client/auth/challenge
github.com/docker/distribution/registry/client/transport github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory github.com/docker/distribution/registry/storage/cache/memory
# github.com/docker/go-connections v0.4.1-0.20231031175723-0b8c1f4e07a0 # github.com/docker/go-connections v0.4.1-0.20231110212414-fa09c952e3ea
## explicit; go 1.13 ## explicit; go 1.18
github.com/docker/go-connections/nat github.com/docker/go-connections/nat
github.com/docker/go-connections/sockets github.com/docker/go-connections/sockets
github.com/docker/go-connections/tlsconfig github.com/docker/go-connections/tlsconfig