github.com/oam-dev/kubevela@v1.9.11/pkg/utils/registries/secret_authenticator.go (about) 1 /* 2 Copyright 2023 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package registries 18 19 import ( 20 "context" 21 "encoding/base64" 22 "fmt" 23 "net/http" 24 "net/url" 25 26 "github.com/google/go-containerregistry/pkg/authn" 27 "github.com/google/go-containerregistry/pkg/name" 28 "github.com/google/go-containerregistry/pkg/v1/remote/transport" 29 ) 30 31 // SecretAuthenticator provides helper functions for secret authenticator operations 32 type SecretAuthenticator interface { 33 Options() []Option 34 35 Auth(ctx context.Context) (bool, error) 36 37 Authorization() (*authn.AuthConfig, error) 38 } 39 40 type secretAuthenticator struct { 41 auths DockerConfig 42 insecure bool // force using insecure when talk to the remote registry, even registry address starts with https 43 } 44 45 // NewSecretAuthenticator creates a secret authenticator 46 func NewSecretAuthenticator(imageRegistry *ImageRegistry) (SecretAuthenticator, error) { 47 48 if imageRegistry == nil { 49 return &secretAuthenticator{}, nil 50 } 51 52 sa := &secretAuthenticator{ 53 insecure: false, 54 } 55 56 // force insecure if imageRegistry has Insecure 57 sa.insecure = imageRegistry.Insecure 58 if imageRegistry.Insecure { 59 sa.insecure = true 60 } 61 62 auth := fmt.Sprintf("%s:%s", imageRegistry.Auth.Username, imageRegistry.Auth.Password) 63 64 entry := DockerConfigEntry{ 65 Username: imageRegistry.Auth.Username, 66 Password: imageRegistry.Auth.Password, 67 Email: imageRegistry.Auth.Email, 68 Auth: base64.StdEncoding.EncodeToString([]byte(auth)), 69 } 70 71 sa.auths = map[string]DockerConfigEntry{} 72 if imageRegistry.UseHTTP { 73 sa.auths[fmt.Sprintf("http://%s", imageRegistry.Registry)] = entry 74 } else { 75 sa.auths[fmt.Sprintf("https://%s", imageRegistry.Registry)] = entry 76 } 77 return sa, nil 78 } 79 80 func (s *secretAuthenticator) Authorization() (*authn.AuthConfig, error) { 81 for _, v := range s.auths { 82 return &authn.AuthConfig{ 83 Username: v.Username, 84 Password: v.Password, 85 Auth: v.Auth, 86 }, nil 87 } 88 return &authn.AuthConfig{}, nil 89 } 90 91 func (s *secretAuthenticator) Auth(ctx context.Context) (bool, error) { 92 for k := range s.auths { 93 return s.AuthRegistry(ctx, k) 94 } 95 return false, fmt.Errorf("no registry found in image-registry") 96 } 97 98 func (s *secretAuthenticator) AuthRegistry(ctx context.Context, reg string) (bool, error) { 99 url, err := url.Parse(reg) // in case reg is unformatted like http://docker.index.io 100 if err != nil { 101 return false, err 102 } 103 104 options := make([]name.Option, 0) 105 if url.Scheme == "http" || s.insecure { 106 options = append(options, name.Insecure) 107 } 108 109 registry, err := name.NewRegistry(url.Host, options...) 110 if err != nil { 111 return false, err 112 } 113 114 _, err = transport.NewWithContext(ctx, registry, s, http.DefaultTransport, []string{}) 115 if err != nil { 116 return false, err 117 } 118 119 return true, nil 120 } 121 122 func (s *secretAuthenticator) Options() []Option { 123 options := make([]Option, 0) 124 125 options = append(options, WithAuth(s)) 126 if s.insecure { 127 options = append(options, Insecure) 128 } 129 130 return options 131 }