Add HTTP Support for OCI artifacts

Signed-off-by: Tom Runyon <runyontr@gmail.com>
Signed-off-by: Tom Runyon <tom@defenseunicorns.com>
pull/11623/head
Tom Runyon 3 years ago
parent 330105ca6f
commit 3265d17a81
No known key found for this signature in database
GPG Key ID: D1CF51977E0E790F

@ -70,7 +70,7 @@ type (
caFile string
insecureSkipVerifyTLS bool
plainHTTP bool
httpClient *http.Client
httpClient *http.Client
}
// ClientOption allows specifying various settings configurable by the user for overriding the defaults
@ -132,7 +132,10 @@ func NewClient(options ...ClientOption) (*Client, error) {
TLSClientConfig: config,
},
}))
}
if client.plainHTTP {
opts = append(opts, auth.WithResolverPlainHTTP())
}
if client.httpClient != nil {
opts = append(opts, auth.WithResolverClient(client.httpClient))
}
@ -240,6 +243,9 @@ func ClientOptInsecureSkipVerifyTLS(insecureSkipVerifyTLS bool) ClientOption {
func ClientOptPlainHTTP(plainHTTP bool) ClientOption {
return func(client *Client) {
client.plainHTTP = plainHTTP
}
}
// ClientOptHTTPClient returns a function that sets the httpClient setting on a client options set
func ClientOptHTTPClient(httpClient *http.Client) ClientOption {
return func(client *Client) {
@ -252,12 +258,13 @@ type (
LoginOption func(*loginOperation)
loginOperation struct {
username string
password string
insecure bool
certFile string
keyFile string
caFile string
username string
password string
insecure bool
certFile string
keyFile string
caFile string
plainHTTP bool
}
)
@ -293,6 +300,13 @@ func LoginOptBasicAuth(username string, password string) LoginOption {
}
}
// LoginOptBasicAuth returns a function that sets the username/password settings on login
func LoginOptPlainHTTP() LoginOption {
return func(operation *loginOperation) {
operation.plainHTTP = true
}
}
// LoginOptInsecure returns a function that sets the insecure setting on login
func LoginOptInsecure(insecure bool) LoginOption {
return func(operation *loginOperation) {

@ -0,0 +1,76 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package registry
import (
"os"
"testing"
"github.com/stretchr/testify/suite"
)
type HTTPRegistryClientTestSuite struct {
TestSuite
}
func (suite *HTTPRegistryClientTestSuite) SetupSuite() {
// init test client
dockerRegistry := setup(&suite.TestSuite, false, false)
// Start Docker registry
go dockerRegistry.ListenAndServe()
}
func (suite *HTTPRegistryClientTestSuite) TearDownSuite() {
os.RemoveAll(suite.WorkspaceDir)
}
func (suite *HTTPRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(false))
suite.Nil(err, "Expected no error logging into registry with good credentials: %v", err)
err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, "badpassword"),
LoginOptInsecure(true))
suite.NotNil(err, "error logging into registry with good credentials, insecure mode")
}
func (suite *HTTPRegistryClientTestSuite) Test_1_Push() {
testPush(&suite.TestSuite)
}
func (suite *HTTPRegistryClientTestSuite) Test_2_Pull() {
testPull(&suite.TestSuite)
}
func (suite *HTTPRegistryClientTestSuite) Test_3_Tags() {
testTags(&suite.TestSuite)
}
func (suite *HTTPRegistryClientTestSuite) Test_4_Logout() {
err := suite.RegistryClient.Logout("this-host-aint-real:5000")
suite.NotNil(err, "error logging out of registry that has no entry")
err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry")
}
func TestHTTPRegistryClientTestSuite(t *testing.T) {
suite.Run(t, new(HTTPRegistryClientTestSuite))
}

@ -17,12 +17,16 @@ limitations under the License.
package registry
import (
<<<<<<< HEAD
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"net"
=======
"fmt"
>>>>>>> dd5e82b5 (refactor to new test suite)
"os"
"path/filepath"
"testing"
@ -200,39 +204,8 @@ func (suite *RegistryClientTestSuite) SetupSuite() {
suite.Nil(err, "no error finding free port for test TLS registry")
suite.TLSDockerRegistryHost = fmt.Sprintf("%s:%d", hostname, tlsRegistryPort)
tlsRegistryConfig := &configuration.Configuration{}
tlsRegistryConfig.HTTP.Addr = fmt.Sprintf(":%d", tlsRegistryPort)
tlsRegistryConfig.HTTP.TLS.Certificate = caCertPath
tlsRegistryConfig.HTTP.TLS.Key = caKeyPath
tlsRegistryConfig.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}}
tlsRegistryConfig.Auth = configuration.Auth{
"htpasswd": configuration.Parameters{
"realm": hostname,
"path": htpasswdPath,
},
}
tlsDockerRegistry, err := registry.NewRegistry(context.Background(), tlsRegistryConfig)
suite.Nil(err, "no error creating test TLS registry")
// init TLS registry with self-signed CA and client verification enabled
anotherTLSRegistryPort, err := freeport.GetFreePort()
suite.Nil(err, "no error finding free port for test another TLS registry")
suite.TLSVerifyClientDockerRegistryHost = fmt.Sprintf("%s:%d", hostname, anotherTLSRegistryPort)
anotherTLSRegistryConfig := &configuration.Configuration{}
anotherTLSRegistryConfig.HTTP.Addr = fmt.Sprintf(":%d", anotherTLSRegistryPort)
anotherTLSRegistryConfig.HTTP.TLS.Certificate = caCertPath
anotherTLSRegistryConfig.HTTP.TLS.Key = caKeyPath
anotherTLSRegistryConfig.HTTP.TLS.ClientCAs = []string{caCertPath}
anotherTLSRegistryConfig.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}}
// no auth because we cannot pass Login action
anotherTLSDockerRegistry, err := registry.NewRegistry(context.Background(), anotherTLSRegistryConfig)
suite.Nil(err, "no error creating test another TLS registry")
// start registries
// Start Docker registry
go dockerRegistry.ListenAndServe()
go plainHTTPDockerRegistry.ListenAndServe()
go tlsDockerRegistry.ListenAndServe()
go anotherTLSDockerRegistry.ListenAndServe()
}
func (suite *RegistryClientTestSuite) TearDownSuite() {
@ -259,36 +232,6 @@ func (suite *RegistryClientTestSuite) Test_0_Login() {
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true))
suite.Nil(err, "no error logging into registry with good credentials, insecure mode")
err = suite.PlainHTTPRegistryClient.Login(suite.PlainHTTPDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(false))
suite.NotNil(err, "no error logging into registry with good credentials")
err = suite.PlainHTTPRegistryClient.Login(suite.PlainHTTPDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true))
suite.Nil(err, "error logging into registry with good credentials, insecure mode")
err = suite.InsecureRegistryClient.Login(suite.TLSDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(false))
suite.NotNil(err, "no error logging into insecure with good credentials")
err = suite.InsecureRegistryClient.Login(suite.TLSDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true))
suite.Nil(err, "error logging into insecure with good credentials, insecure mode")
err = suite.RegistryClientWithCA.Login(suite.TLSDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(false))
suite.NotNil(err, "no error logging into insecure with good credentials")
err = suite.RegistryClientWithCA.Login(suite.TLSDockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true))
suite.Nil(err, "error logging into insecure with good credentials, insecure mode")
}
func (suite *RegistryClientTestSuite) Test_1_Push() {
@ -309,17 +252,6 @@ func (suite *RegistryClientTestSuite) Test_4_Logout() {
err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry")
err = suite.PlainHTTPRegistryClient.Logout(suite.PlainHTTPDockerRegistryHost)
suite.Nil(err, "error logging out of plain http registry")
err = suite.InsecureRegistryClient.Logout(suite.TLSDockerRegistryHost)
suite.Nil(err, "error logging out of insecure registry")
// error as logout happened for TLSDockerRegistryHost in last step
err = suite.RegistryClientWithCA.Logout(suite.TLSDockerRegistryHost)
suite.Nil(err, "no error logging out of registry with ca cert")
}
func (suite *RegistryClientTestSuite) Test_5_ManInTheMiddle() {

@ -155,3 +155,18 @@ func NewRegistryClientWithTLS(out io.Writer, certFile, keyFile, caFile string, i
}
return registryClient, nil
}
func NewRegistryClientHTTP(out io.Writer, certFile, keyFile, caFile string, insecureSkipTLSverify bool, registryConfig string, debug bool) (*Client, error) {
// Create a new http registry client
registryClient, err := NewClient(
ClientOptDebug(debug),
ClientOptEnableCache(true),
ClientOptWriter(out),
ClientOptCredentialsFile(registryConfig),
ClientOptPlainHTTP(true),
)
if err != nil {
return nil, err
}
return registryClient, nil
}

@ -55,17 +55,29 @@ var (
testHtpasswdFileBasename = "authtest.htpasswd"
testUsername = "myuser"
testPassword = "mypass"
testCACertFileName = "root.pem"
testCAKeyFileName = "root-key.pem"
testClientCertFileName = "client.pem"
testClientKeyFileName = "client-key.pem"
)
type TestSuite struct {
suite.Suite
Out io.Writer
DockerRegistryHost string
Out io.Writer
DockerRegistryHost string
CompromisedRegistryHost string
WorkspaceDir string
RegistryClient *Client
}
// setup creates a oci registry for use in testing and sets the internal
// RegistryClient in the provided *TestSutie object with a client for communicating
// to the registry for testing:
//
// tlsEnabled - true for an https registry, false for http
// insecure - true for forcing the client to trust the certs when communicating to the registry
// false otherwise
func setup(suite *TestSuite, tlsEnabled bool, insecure bool) *registry.Registry {
suite.WorkspaceDir = testWorkspaceDir
os.RemoveAll(suite.WorkspaceDir)
@ -101,6 +113,7 @@ func setup(suite *TestSuite, tlsEnabled bool, insecure bool) *registry.Registry
ClientOptEnableCache(true),
ClientOptWriter(suite.Out),
ClientOptCredentialsFile(credentialsFile),
ClientOptPlainHTTP(true),
)
}

Loading…
Cancel
Save