github.com/openshift/source-to-image@v1.4.1-0.20240516041539-bf52fc02204e/test/integration/docker/dockerssl_test.go (about)

     1  //go:build integration
     2  // +build integration
     3  
     4  package docker
     5  
     6  import (
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"io/ioutil"
    10  	"log"
    11  	"net"
    12  	"net/http"
    13  	"os"
    14  	"runtime"
    15  	"testing"
    16  
    17  	dockerapi "github.com/docker/docker/api"
    18  
    19  	"github.com/openshift/source-to-image/pkg/api"
    20  	"github.com/openshift/source-to-image/pkg/docker"
    21  )
    22  
    23  const (
    24  	tcpListener  = "127.0.0.1:8080"
    25  	tlsListener  = "127.0.0.1:8443"
    26  	unixListener = "/tmp/test.sock"
    27  )
    28  
    29  var serverCert tls.Certificate
    30  var caPool *x509.CertPool
    31  
    32  func init() {
    33  	var err error
    34  	serverCert, err = tls.LoadX509KeyPair("../testdata/127.0.0.1.crt", "../testdata/127.0.0.1.key")
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  
    39  	ca, err := ioutil.ReadFile("../testdata/ca.crt")
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  
    44  	caPool = x509.NewCertPool()
    45  	caPool.AppendCertsFromPEM(ca)
    46  
    47  	log.SetOutput(ioutil.Discard)
    48  }
    49  
    50  type Server struct {
    51  	l net.Listener
    52  	c chan struct{}
    53  }
    54  
    55  func (s *Server) Close() {
    56  	s.l.Close()
    57  	<-s.c
    58  }
    59  
    60  func (s *Server) serveFakeDockerAPIServer() {
    61  	mux := http.NewServeMux()
    62  	mux.HandleFunc("/v"+dockerapi.DefaultVersion+"/version", func(w http.ResponseWriter, req *http.Request) {
    63  		w.Header().Add("Content-Type", "application/json")
    64  		w.Write([]byte("{}"))
    65  	})
    66  	hs := http.Server{Handler: mux}
    67  	// Disable keepalives in order to prevent an explosion in the number of
    68  	// goroutines that makes stack traces noisy.  TODO: when using Go 1.8,
    69  	// http.Server.Shutdown() should do this for us.
    70  	hs.SetKeepAlivesEnabled(false)
    71  	hs.Serve(s.l)
    72  	s.c <- struct{}{}
    73  }
    74  
    75  func serveTLS(t *testing.T, config *tls.Config) *Server {
    76  	config.Certificates = []tls.Certificate{serverCert}
    77  
    78  	l, err := tls.Listen("tcp", tlsListener, config)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	s := &Server{l: l, c: make(chan struct{})}
    84  	go s.serveFakeDockerAPIServer()
    85  
    86  	return s
    87  }
    88  
    89  func serveTCP(t *testing.T) *Server {
    90  	l, err := net.Listen("tcp", tcpListener)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	s := &Server{l: l, c: make(chan struct{})}
    96  	go s.serveFakeDockerAPIServer()
    97  
    98  	return s
    99  }
   100  
   101  func serveUNIX(t *testing.T) *Server {
   102  	os.Remove(unixListener)
   103  
   104  	l, err := net.Listen("unix", unixListener)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  
   109  	s := &Server{l: l, c: make(chan struct{})}
   110  	go s.serveFakeDockerAPIServer()
   111  
   112  	return s
   113  }
   114  
   115  func runTest(t *testing.T, config *api.DockerConfig, expectedSuccess bool) {
   116  	client, err := docker.NewEngineAPIClient(config)
   117  	if err != nil {
   118  		if expectedSuccess {
   119  			t.Errorf("with DockerConfig %+v, expected success %v, got error %v", config, expectedSuccess, err)
   120  		}
   121  		return
   122  	}
   123  	d := docker.New(client, api.AuthConfig{})
   124  	err = d.CheckReachable()
   125  	if (err == nil) != expectedSuccess {
   126  		t.Errorf("with DockerConfig %+v, expected success %v, got error %v", config, expectedSuccess, err)
   127  	}
   128  }
   129  
   130  func TestTCP(t *testing.T) {
   131  	s := serveTCP(t)
   132  	defer s.Close()
   133  
   134  	dc := &api.DockerConfig{Endpoint: "tcp://" + tcpListener}
   135  
   136  	for _, dc.UseTLS = range []bool{true, false} {
   137  		for _, dc.TLSVerify = range []bool{true, false} {
   138  			for _, dc.CAFile = range []string{"../testdata/ca.crt", "bad", ""} {
   139  				for _, dc.CertFile = range []string{"../testdata/client.crt", "bad", ""} {
   140  					for _, dc.KeyFile = range []string{"../testdata/client.key", "bad", ""} {
   141  						runTest(t, dc, !dc.UseTLS && !dc.TLSVerify)
   142  					}
   143  				}
   144  			}
   145  		}
   146  	}
   147  }
   148  
   149  func TestUNIX(t *testing.T) {
   150  	if runtime.GOOS == "windows" {
   151  		return
   152  	}
   153  
   154  	s := serveUNIX(t)
   155  	defer s.Close()
   156  
   157  	dc := &api.DockerConfig{Endpoint: "unix://" + unixListener}
   158  
   159  	for _, dc.UseTLS = range []bool{true, false} {
   160  		for _, dc.TLSVerify = range []bool{true, false} {
   161  			for _, dc.CAFile = range []string{"../testdata/ca.crt", "bad", ""} {
   162  				for _, dc.CertFile = range []string{"../testdata/client.crt", "bad", ""} {
   163  					for _, dc.KeyFile = range []string{"../testdata/client.key", "bad", ""} {
   164  						runTest(t, dc, !dc.UseTLS && !dc.TLSVerify)
   165  					}
   166  				}
   167  			}
   168  		}
   169  	}
   170  }
   171  
   172  func TestSSL(t *testing.T) {
   173  	s := serveTLS(t, &tls.Config{})
   174  	defer s.Close()
   175  
   176  	dc := &api.DockerConfig{Endpoint: "tcp://" + tlsListener}
   177  
   178  	for _, dc.UseTLS = range []bool{true, false} {
   179  		for _, dc.TLSVerify = range []bool{true, false} {
   180  			for _, dc.CAFile = range []string{"../testdata/ca.crt", "bad", ""} {
   181  				for _, dc.CertFile = range []string{"../testdata/client.crt", "bad", ""} {
   182  					for _, dc.KeyFile = range []string{"../testdata/client.key", "bad", ""} {
   183  						expected := dc.UseTLS && !dc.TLSVerify || dc.TLSVerify && dc.CAFile == "../testdata/ca.crt"
   184  
   185  						if (dc.CertFile == "../testdata/client.crt") != (dc.KeyFile == "../testdata/client.key") {
   186  							expected = false
   187  						}
   188  
   189  						runTest(t, dc, expected)
   190  					}
   191  				}
   192  			}
   193  		}
   194  	}
   195  }
   196  
   197  func TestSSLClientCert(t *testing.T) {
   198  	s := serveTLS(t, &tls.Config{
   199  		ClientAuth: tls.RequireAndVerifyClientCert,
   200  		ClientCAs:  caPool,
   201  	})
   202  	defer s.Close()
   203  
   204  	dc := &api.DockerConfig{Endpoint: "tcp://" + tlsListener}
   205  
   206  	for _, dc.UseTLS = range []bool{true, false} {
   207  		for _, dc.TLSVerify = range []bool{true, false} {
   208  			for _, dc.CAFile = range []string{"../testdata/ca.crt", "bad", ""} {
   209  				for _, dc.CertFile = range []string{"../testdata/client.crt", "bad", ""} {
   210  					for _, dc.KeyFile = range []string{"../testdata/client.key", "bad", ""} {
   211  						expected := dc.UseTLS && !dc.TLSVerify || dc.TLSVerify && dc.CAFile == "../testdata/ca.crt"
   212  
   213  						if dc.CertFile != "../testdata/client.crt" || dc.KeyFile != "../testdata/client.key" {
   214  							expected = false
   215  						}
   216  
   217  						runTest(t, dc, expected)
   218  					}
   219  				}
   220  			}
   221  		}
   222  	}
   223  }