github.com/reds/docker@v1.11.2-rc1/distribution/registry.go (about) 1 package distribution 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "net/url" 8 "time" 9 10 "github.com/docker/distribution" 11 distreference "github.com/docker/distribution/reference" 12 "github.com/docker/distribution/registry/client" 13 "github.com/docker/distribution/registry/client/auth" 14 "github.com/docker/distribution/registry/client/transport" 15 "github.com/docker/docker/dockerversion" 16 "github.com/docker/docker/registry" 17 "github.com/docker/engine-api/types" 18 "golang.org/x/net/context" 19 ) 20 21 type dumbCredentialStore struct { 22 auth *types.AuthConfig 23 } 24 25 func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) { 26 return dcs.auth.Username, dcs.auth.Password 27 } 28 29 func (dcs dumbCredentialStore) RefreshToken(*url.URL, string) string { 30 return dcs.auth.IdentityToken 31 } 32 33 func (dcs dumbCredentialStore) SetRefreshToken(*url.URL, string, string) { 34 } 35 36 // NewV2Repository returns a repository (v2 only). It creates a HTTP transport 37 // providing timeout settings and authentication support, and also verifies the 38 // remote API version. 39 func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *types.AuthConfig, actions ...string) (repo distribution.Repository, foundVersion bool, err error) { 40 repoName := repoInfo.FullName() 41 // If endpoint does not support CanonicalName, use the RemoteName instead 42 if endpoint.TrimHostname { 43 repoName = repoInfo.RemoteName() 44 } 45 46 // TODO(dmcgowan): Call close idle connections when complete, use keep alive 47 base := &http.Transport{ 48 Proxy: http.ProxyFromEnvironment, 49 Dial: (&net.Dialer{ 50 Timeout: 30 * time.Second, 51 KeepAlive: 30 * time.Second, 52 DualStack: true, 53 }).Dial, 54 TLSHandshakeTimeout: 10 * time.Second, 55 TLSClientConfig: endpoint.TLSConfig, 56 // TODO(dmcgowan): Call close idle connections when complete and use keep alive 57 DisableKeepAlives: true, 58 } 59 60 modifiers := registry.DockerHeaders(dockerversion.DockerUserAgent(ctx), metaHeaders) 61 authTransport := transport.NewTransport(base, modifiers...) 62 63 challengeManager, foundVersion, err := registry.PingV2Registry(endpoint, authTransport) 64 if err != nil { 65 transportOK := false 66 if responseErr, ok := err.(registry.PingResponseError); ok { 67 transportOK = true 68 err = responseErr.Err 69 } 70 return nil, foundVersion, fallbackError{ 71 err: err, 72 confirmedV2: foundVersion, 73 transportOK: transportOK, 74 } 75 } 76 77 if authConfig.RegistryToken != "" { 78 passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken} 79 modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler)) 80 } else { 81 creds := dumbCredentialStore{auth: authConfig} 82 tokenHandlerOptions := auth.TokenHandlerOptions{ 83 Transport: authTransport, 84 Credentials: creds, 85 Scopes: []auth.Scope{ 86 auth.RepositoryScope{ 87 Repository: repoName, 88 Actions: actions, 89 }, 90 }, 91 ClientID: registry.AuthClientID, 92 } 93 tokenHandler := auth.NewTokenHandlerWithOptions(tokenHandlerOptions) 94 basicHandler := auth.NewBasicHandler(creds) 95 modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler)) 96 } 97 tr := transport.NewTransport(base, modifiers...) 98 99 repoNameRef, err := distreference.ParseNamed(repoName) 100 if err != nil { 101 return nil, foundVersion, fallbackError{ 102 err: err, 103 confirmedV2: foundVersion, 104 transportOK: true, 105 } 106 } 107 108 repo, err = client.NewRepository(ctx, repoNameRef, endpoint.URL.String(), tr) 109 if err != nil { 110 err = fallbackError{ 111 err: err, 112 confirmedV2: foundVersion, 113 transportOK: true, 114 } 115 } 116 return 117 } 118 119 type existingTokenHandler struct { 120 token string 121 } 122 123 func (th *existingTokenHandler) Scheme() string { 124 return "bearer" 125 } 126 127 func (th *existingTokenHandler) AuthorizeRequest(req *http.Request, params map[string]string) error { 128 req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", th.token)) 129 return nil 130 }