mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
f2d481a299
Further differentiate the APIEndpoint used with V2 with the endpoint type which is only used for v1 registry interactions Rename Endpoint to V1Endpoint and remove version ambiguity Use distribution token handler for login Signed-off-by: Derek McGowan <derek@mcgstyle.net> Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package distribution
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/docker/distribution"
|
|
distreference "github.com/docker/distribution/reference"
|
|
"github.com/docker/distribution/registry/client"
|
|
"github.com/docker/distribution/registry/client/auth"
|
|
"github.com/docker/distribution/registry/client/transport"
|
|
"github.com/docker/docker/dockerversion"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/docker/engine-api/types"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
type dumbCredentialStore struct {
|
|
auth *types.AuthConfig
|
|
}
|
|
|
|
func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) {
|
|
return dcs.auth.Username, dcs.auth.Password
|
|
}
|
|
|
|
// NewV2Repository returns a repository (v2 only). It creates a HTTP transport
|
|
// providing timeout settings and authentication support, and also verifies the
|
|
// remote API version.
|
|
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) {
|
|
repoName := repoInfo.FullName()
|
|
// If endpoint does not support CanonicalName, use the RemoteName instead
|
|
if endpoint.TrimHostname {
|
|
repoName = repoInfo.RemoteName()
|
|
}
|
|
|
|
// TODO(dmcgowan): Call close idle connections when complete, use keep alive
|
|
base := &http.Transport{
|
|
Proxy: http.ProxyFromEnvironment,
|
|
Dial: (&net.Dialer{
|
|
Timeout: 30 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
DualStack: true,
|
|
}).Dial,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
TLSClientConfig: endpoint.TLSConfig,
|
|
// TODO(dmcgowan): Call close idle connections when complete and use keep alive
|
|
DisableKeepAlives: true,
|
|
}
|
|
|
|
modifiers := registry.DockerHeaders(dockerversion.DockerUserAgent(), metaHeaders)
|
|
authTransport := transport.NewTransport(base, modifiers...)
|
|
|
|
challengeManager, foundVersion, err := registry.PingV2Registry(endpoint, authTransport)
|
|
if err != nil {
|
|
transportOK := false
|
|
if responseErr, ok := err.(registry.PingResponseError); ok {
|
|
transportOK = true
|
|
err = responseErr.Err
|
|
}
|
|
return nil, foundVersion, fallbackError{
|
|
err: err,
|
|
confirmedV2: foundVersion,
|
|
transportOK: transportOK,
|
|
}
|
|
}
|
|
|
|
if authConfig.RegistryToken != "" {
|
|
passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
|
|
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
|
} else {
|
|
creds := dumbCredentialStore{auth: authConfig}
|
|
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
|
|
basicHandler := auth.NewBasicHandler(creds)
|
|
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
|
|
}
|
|
tr := transport.NewTransport(base, modifiers...)
|
|
|
|
repoNameRef, err := distreference.ParseNamed(repoName)
|
|
if err != nil {
|
|
return nil, foundVersion, fallbackError{
|
|
err: err,
|
|
confirmedV2: foundVersion,
|
|
transportOK: true,
|
|
}
|
|
}
|
|
|
|
repo, err = client.NewRepository(ctx, repoNameRef, endpoint.URL.String(), tr)
|
|
if err != nil {
|
|
err = fallbackError{
|
|
err: err,
|
|
confirmedV2: foundVersion,
|
|
transportOK: true,
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
type existingTokenHandler struct {
|
|
token string
|
|
}
|
|
|
|
func (th *existingTokenHandler) Scheme() string {
|
|
return "bearer"
|
|
}
|
|
|
|
func (th *existingTokenHandler) AuthorizeRequest(req *http.Request, params map[string]string) error {
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", th.token))
|
|
return nil
|
|
}
|