diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 3ea68f181..0c9f256d3 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -268,7 +268,7 @@ func LoginOptPlainText(isPlainText bool) LoginOption { } } -func ensureTLSConfig(client *auth.Client) (*tls.Config, error) { +func ensureTLSConfig(client *auth.Client, setConfig *tls.Config) (*tls.Config, error) { var transport *http.Transport switch t := client.Client.Transport.(type) { @@ -292,7 +292,10 @@ func ensureTLSConfig(client *auth.Client) (*tls.Config, error) { return nil, fmt.Errorf("unable to access TLS client configuration, the provided HTTP Transport is not supported, given: %T", client.Client.Transport) } - if transport.TLSClientConfig == nil { + switch { + case setConfig != nil: + transport.TLSClientConfig = setConfig + case transport.TLSClientConfig == nil: transport.TLSClientConfig = &tls.Config{} } @@ -302,7 +305,7 @@ func ensureTLSConfig(client *auth.Client) (*tls.Config, error) { // LoginOptInsecure returns a function that sets the insecure setting on login func LoginOptInsecure(insecure bool) LoginOption { return func(o *loginOperation) { - tlsConfig, err := ensureTLSConfig(o.client.authorizer) + tlsConfig, err := ensureTLSConfig(o.client.authorizer, nil) if err != nil { panic(err) @@ -318,7 +321,7 @@ func LoginOptTLSClientConfig(certFile, keyFile, caFile string) LoginOption { if (certFile == "" || keyFile == "") && caFile == "" { return } - tlsConfig, err := ensureTLSConfig(o.client.authorizer) + tlsConfig, err := ensureTLSConfig(o.client.authorizer, nil) if err != nil { panic(err) } @@ -345,6 +348,17 @@ func LoginOptTLSClientConfig(certFile, keyFile, caFile string) LoginOption { } } +// LoginOptTLSClientConfigFromConfig returns a function that sets the TLS settings on login +// receiving the configuration in memory rather than from files. +func LoginOptTLSClientConfigFromConfig(conf *tls.Config) LoginOption { + return func(o *loginOperation) { + _, err := ensureTLSConfig(o.client.authorizer, conf) + if err != nil { + panic(err) + } + } +} + type ( // LogoutOption allows specifying various settings on logout LogoutOption func(*logoutOperation) diff --git a/pkg/registry/client_tls_test.go b/pkg/registry/client_tls_test.go index 156ae4816..0897858b5 100644 --- a/pkg/registry/client_tls_test.go +++ b/pkg/registry/client_tls_test.go @@ -17,6 +17,8 @@ limitations under the License. package registry import ( + "crypto/tls" + "crypto/x509" "os" "testing" @@ -52,6 +54,30 @@ func (suite *TLSRegistryClientTestSuite) Test_0_Login() { suite.Nil(err, "no error logging into registry with good credentials") } +func (suite *TLSRegistryClientTestSuite) Test_1_Login() { + err := suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth("badverybad", "ohsobad"), + LoginOptTLSClientConfigFromConfig(&tls.Config{})) + suite.NotNil(err, "error logging into registry with bad credentials") + + // Create a *tls.Config from tlsCert, tlsKey, and tlsCA. + cert, err := tls.LoadX509KeyPair(tlsCert, tlsKey) + suite.Nil(err, "error loading x509 key pair") + rootCAs := x509.NewCertPool() + caCert, err := os.ReadFile(tlsCA) + suite.Nil(err, "error reading CA certificate") + rootCAs.AppendCertsFromPEM(caCert) + conf := &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: rootCAs, + } + + err = suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth(testUsername, testPassword), + LoginOptTLSClientConfigFromConfig(conf)) + suite.Nil(err, "no error logging into registry with good credentials") +} + func (suite *TLSRegistryClientTestSuite) Test_1_Push() { testPush(&suite.TestSuite) }