github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/image/save/distributionpkg/proxy/proxyauth.go (about) 1 // Copyright © 2021 https://github.com/distribution/distribution 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package proxy 16 17 import ( 18 "crypto/tls" 19 "io" 20 "net/http" 21 "net/url" 22 "strings" 23 24 "github.com/distribution/distribution/v3/registry/client/auth" 25 "github.com/distribution/distribution/v3/registry/client/auth/challenge" 26 "github.com/sirupsen/logrus" 27 ) 28 29 // comment this const because not used 30 //const challengeHeader = "Docker-Distribution-Api-Version" 31 32 const certUnknown = "x509: certificate signed by unknown authority" 33 34 type userpass struct { 35 username string 36 password string 37 } 38 39 type credentials struct { 40 creds map[string]userpass 41 } 42 43 func (c credentials) Basic(u *url.URL) (string, string) { 44 up := c.creds[u.String()] 45 46 return up.username, up.password 47 } 48 49 func (c credentials) RefreshToken(u *url.URL, service string) string { 50 return "" 51 } 52 53 func (c credentials) SetRefreshToken(u *url.URL, service, token string) { 54 } 55 56 // configureAuth stores credentials for challenge responses 57 func configureAuth(username, password, remoteURL string) (auth.CredentialStore, error) { 58 creds := map[string]userpass{} 59 60 authURLs, err := getAuthURLs(remoteURL) 61 if err != nil { 62 return nil, err 63 } 64 65 for _, url := range authURLs { 66 // context.GetLogger(context.Background()).Infof("Discovered token authentication URL: %s", url) 67 creds[url] = userpass{ 68 username: username, 69 password: password, 70 } 71 } 72 73 return credentials{creds: creds}, nil 74 } 75 76 func getAuthURLs(remoteURL string) ([]string, error) { 77 authURLs := []string{} 78 79 resp, err := http.Get(remoteURL + "/v2/") 80 if err != nil { 81 if strings.Contains(err.Error(), certUnknown) { 82 logrus.Warnf("create connect with unauthenticated registry url: %s", remoteURL) 83 resp, err = newClientSkipVerify().Get(remoteURL + "/v2/") 84 if err != nil { 85 return nil, err 86 } 87 } else { 88 return nil, err 89 } 90 } 91 defer func(Body io.ReadCloser) { 92 err := Body.Close() 93 if err != nil { 94 logrus.Warnf("failed to close http reader") 95 } 96 }(resp.Body) 97 98 for _, c := range challenge.ResponseChallenges(resp) { 99 if strings.EqualFold(c.Scheme, "bearer") { 100 authURLs = append(authURLs, c.Parameters["realm"]) 101 } 102 } 103 104 return authURLs, nil 105 } 106 107 // #nosec 108 func ping(manager challenge.Manager, endpoint string) error { 109 resp, err := http.Get(endpoint) 110 if err != nil { 111 if strings.Contains(err.Error(), certUnknown) { 112 resp, err = newClientSkipVerify().Get(endpoint) 113 if err != nil { 114 return err 115 } 116 } else { 117 return err 118 } 119 } 120 defer resp.Body.Close() 121 122 return manager.AddResponse(resp) 123 } 124 125 // #nosec 126 func newClientSkipVerify() *http.Client { 127 return &http.Client{ 128 Transport: &http.Transport{ 129 TLSClientConfig: &tls.Config{ 130 InsecureSkipVerify: true, 131 }, 132 }, 133 } 134 }