mirror of https://github.com/helm/helm.git
fix(main): fix basic auth for helm pull or push
Signed-off-by: cuisongliu <cuisongliu@qq.com>
This commit is contained in:
parent
32c7e37e32
commit
4a27baaffc
|
@ -59,7 +59,7 @@ type (
|
|||
out io.Writer
|
||||
authorizer auth.Client
|
||||
registryAuthorizer *registryauth.Client
|
||||
resolver remotes.Resolver
|
||||
resolver func(ref registry.Reference) (remotes.Resolver, error)
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
|
@ -86,9 +86,23 @@ func NewClient(options ...ClientOption) (*Client, error) {
|
|||
}
|
||||
client.authorizer = authClient
|
||||
}
|
||||
if client.resolver == nil {
|
||||
client.resolver = func(ref registry.Reference) (remotes.Resolver, error) {
|
||||
headers := http.Header{}
|
||||
headers.Set("User-Agent", version.GetUserAgent())
|
||||
dockerClient, ok := client.authorizer.(*dockerauth.Client)
|
||||
if ok {
|
||||
username, password, err := dockerClient.Credential(ref.Registry)
|
||||
if err != nil {
|
||||
return nil, errors.New("unable to retrieve credentials")
|
||||
}
|
||||
// A blank returned username and password value is a bearer token
|
||||
if username == "" && password != "" {
|
||||
headers.Set("Authorization", fmt.Sprintf("Bearer %s", password))
|
||||
} else {
|
||||
headers.Set("Authorization", fmt.Sprintf("Basic %s", basicAuth(username, password)))
|
||||
}
|
||||
}
|
||||
|
||||
opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)}
|
||||
if client.httpClient != nil {
|
||||
opts = append(opts, auth.WithResolverClient(client.httpClient))
|
||||
|
@ -97,9 +111,8 @@ func NewClient(options ...ClientOption) (*Client, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.resolver = resolver
|
||||
return resolver, nil
|
||||
}
|
||||
|
||||
// allocate a cache if option is set
|
||||
var cache registryauth.Cache
|
||||
if client.enableCache {
|
||||
|
@ -117,7 +130,6 @@ func NewClient(options ...ClientOption) (*Client, error) {
|
|||
if !ok {
|
||||
return registryauth.EmptyCredential, errors.New("unable to obtain docker client")
|
||||
}
|
||||
|
||||
username, password, err := dockerClient.Credential(reg)
|
||||
if err != nil {
|
||||
return registryauth.EmptyCredential, errors.New("unable to retrieve credentials")
|
||||
|
@ -324,7 +336,11 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
|
|||
}
|
||||
|
||||
var descriptors, layers []ocispec.Descriptor
|
||||
registryStore := content.Registry{Resolver: c.resolver}
|
||||
remotesResolver, err := c.resolver(parsedRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registryStore := content.Registry{Resolver: remotesResolver}
|
||||
|
||||
manifest, err := oras.Copy(ctx(c.out, c.debug), registryStore, parsedRef.String(), memoryStore, "",
|
||||
oras.WithPullEmptyNameAllowed(),
|
||||
|
@ -562,8 +578,11 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
|
|||
if err := memoryStore.StoreManifest(parsedRef.String(), manifest, manifestData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
registryStore := content.Registry{Resolver: c.resolver}
|
||||
remotesResolver, err := c.resolver(parsedRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registryStore := content.Registry{Resolver: remotesResolver}
|
||||
_, err = oras.Copy(ctx(c.out, c.debug), memoryStore, parsedRef.String(), registryStore, "",
|
||||
oras.WithNameValidation(nil))
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,7 @@ package registry // import "helm.sh/helm/v3/pkg/registry"
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -245,3 +246,13 @@ func addToMap(inputMap map[string]string, newKey string, newValue string) map[st
|
|||
return inputMap
|
||||
|
||||
}
|
||||
|
||||
// See 2 (end of page 4) https://www.ietf.org/rfc/rfc2617.txt
|
||||
// "To receive authorization, the client sends the userid and password,
|
||||
// separated by a single colon (":") character, within a base64
|
||||
// encoded string in the credentials."
|
||||
// It is not meant to be urlencoded.
|
||||
func basicAuth(username, password string) string {
|
||||
auth := username + ":" + password
|
||||
return base64.StdEncoding.EncodeToString([]byte(auth))
|
||||
}
|
||||
|
|
|
@ -238,3 +238,31 @@ func TestGenerateOCICreatedAnnotations(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_basicAuth(t *testing.T) {
|
||||
type args struct {
|
||||
username string
|
||||
password string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Basic Auth",
|
||||
args: args{
|
||||
username: "admin",
|
||||
password: "passw0rd",
|
||||
},
|
||||
want: "YWRtaW46cGFzc3cwcmQ=",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := basicAuth(tt.args.username, tt.args.password); got != tt.want {
|
||||
t.Errorf("basicAuth() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue