...

Source file src/github.com/docker/go-connections/tlsconfig/config_test.go

Documentation: github.com/docker/go-connections/tlsconfig

     1  package tlsconfig
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"encoding/pem"
     8  	"os"
     9  	"reflect"
    10  	"runtime"
    11  	"testing"
    12  )
    13  
    14  // This is the currently active Amazon Root CA 1 (CN=Amazon Root CA 1,O=Amazon,C=US),
    15  // downloaded from: https://www.amazontrust.com/repository/AmazonRootCA1.pem
    16  // It's valid since May 26 00:00:00 2015 GMT and expires on Jan 17 00:00:00 2038 GMT.
    17  // Download updated versions from https://www.amazontrust.com/repository/
    18  const (
    19  	systemRootTrustedCert = `
    20  -----BEGIN CERTIFICATE-----
    21  MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
    22  ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
    23  b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
    24  MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
    25  b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
    26  ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
    27  9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
    28  IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
    29  VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
    30  93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
    31  jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
    32  AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
    33  A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
    34  U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
    35  N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
    36  o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
    37  5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
    38  rqXRfboQnoZsG4q5WTP468SQvvG5
    39  -----END CERTIFICATE-----
    40  `
    41  	rsaPrivateKeyFile             = "fixtures/key.pem"
    42  	certificateFile               = "fixtures/cert.pem"
    43  	multiCertificateFile          = "fixtures/multi.pem"
    44  	rsaEncryptedPrivateKeyFile    = "fixtures/encrypted_key.pem"
    45  	certificateOfEncryptedKeyFile = "fixtures/cert_of_encrypted_key.pem"
    46  )
    47  
    48  // returns the name of a pre-generated, multiple-certificate CA file
    49  // with both RSA and ECDSA certs.
    50  func getMultiCert() string {
    51  	return multiCertificateFile
    52  }
    53  
    54  // returns the names of pre-generated key and certificate files.
    55  func getCertAndKey() (string, string) {
    56  	return rsaPrivateKeyFile, certificateFile
    57  }
    58  
    59  // returns the names of pre-generated, encrypted private key and
    60  // corresponding certificate file
    61  func getCertAndEncryptedKey() (string, string) {
    62  	return rsaEncryptedPrivateKeyFile, certificateOfEncryptedKeyFile
    63  }
    64  
    65  // If the cert files and directory are provided but are invalid, an error is
    66  // returned.
    67  func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
    68  	key, cert := getCertAndKey()
    69  	ca := getMultiCert()
    70  
    71  	tempFile, err := os.CreateTemp("", "cert-test")
    72  	if err != nil {
    73  		t.Fatal("Unable to create temporary empty file")
    74  	}
    75  	defer os.RemoveAll(tempFile.Name())
    76  	tempFile.Close()
    77  
    78  	for _, badFile := range []string{"not-a-file", tempFile.Name()} {
    79  		for i := 0; i < 3; i++ {
    80  			files := []string{cert, key, ca}
    81  			files[i] = badFile
    82  
    83  			result, err := Server(Options{
    84  				CertFile:   files[0],
    85  				KeyFile:    files[1],
    86  				CAFile:     files[2],
    87  				ClientAuth: tls.VerifyClientCertIfGiven,
    88  			})
    89  			if err == nil || result != nil {
    90  				t.Fatal("Expected a non-real file to error and return a nil TLS config")
    91  			}
    92  		}
    93  	}
    94  }
    95  
    96  // If server cert and key are provided and client auth and client CA are not
    97  // set, a tls config with only the server certs will be returned.
    98  func TestConfigServerTLSServerCertsOnly(t *testing.T) {
    99  	key, cert := getCertAndKey()
   100  
   101  	keypair, err := tls.LoadX509KeyPair(cert, key)
   102  	if err != nil {
   103  		t.Fatal("Unable to load the generated cert and key")
   104  	}
   105  
   106  	tlsConfig, err := Server(Options{
   107  		CertFile: cert,
   108  		KeyFile:  key,
   109  	})
   110  	if err != nil || tlsConfig == nil {
   111  		t.Fatal("Unable to configure server TLS", err)
   112  	}
   113  
   114  	if len(tlsConfig.Certificates) != 1 {
   115  		t.Fatal("Unexpected server certificates")
   116  	}
   117  	if len(tlsConfig.Certificates[0].Certificate) != len(keypair.Certificate) {
   118  		t.Fatal("Unexpected server certificates")
   119  	}
   120  	for i, cert := range tlsConfig.Certificates[0].Certificate {
   121  		if !bytes.Equal(cert, keypair.Certificate[i]) {
   122  			t.Fatal("Unexpected server certificates")
   123  		}
   124  	}
   125  
   126  	if !reflect.DeepEqual(tlsConfig.CipherSuites, DefaultServerAcceptedCiphers) {
   127  		t.Fatal("Unexpected server cipher suites")
   128  	}
   129  	if !tlsConfig.PreferServerCipherSuites { //nolint:staticcheck // Ignore SA1019: tlsConfig.PreferServerCipherSuites has been deprecated since Go 1.18: PreferServerCipherSuites is ignored.
   130  		t.Fatal("Expected server to prefer cipher suites")
   131  	}
   132  	if tlsConfig.MinVersion != tls.VersionTLS12 {
   133  		t.Fatal("Unexpected server TLS version")
   134  	}
   135  }
   136  
   137  // If client CA is provided, it will only be used if the client auth is >=
   138  // VerifyClientCertIfGiven
   139  func TestConfigServerTLSClientCANotSetIfClientAuthTooLow(t *testing.T) {
   140  	key, cert := getCertAndKey()
   141  	ca := getMultiCert()
   142  
   143  	tlsConfig, err := Server(Options{
   144  		CertFile:   cert,
   145  		KeyFile:    key,
   146  		ClientAuth: tls.RequestClientCert,
   147  		CAFile:     ca,
   148  	})
   149  
   150  	if err != nil || tlsConfig == nil {
   151  		t.Fatal("Unable to configure server TLS", err)
   152  	}
   153  
   154  	if len(tlsConfig.Certificates) != 1 {
   155  		t.Fatal("Unexpected server certificates")
   156  	}
   157  	if tlsConfig.ClientAuth != tls.RequestClientCert {
   158  		t.Fatal("ClientAuth was not set to what was in the options")
   159  	}
   160  	if tlsConfig.ClientCAs != nil { //nolint:staticcheck // Ignore SA1019: tlsConfig.ClientCAs.Subjects has been deprecated since Go 1.18: if s was returned by SystemCertPool, Subjects will not include the system roots.
   161  		t.Fatalf("Client CAs should never have been set")
   162  	}
   163  }
   164  
   165  // If client CA is provided, it will only be used if the client auth is >=
   166  // VerifyClientCertIfGiven
   167  func TestConfigServerTLSClientCASet(t *testing.T) {
   168  	key, cert := getCertAndKey()
   169  	ca := getMultiCert()
   170  
   171  	tlsConfig, err := Server(Options{
   172  		CertFile:   cert,
   173  		KeyFile:    key,
   174  		ClientAuth: tls.VerifyClientCertIfGiven,
   175  		CAFile:     ca,
   176  	})
   177  
   178  	if err != nil || tlsConfig == nil {
   179  		t.Fatal("Unable to configure server TLS", err)
   180  	}
   181  
   182  	if len(tlsConfig.Certificates) != 1 {
   183  		t.Fatal("Unexpected server certificates")
   184  	}
   185  	if tlsConfig.ClientAuth != tls.VerifyClientCertIfGiven {
   186  		t.Fatal("ClientAuth was not set to what was in the options")
   187  	}
   188  	basePool, err := SystemCertPool()
   189  	if err != nil {
   190  		basePool = x509.NewCertPool()
   191  	}
   192  	// because we are not enabling `ExclusiveRootPools`, any root pool will also contain the system roots
   193  	if tlsConfig.ClientCAs == nil || len(tlsConfig.ClientCAs.Subjects()) != len(basePool.Subjects())+2 { //nolint:staticcheck // Ignore SA1019: tlsConfig.ClientCAs.Subjects has been deprecated since Go 1.18: if s was returned by SystemCertPool, Subjects will not include the system roots.
   194  		t.Fatalf("Client CAs were never set correctly")
   195  	}
   196  }
   197  
   198  // Exclusive root pools determines whether the CA pool will be a union of the system
   199  // certificate pool and custom certs, or an exclusive or of the custom certs and system pool
   200  func TestConfigServerExclusiveRootPools(t *testing.T) {
   201  	if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
   202  		// FIXME: see https://github.com/docker/go-connections/issues/105.
   203  		t.Skip("FIXME: failing on Windows and darwin")
   204  	}
   205  	key, cert := getCertAndKey()
   206  	ca := getMultiCert()
   207  
   208  	caBytes, err := os.ReadFile(ca)
   209  	if err != nil {
   210  		t.Fatal("Unable to read CA certs", err)
   211  	}
   212  
   213  	var testCerts []*x509.Certificate
   214  	for _, pemBytes := range [][]byte{caBytes, []byte(systemRootTrustedCert)} {
   215  		pemBlock, _ := pem.Decode(pemBytes)
   216  		if pemBlock == nil {
   217  			t.Fatal("Malformed certificate")
   218  		}
   219  		cert, err := x509.ParseCertificate(pemBlock.Bytes)
   220  		if err != nil {
   221  			t.Fatal("Unable to parse certificate")
   222  		}
   223  		testCerts = append(testCerts, cert)
   224  	}
   225  
   226  	// ExclusiveRootPools not set, so should be able to verify both system-signed certs
   227  	// and custom CA-signed certs
   228  	tlsConfig, err := Server(Options{
   229  		CertFile:   cert,
   230  		KeyFile:    key,
   231  		ClientAuth: tls.VerifyClientCertIfGiven,
   232  		CAFile:     ca,
   233  	})
   234  
   235  	if err != nil || tlsConfig == nil {
   236  		t.Fatal("Unable to configure server TLS", err)
   237  	}
   238  
   239  	for i, cert := range testCerts {
   240  		if _, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.ClientCAs}); err != nil {
   241  			t.Fatalf("Unable to verify certificate %d: %v", i, err)
   242  		}
   243  	}
   244  
   245  	// ExclusiveRootPools set and custom CA provided, so system certs should not be verifiable
   246  	// and custom CA-signed certs should be verifiable
   247  	tlsConfig, err = Server(Options{
   248  		CertFile:           cert,
   249  		KeyFile:            key,
   250  		ClientAuth:         tls.VerifyClientCertIfGiven,
   251  		CAFile:             ca,
   252  		ExclusiveRootPools: true,
   253  	})
   254  
   255  	if err != nil || tlsConfig == nil {
   256  		t.Fatal("Unable to configure server TLS", err)
   257  	}
   258  
   259  	for i, cert := range testCerts {
   260  		_, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.ClientCAs})
   261  		switch {
   262  		case i == 0 && err != nil:
   263  			t.Fatal("Unable to verify custom certificate, even though the root pool should have only the custom CA", err)
   264  		case i == 1 && err == nil:
   265  			t.Fatal("Successfully verified system root-signed certificate though the root pool should have only the cusotm CA", err)
   266  		}
   267  	}
   268  
   269  	// No CA file provided, system cert should be verifiable only
   270  	tlsConfig, err = Server(Options{
   271  		CertFile: cert,
   272  		KeyFile:  key,
   273  	})
   274  
   275  	if err != nil || tlsConfig == nil {
   276  		t.Fatal("Unable to configure server TLS", err)
   277  	}
   278  
   279  	for i, cert := range testCerts {
   280  		_, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.ClientCAs})
   281  		switch {
   282  		case i == 1 && err != nil:
   283  			t.Fatal("Unable to verify system root-signed certificate, even though the root pool should be the system pool only", err)
   284  		case i == 0 && err == nil:
   285  			t.Fatal("Successfully verified custom certificate though the root pool should be the system pool only", err)
   286  		}
   287  	}
   288  }
   289  
   290  // If we provide a modifier to the server's default TLS configuration generator, it
   291  // should be applied accordingly
   292  func TestConfigServerDefaultWithTLSMinimumModifier(t *testing.T) {
   293  	tlsVersions := []uint16{
   294  		tls.VersionTLS11,
   295  		tls.VersionTLS12,
   296  	}
   297  
   298  	for _, tlsVersion := range tlsVersions {
   299  		servDefault := ServerDefault(func(c *tls.Config) {
   300  			c.MinVersion = tlsVersion
   301  		})
   302  
   303  		if servDefault.MinVersion != tlsVersion {
   304  			t.Fatalf("Unexpected min TLS version for default server TLS config: %d", servDefault.MinVersion)
   305  		}
   306  	}
   307  }
   308  
   309  // If we provide a modifier to the client's default TLS configuration generator, it
   310  // should be applied accordingly
   311  func TestConfigClientDefaultWithTLSMinimumModifier(t *testing.T) {
   312  	tlsVersions := []uint16{
   313  		tls.VersionTLS11,
   314  		tls.VersionTLS12,
   315  	}
   316  
   317  	for _, tlsVersion := range tlsVersions {
   318  		clientDefault := ClientDefault(func(c *tls.Config) {
   319  			c.MinVersion = tlsVersion
   320  		})
   321  
   322  		if clientDefault.MinVersion != tlsVersion {
   323  			t.Fatalf("Unexpected min TLS version for default client TLS config: %d", clientDefault.MinVersion)
   324  		}
   325  	}
   326  }
   327  
   328  // If a valid minimum version is specified in the options, the server's
   329  // minimum version should be set accordingly
   330  func TestConfigServerTLSMinVersionIsSetBasedOnOptions(t *testing.T) {
   331  	versions := []uint16{
   332  		tls.VersionTLS12,
   333  	}
   334  	key, cert := getCertAndKey()
   335  
   336  	for _, v := range versions {
   337  		tlsConfig, err := Server(Options{
   338  			MinVersion: v,
   339  			CertFile:   cert,
   340  			KeyFile:    key,
   341  		})
   342  
   343  		if err != nil || tlsConfig == nil {
   344  			t.Fatal("Unable to configure server TLS", err)
   345  		}
   346  
   347  		if tlsConfig.MinVersion != v {
   348  			t.Fatal("Unexpected minimum TLS version: ", tlsConfig.MinVersion)
   349  		}
   350  	}
   351  }
   352  
   353  // An error should be returned if the specified minimum version for the server
   354  // is too low, i.e. less than VersionTLS10
   355  func TestConfigServerTLSMinVersionNotSetIfMinVersionIsTooLow(t *testing.T) {
   356  	key, cert := getCertAndKey()
   357  
   358  	_, err := Server(Options{
   359  		MinVersion: tls.VersionTLS10,
   360  		CertFile:   cert,
   361  		KeyFile:    key,
   362  	})
   363  
   364  	if err == nil {
   365  		t.Fatal("Should have returned an error for minimum version below TLS10")
   366  	}
   367  }
   368  
   369  // An error should be returned if an invalid minimum version for the server is
   370  // in the options struct
   371  func TestConfigServerTLSMinVersionNotSetIfMinVersionIsInvalid(t *testing.T) {
   372  	key, cert := getCertAndKey()
   373  
   374  	_, err := Server(Options{
   375  		MinVersion: 1,
   376  		CertFile:   cert,
   377  		KeyFile:    key,
   378  	})
   379  
   380  	if err == nil {
   381  		t.Fatal("Should have returned error on invalid minimum version option")
   382  	}
   383  }
   384  
   385  // The root CA is never set if InsecureSkipBoolean is set to true, but the
   386  // default client options are set
   387  func TestConfigClientTLSNoVerify(t *testing.T) {
   388  	ca := getMultiCert()
   389  
   390  	tlsConfig, err := Client(Options{CAFile: ca, InsecureSkipVerify: true})
   391  
   392  	if err != nil || tlsConfig == nil {
   393  		t.Fatal("Unable to configure client TLS", err)
   394  	}
   395  
   396  	if tlsConfig.RootCAs != nil { //nolint:staticcheck // Ignore SA1019: tlsConfig.RootCAs.Subjects has been deprecated since Go 1.18: if s was returned by SystemCertPool, Subjects will not include the system roots.
   397  		t.Fatal("Should not have set Root CAs", err)
   398  	}
   399  
   400  	if !reflect.DeepEqual(tlsConfig.CipherSuites, clientCipherSuites) {
   401  		t.Fatal("Unexpected client cipher suites")
   402  	}
   403  	if tlsConfig.MinVersion != tls.VersionTLS12 {
   404  		t.Fatal("Unexpected client TLS version")
   405  	}
   406  
   407  	if tlsConfig.Certificates != nil {
   408  		t.Fatal("Somehow client certificates were set")
   409  	}
   410  }
   411  
   412  // The root CA is never set if InsecureSkipBoolean is set to false and root CA
   413  // is not provided.
   414  func TestConfigClientTLSNoRoot(t *testing.T) {
   415  	tlsConfig, err := Client(Options{})
   416  
   417  	if err != nil || tlsConfig == nil {
   418  		t.Fatal("Unable to configure client TLS", err)
   419  	}
   420  
   421  	if tlsConfig.RootCAs != nil {
   422  		t.Fatal("Should not have set Root CAs", err)
   423  	}
   424  
   425  	if !reflect.DeepEqual(tlsConfig.CipherSuites, clientCipherSuites) {
   426  		t.Fatal("Unexpected client cipher suites")
   427  	}
   428  	if tlsConfig.MinVersion != tls.VersionTLS12 {
   429  		t.Fatal("Unexpected client TLS version")
   430  	}
   431  
   432  	if tlsConfig.Certificates != nil {
   433  		t.Fatal("Somehow client certificates were set")
   434  	}
   435  }
   436  
   437  // The RootCA is set if the file is provided and InsecureSkipVerify is false
   438  func TestConfigClientTLSRootCAFileWithOneCert(t *testing.T) {
   439  	ca := getMultiCert()
   440  
   441  	tlsConfig, err := Client(Options{CAFile: ca})
   442  
   443  	if err != nil || tlsConfig == nil {
   444  		t.Fatal("Unable to configure client TLS", err)
   445  	}
   446  	basePool, err := SystemCertPool()
   447  	if err != nil {
   448  		basePool = x509.NewCertPool()
   449  	}
   450  	// because we are not enabling `ExclusiveRootPools`, any root pool will also contain the system roots
   451  	if tlsConfig.RootCAs == nil || len(tlsConfig.RootCAs.Subjects()) != len(basePool.Subjects())+2 { //nolint:staticcheck // Ignore SA1019: tlsConfig.ClientCAs.Subjects has been deprecated since Go 1.18: if s was returned by SystemCertPool, Subjects will not include the system roots.
   452  		t.Fatal("Root CAs not set properly", err)
   453  	}
   454  	if tlsConfig.Certificates != nil {
   455  		t.Fatal("Somehow client certificates were set")
   456  	}
   457  }
   458  
   459  // An error is returned if a root CA is provided but the file doesn't exist.
   460  func TestConfigClientTLSNonexistentRootCAFile(t *testing.T) {
   461  	tlsConfig, err := Client(Options{CAFile: "nonexistent"})
   462  
   463  	if err == nil || tlsConfig != nil {
   464  		t.Fatal("Should not have been able to configure client TLS", err)
   465  	}
   466  }
   467  
   468  // An error is returned if either the client cert or the key are provided
   469  // but invalid or blank.
   470  func TestConfigClientTLSClientCertOrKeyInvalid(t *testing.T) {
   471  	key, cert := getCertAndKey()
   472  
   473  	tempFile, err := os.CreateTemp("", "cert-test")
   474  	if err != nil {
   475  		t.Fatal("Unable to create temporary empty file")
   476  	}
   477  	defer os.Remove(tempFile.Name())
   478  	_ = tempFile.Close()
   479  
   480  	for i := 0; i < 2; i++ {
   481  		for _, invalid := range []string{"not-a-file", "", tempFile.Name()} {
   482  			files := []string{cert, key}
   483  			files[i] = invalid
   484  
   485  			tlsConfig, err := Client(Options{CertFile: files[0], KeyFile: files[1]})
   486  			if err == nil || tlsConfig != nil {
   487  				t.Fatal("Should not have been able to configure client TLS", err)
   488  			}
   489  		}
   490  	}
   491  }
   492  
   493  // The certificate is set if the client cert and client key are provided and
   494  // valid.
   495  func TestConfigClientTLSValidClientCertAndKey(t *testing.T) {
   496  	key, cert := getCertAndKey()
   497  
   498  	keypair, err := tls.LoadX509KeyPair(cert, key)
   499  	if err != nil {
   500  		t.Fatal("Unable to load the generated cert and key")
   501  	}
   502  
   503  	tlsConfig, err := Client(Options{CertFile: cert, KeyFile: key})
   504  
   505  	if err != nil || tlsConfig == nil {
   506  		t.Fatal("Unable to configure client TLS", err)
   507  	}
   508  
   509  	if len(tlsConfig.Certificates) != 1 {
   510  		t.Fatal("Unexpected client certificates")
   511  	}
   512  	if len(tlsConfig.Certificates[0].Certificate) != len(keypair.Certificate) {
   513  		t.Fatal("Unexpected client certificates")
   514  	}
   515  	for i, cert := range tlsConfig.Certificates[0].Certificate {
   516  		if !bytes.Equal(cert, keypair.Certificate[i]) {
   517  			t.Fatal("Unexpected client certificates")
   518  		}
   519  	}
   520  
   521  	if tlsConfig.RootCAs != nil {
   522  		t.Fatal("Root CAs should not have been set", err)
   523  	}
   524  }
   525  
   526  // The certificate is set if the client cert and encrypted client key are
   527  // provided and valid and passphrase can decrypt the key
   528  func TestConfigClientTLSValidClientCertAndEncryptedKey(t *testing.T) {
   529  	key, cert := getCertAndEncryptedKey()
   530  
   531  	tlsConfig, err := Client(Options{
   532  		CertFile:   cert,
   533  		KeyFile:    key,
   534  		Passphrase: "FooBar123",
   535  	})
   536  
   537  	if err != nil || tlsConfig == nil {
   538  		t.Fatal("Unable to configure client TLS", err)
   539  	}
   540  
   541  	if len(tlsConfig.Certificates) != 1 {
   542  		t.Fatal("Unexpected client certificates")
   543  	}
   544  }
   545  
   546  // The certificate is not set if the provided passphrase cannot decrypt
   547  // the encrypted key.
   548  func TestConfigClientTLSNotSetWithInvalidPassphrase(t *testing.T) {
   549  	key, cert := getCertAndEncryptedKey()
   550  
   551  	tlsConfig, err := Client(Options{
   552  		CertFile:   cert,
   553  		KeyFile:    key,
   554  		Passphrase: "InvalidPassphrase",
   555  	})
   556  
   557  	if !IsErrEncryptedKey(err) || tlsConfig != nil {
   558  		t.Fatal("Expected failure due to incorrect passphrase.")
   559  	}
   560  }
   561  
   562  // Exclusive root pools determines whether the CA pool will be a union of the system
   563  // certificate pool and custom certs, or an exclusive or of the custom certs and system pool
   564  func TestConfigClientExclusiveRootPools(t *testing.T) {
   565  	if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
   566  		// FIXME: see https://github.com/docker/go-connections/issues/105.
   567  		t.Skip("FIXME: failing on Windows and darwin")
   568  	}
   569  	ca := getMultiCert()
   570  
   571  	caBytes, err := os.ReadFile(ca)
   572  	if err != nil {
   573  		t.Fatal("Unable to read CA certs", err)
   574  	}
   575  
   576  	var testCerts []*x509.Certificate
   577  	for _, pemBytes := range [][]byte{caBytes, []byte(systemRootTrustedCert)} {
   578  		pemBlock, _ := pem.Decode(pemBytes)
   579  		if pemBlock == nil {
   580  			t.Fatal("Malformed certificate")
   581  		}
   582  		cert, err := x509.ParseCertificate(pemBlock.Bytes)
   583  		if err != nil {
   584  			t.Fatal("Unable to parse certificate")
   585  		}
   586  		testCerts = append(testCerts, cert)
   587  	}
   588  
   589  	// ExclusiveRootPools not set, so should be able to verify both system-signed certs
   590  	// and custom CA-signed certs
   591  	tlsConfig, err := Client(Options{CAFile: ca})
   592  
   593  	if err != nil || tlsConfig == nil {
   594  		t.Fatal("Unable to configure client TLS", err)
   595  	}
   596  
   597  	for i, cert := range testCerts {
   598  		if _, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.RootCAs}); err != nil {
   599  			t.Fatalf("Unable to verify certificate %d: %v", i, err)
   600  		}
   601  	}
   602  
   603  	// ExclusiveRootPools set and custom CA provided, so system certs should not be verifiable
   604  	// and custom CA-signed certs should be verifiable
   605  	tlsConfig, err = Client(Options{
   606  		CAFile:             ca,
   607  		ExclusiveRootPools: true,
   608  	})
   609  
   610  	if err != nil || tlsConfig == nil {
   611  		t.Fatal("Unable to configure client TLS", err)
   612  	}
   613  
   614  	for i, cert := range testCerts {
   615  		_, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.RootCAs})
   616  		switch {
   617  		case i == 0 && err != nil:
   618  			t.Fatal("Unable to verify custom certificate, even though the root pool should have only the custom CA", err)
   619  		case i == 1 && err == nil:
   620  			t.Fatal("Successfully verified system root-signed certificate though the root pool should have only the cusotm CA", err)
   621  		}
   622  	}
   623  
   624  	// No CA file provided, system cert should be verifiable only
   625  	tlsConfig, err = Client(Options{})
   626  
   627  	if err != nil || tlsConfig == nil {
   628  		t.Fatal("Unable to configure client TLS", err)
   629  	}
   630  
   631  	for i, cert := range testCerts {
   632  		_, err := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.RootCAs})
   633  		switch {
   634  		case i == 1 && err != nil:
   635  			t.Fatal("Unable to verify system root-signed certificate, even though the root pool should be the system pool only", err)
   636  		case i == 0 && err == nil:
   637  			t.Fatal("Successfully verified custom certificate though the root pool should be the system pool only", err)
   638  		}
   639  	}
   640  }
   641  
   642  // If a valid MinVersion is specified in the options, the client's
   643  // minimum version should be set accordingly
   644  func TestConfigClientTLSMinVersionIsSetBasedOnOptions(t *testing.T) {
   645  	key, cert := getCertAndKey()
   646  
   647  	tlsConfig, err := Client(Options{
   648  		MinVersion: tls.VersionTLS12,
   649  		CertFile:   cert,
   650  		KeyFile:    key,
   651  	})
   652  
   653  	if err != nil || tlsConfig == nil {
   654  		t.Fatal("Unable to configure client TLS", err)
   655  	}
   656  
   657  	if tlsConfig.MinVersion != tls.VersionTLS12 {
   658  		t.Fatal("Unexpected minimum TLS version: ", tlsConfig.MinVersion)
   659  	}
   660  }
   661  
   662  // An error should be returned if the specified minimum version for the client
   663  // is too low, i.e. less than VersionTLS12
   664  func TestConfigClientTLSMinVersionNotSetIfMinVersionIsTooLow(t *testing.T) {
   665  	key, cert := getCertAndKey()
   666  
   667  	_, err := Client(Options{
   668  		MinVersion: tls.VersionTLS11,
   669  		CertFile:   cert,
   670  		KeyFile:    key,
   671  	})
   672  
   673  	if err == nil {
   674  		t.Fatal("Should have returned an error for minimum version below TLS12")
   675  	}
   676  }
   677  
   678  // An error should be returned if an invalid minimum version for the client is
   679  // in the options struct
   680  func TestConfigClientTLSMinVersionNotSetIfMinVersionIsInvalid(t *testing.T) {
   681  	key, cert := getCertAndKey()
   682  
   683  	_, err := Client(Options{
   684  		MinVersion: 1,
   685  		CertFile:   cert,
   686  		KeyFile:    key,
   687  	})
   688  
   689  	if err == nil {
   690  		t.Fatal("Should have returned error on invalid minimum version option")
   691  	}
   692  }
   693  

View as plain text