mirror of
https://github.com/helm/helm.git
synced 2026-03-22 02:20:42 -04:00
Merge b9232c7853 into 42f78ba60e
This commit is contained in:
commit
dff37018b3
8 changed files with 158 additions and 9 deletions
1
go.mod
1
go.mod
|
|
@ -80,6 +80,7 @@ require (
|
|||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -103,6 +103,8 @@ github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8b
|
|||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
|
||||
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
|
|
|
|||
|
|
@ -714,6 +714,8 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
|
|||
repository.PlainHTTP = c.plainHTTP
|
||||
repository.Client = c.authorizer
|
||||
|
||||
ctx = withScopeHint(ctx, repository, auth.ActionPull, auth.ActionPush)
|
||||
|
||||
manifestDescriptor, err = oras.ExtendedCopy(ctx, memoryStore, parsedRef.String(), repository, parsedRef.String(), oras.DefaultExtendedCopyOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -926,3 +928,17 @@ func (c *Client) tagManifest(ctx context.Context, memoryStore *memory.Store,
|
|||
return oras.TagBytes(ctx, memoryStore, ocispec.MediaTypeImageManifest,
|
||||
manifestData, parsedRef.String())
|
||||
}
|
||||
|
||||
// add actions when request a registry authentication token(jwt)
|
||||
// example1. when we want to pull 'testrepo/local-subchart' we can send bellow url, and 'pull' is the action
|
||||
// auth?scope=repository%3Atestrepo%2Flocal-subchart%3Apull&service=testservice
|
||||
// example2. when we want to push 'testrepo/local-subchart' we can send bellow url, and 'pull%2Cpush' are the actions
|
||||
// auth?scope=repository%3Atestrepo%2Flocal-subchart%3Apull%2Cpush&service=testservice
|
||||
// we can set the actions like bellow
|
||||
// example) ctx = WithScopeHint(ctx, repository, auth.ActionPush, auth.ActionPull)
|
||||
func withScopeHint(ctx context.Context, target any, actions ...string) context.Context {
|
||||
if repo, ok := target.(*remote.Repository); ok {
|
||||
return auth.AppendRepositoryScope(ctx, repo.Reference, actions...)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ type HTTPRegistryClientTestSuite struct {
|
|||
|
||||
func (suite *HTTPRegistryClientTestSuite) SetupSuite() {
|
||||
// init test client
|
||||
setup(&suite.TestRegistry, false, false)
|
||||
setup(&suite.TestRegistry, false, false, "htpasswd")
|
||||
}
|
||||
|
||||
func (suite *HTTPRegistryClientTestSuite) TearDownSuite() {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ type InsecureTLSRegistryClientTestSuite struct {
|
|||
|
||||
func (suite *InsecureTLSRegistryClientTestSuite) SetupSuite() {
|
||||
// init test client
|
||||
setup(&suite.TestRegistry, true, true)
|
||||
setup(&suite.TestRegistry, true, true, "htpasswd")
|
||||
|
||||
}
|
||||
|
||||
func (suite *InsecureTLSRegistryClientTestSuite) TearDownSuite() {
|
||||
|
|
|
|||
107
pkg/registry/client_scope_test.go
Normal file
107
pkg/registry/client_scope_test.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type RegistryScopeTestSuite struct {
|
||||
TestRegistry
|
||||
}
|
||||
|
||||
func (suite *RegistryScopeTestSuite) SetupSuite() {
|
||||
// set registry use token auth
|
||||
setup(&suite.TestRegistry, true, true, "token")
|
||||
|
||||
}
|
||||
func (suite *RegistryScopeTestSuite) TearDownSuite() {
|
||||
teardown(&suite.TestRegistry)
|
||||
os.RemoveAll(suite.WorkspaceDir)
|
||||
}
|
||||
|
||||
func (suite *RegistryScopeTestSuite) Test_1_Check_Push_Request_Scope() {
|
||||
|
||||
var requestURL string
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
requestURL = r.URL.String()
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
listener, err := net.Listen("tcp", suite.AuthServerHost)
|
||||
suite.NoError(err, "no error creating server listener")
|
||||
|
||||
ts := httptest.NewUnstartedServer(handler)
|
||||
ts.Listener = listener
|
||||
ts.Start()
|
||||
defer ts.Close()
|
||||
|
||||
// basic push, good ref
|
||||
testingChartCreationTime := "1977-09-02T22:04:05Z"
|
||||
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
|
||||
suite.NoError(err, "no error loading test chart")
|
||||
meta, err := extractChartMeta(chartData)
|
||||
suite.NoError(err, "no error extracting chart meta")
|
||||
ref := fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
|
||||
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
|
||||
suite.Error(err, "error pushing good ref because auth server doesn't give proper token")
|
||||
|
||||
//check the url that authentication server received
|
||||
suite.Equal("/auth?scope=repository%3Atestrepo%2Flocal-subchart%3Apull%2Cpush&service=testservice", requestURL)
|
||||
|
||||
}
|
||||
|
||||
func (suite *RegistryScopeTestSuite) Test_2_Check_Pull_Request_Scope() {
|
||||
|
||||
var requestURL string
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
requestURL = r.URL.String()
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
listener, err := net.Listen("tcp", suite.AuthServerHost)
|
||||
suite.NoError(err, "no error creating server listener")
|
||||
|
||||
ts := httptest.NewUnstartedServer(handler)
|
||||
ts.Listener = listener
|
||||
ts.Start()
|
||||
defer ts.Close()
|
||||
|
||||
// Load test chart (to build ref pushed in previous test)
|
||||
// Simple pull, chart only
|
||||
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
|
||||
suite.NoError(err, "no error loading test chart")
|
||||
meta, err := extractChartMeta(chartData)
|
||||
suite.NoError(err, "no error extracting chart meta")
|
||||
ref := fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
|
||||
_, err = suite.RegistryClient.Pull(ref)
|
||||
suite.Error(err, "error pulling a simple chart because auth server doesn't give proper token")
|
||||
|
||||
//check the url that authentication server received
|
||||
suite.Equal("/auth?scope=repository%3Atestrepo%2Flocal-subchart%3Apull&service=testservice", requestURL)
|
||||
}
|
||||
|
||||
func TestRegistryScopeTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(RegistryScopeTestSuite))
|
||||
}
|
||||
|
|
@ -31,7 +31,8 @@ type TLSRegistryClientTestSuite struct {
|
|||
|
||||
func (suite *TLSRegistryClientTestSuite) SetupSuite() {
|
||||
// init test client
|
||||
setup(&suite.TestRegistry, true, false)
|
||||
setup(&suite.TestRegistry, true, false, "htpasswd")
|
||||
|
||||
}
|
||||
|
||||
func (suite *TLSRegistryClientTestSuite) TearDownSuite() {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/registry"
|
||||
_ "github.com/distribution/distribution/v3/registry/auth/htpasswd"
|
||||
_ "github.com/distribution/distribution/v3/registry/auth/token"
|
||||
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -56,6 +57,8 @@ var (
|
|||
testHtpasswdFileBasename = "authtest.htpasswd"
|
||||
testUsername = "myuser"
|
||||
testPassword = "mypass"
|
||||
testIssuer = "testissuer"
|
||||
testService = "testservice"
|
||||
)
|
||||
|
||||
type TestRegistry struct {
|
||||
|
|
@ -63,13 +66,14 @@ type TestRegistry struct {
|
|||
Out io.Writer
|
||||
FakeRegistryHost string
|
||||
DockerRegistryHost string
|
||||
AuthServerHost string
|
||||
CompromisedRegistryHost string
|
||||
WorkspaceDir string
|
||||
RegistryClient *Client
|
||||
dockerRegistry *registry.Registry
|
||||
}
|
||||
|
||||
func setup(suite *TestRegistry, tlsEnabled, insecure bool) {
|
||||
func setup(suite *TestRegistry, tlsEnabled, insecure bool, auth string) {
|
||||
suite.WorkspaceDir = testWorkspaceDir
|
||||
err := os.RemoveAll(suite.WorkspaceDir)
|
||||
require.NoError(suite.T(), err, "no error removing test workspace dir")
|
||||
|
|
@ -139,11 +143,28 @@ func setup(suite *TestRegistry, tlsEnabled, insecure bool) {
|
|||
config.HTTP.DrainTimeout = time.Duration(10) * time.Second
|
||||
config.Storage = map[string]configuration.Parameters{"inmemory": map[string]any{}}
|
||||
|
||||
config.Auth = configuration.Auth{
|
||||
"htpasswd": configuration.Parameters{
|
||||
"realm": "localhost",
|
||||
"path": htpasswdPath,
|
||||
},
|
||||
if auth == "token" {
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
suite.Nil(err, "no error finding free port for test auth server")
|
||||
|
||||
//set test auth server host
|
||||
suite.AuthServerHost = ln.Addr().String()
|
||||
|
||||
config.Auth = configuration.Auth{
|
||||
"token": configuration.Parameters{
|
||||
"realm": "http://" + suite.AuthServerHost + "/auth",
|
||||
"service": testService,
|
||||
"issuer": testIssuer,
|
||||
"rootcertbundle": tlsServerCert,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
config.Auth = configuration.Auth{
|
||||
"htpasswd": configuration.Parameters{
|
||||
"realm": "localhost",
|
||||
"path": htpasswdPath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// config tls
|
||||
|
|
|
|||
Loading…
Reference in a new issue