diff --git a/Gopkg.lock b/Gopkg.lock index 39cb8eb22..61facc9e4 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -275,7 +275,7 @@ version = "v18.09.5" [[projects]] - digest = "1:888aaacf886021e4a0fa6b09a61f1158063bd6c2e2ddefe14f3a7ccbc93ffe27" + digest = "1:feaf11ab67fe48ec2712bf9d44e2fb2d4ebdc5da8e5a47bd3ce05bae9f82825b" name = "github.com/docker/distribution" packages = [ ".", @@ -296,6 +296,7 @@ "registry/api/errcode", "registry/api/v2", "registry/auth", + "registry/auth/htpasswd", "registry/client", "registry/client/auth", "registry/client/auth/challenge", @@ -983,9 +984,11 @@ [[projects]] branch = "master" - digest = "1:599ef9ff10026292c425292ab1d2bb1521cd671fe89a6034df07bf1411daa44b" + digest = "1:91e034b0c63a4c747c6e9dc8285f36dc5fe699a78d34de0a663895e52ff673dd" name = "golang.org/x/crypto" packages = [ + "bcrypt", + "blowfish", "cast5", "ed25519", "ed25519/internal/edwards25519", @@ -1748,13 +1751,13 @@ "github.com/asaskevich/govalidator", "github.com/containerd/containerd/reference", "github.com/containerd/containerd/remotes", - "github.com/containerd/containerd/remotes/docker", "github.com/deislabs/oras/pkg/auth", "github.com/deislabs/oras/pkg/auth/docker", "github.com/deislabs/oras/pkg/content", "github.com/deislabs/oras/pkg/oras", "github.com/docker/distribution/configuration", "github.com/docker/distribution/registry", + "github.com/docker/distribution/registry/auth/htpasswd", "github.com/docker/distribution/registry/storage/driver/inmemory", "github.com/docker/go-units", "github.com/evanphx/json-patch", @@ -1772,6 +1775,7 @@ "github.com/spf13/pflag", "github.com/stretchr/testify/assert", "github.com/stretchr/testify/suite", + "golang.org/x/crypto/bcrypt", "golang.org/x/crypto/openpgp", "golang.org/x/crypto/openpgp/clearsign", "golang.org/x/crypto/openpgp/errors", diff --git a/pkg/registry/client_test.go b/pkg/registry/client_test.go index aa3770ac1..ac373d4bc 100644 --- a/pkg/registry/client_test.go +++ b/pkg/registry/client_test.go @@ -20,15 +20,19 @@ import ( "bytes" "context" "fmt" + "golang.org/x/crypto/bcrypt" "io" + "io/ioutil" "net" "os" + "path/filepath" "testing" "time" - "github.com/containerd/containerd/remotes/docker" + auth "github.com/deislabs/oras/pkg/auth/docker" "github.com/docker/distribution/configuration" "github.com/docker/distribution/registry" + _ "github.com/docker/distribution/registry/auth/htpasswd" _ "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/stretchr/testify/suite" @@ -36,7 +40,10 @@ import ( ) var ( - testCacheRootDir = "helm-registry-test" + testCacheRootDir = "helm-registry-test" + testHtpasswdFileBasename = "authtest.htpasswd" + testUsername = "myuser" + testPassword = "mypass" ) type RegistryClientTestSuite struct { @@ -49,28 +56,52 @@ type RegistryClientTestSuite struct { func (suite *RegistryClientTestSuite) SetupSuite() { suite.CacheRootDir = testCacheRootDir + os.RemoveAll(suite.CacheRootDir) + os.Mkdir(suite.CacheRootDir, 0700) - // Init test client var out bytes.Buffer suite.Out = &out + credentialsFile := filepath.Join(suite.CacheRootDir, CredentialsFileBasename) + + client, err := auth.NewClient(credentialsFile) + suite.Nil(err, "no error creating auth client") + + resolver, err := client.Resolver(context.Background()) + suite.Nil(err, "no error creating resolver") + + // Init test client suite.RegistryClient = NewClient(&ClientOptions{ Out: suite.Out, + Authorizer: Authorizer{ + Client: client, + }, Resolver: Resolver{ - Resolver: docker.NewResolver(docker.ResolverOptions{}), + Resolver: resolver, }, CacheRootDir: suite.CacheRootDir, }) + // create htpasswd file (w BCrypt, which is required) + pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost) + suite.Nil(err, "no error generating bcrypt password for test httpasswd file") + httpasswdPath := filepath.Join(suite.CacheRootDir, testHtpasswdFileBasename) + err = ioutil.WriteFile(httpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0644) + suite.Nil(err, "no error creating test httpasswd file") + // Registry config config := &configuration.Configuration{} port, err := getFreePort() - if err != nil { - suite.Nil(err, "no error finding free port for test registry") - } + suite.Nil(err, "no error finding free port for test registry") suite.DockerRegistryHost = fmt.Sprintf("localhost:%d", port) config.HTTP.Addr = fmt.Sprintf(":%d", port) config.HTTP.DrainTimeout = time.Duration(10) * time.Second config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + config.Auth = configuration.Auth{ + "httpasswd": configuration.Parameters{ + "realm": "localhost", + "path": httpasswdPath, + }, + } dockerRegistry, err := registry.NewRegistry(context.Background(), config) suite.Nil(err, "no error creating test registry") @@ -82,7 +113,15 @@ func (suite *RegistryClientTestSuite) TearDownSuite() { os.RemoveAll(suite.CacheRootDir) } -func (suite *RegistryClientTestSuite) Test_0_SaveChart() { +func (suite *RegistryClientTestSuite) Test_0_Login() { + err := suite.RegistryClient.Login(suite.DockerRegistryHost, "badverybad", "ohsobad") + suite.NotNil(err, "error logging into registry with bad credentials") + + err = suite.RegistryClient.Login(suite.DockerRegistryHost, testUsername, testPassword) + suite.Nil(err, "no error logging into registry with good credentials") +} + +func (suite *RegistryClientTestSuite) Test_1_SaveChart() { ref, err := ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) suite.Nil(err) @@ -100,7 +139,7 @@ func (suite *RegistryClientTestSuite) Test_0_SaveChart() { suite.Nil(err) } -func (suite *RegistryClientTestSuite) Test_1_LoadChart() { +func (suite *RegistryClientTestSuite) Test_2_LoadChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) @@ -117,7 +156,7 @@ func (suite *RegistryClientTestSuite) Test_1_LoadChart() { suite.Equal("1.2.3", ch.Metadata.Version) } -func (suite *RegistryClientTestSuite) Test_2_PushChart() { +func (suite *RegistryClientTestSuite) Test_3_PushChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) @@ -132,7 +171,7 @@ func (suite *RegistryClientTestSuite) Test_2_PushChart() { suite.Nil(err) } -func (suite *RegistryClientTestSuite) Test_3_PullChart() { +func (suite *RegistryClientTestSuite) Test_4_PullChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) @@ -147,12 +186,12 @@ func (suite *RegistryClientTestSuite) Test_3_PullChart() { suite.Nil(err) } -func (suite *RegistryClientTestSuite) Test_4_PrintChartTable() { +func (suite *RegistryClientTestSuite) Test_5_PrintChartTable() { err := suite.RegistryClient.PrintChartTable() suite.Nil(err) } -func (suite *RegistryClientTestSuite) Test_5_RemoveChart() { +func (suite *RegistryClientTestSuite) Test_6_RemoveChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) @@ -167,6 +206,14 @@ func (suite *RegistryClientTestSuite) Test_5_RemoveChart() { suite.Nil(err) } +func (suite *RegistryClientTestSuite) Test_7_Logout() { + err := suite.RegistryClient.Logout("this-host-aint-real-son: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 TestRegistryClientTestSuite(t *testing.T) { suite.Run(t, new(RegistryClientTestSuite)) }