mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
257c59251b
This updates the vendored docker/distribution to the current master branch. Note the following changes: - The manifest package was split into manifest/schema1. Most references to the manifest package in the engine needed to be updated to use schema1 instead. - Validation functions in api/v2 were replaced by the distribution/reference package. The engine code has been updated to use the reference package for validation where necessary. A future PR will change the engine to use the types defined in distribution/reference more comprehensively. - The reference package explicitly allows double _ characters in repository names. registry_test.go was updated for this. - TestPullFailsWithAlteredManifest was corrupting the manifest JSON, now that the schema1 package unmarshals the correct payload. The test is being changed to modify the JSON without affecting its length, which allows the pull to succeed to the point where digest validation happens. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
115 lines
3.5 KiB
Go
115 lines
3.5 KiB
Go
package graph
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/distribution"
|
|
"github.com/docker/distribution/digest"
|
|
"github.com/docker/distribution/manifest/schema1"
|
|
"github.com/docker/distribution/registry/client"
|
|
"github.com/docker/distribution/registry/client/auth"
|
|
"github.com/docker/distribution/registry/client/transport"
|
|
"github.com/docker/docker/cliconfig"
|
|
"github.com/docker/docker/registry"
|
|
"golang.org/x/net/context"
|
|
"strings"
|
|
)
|
|
|
|
type dumbCredentialStore struct {
|
|
auth *cliconfig.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(repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *cliconfig.AuthConfig, actions ...string) (distribution.Repository, error) {
|
|
ctx := context.Background()
|
|
|
|
repoName := repoInfo.CanonicalName
|
|
// 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(metaHeaders)
|
|
authTransport := transport.NewTransport(base, modifiers...)
|
|
pingClient := &http.Client{
|
|
Transport: authTransport,
|
|
Timeout: 15 * time.Second,
|
|
}
|
|
endpointStr := strings.TrimRight(endpoint.URL, "/") + "/v2/"
|
|
req, err := http.NewRequest("GET", endpointStr, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := pingClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
versions := auth.APIVersions(resp, endpoint.VersionHeader)
|
|
if endpoint.VersionHeader != "" && len(endpoint.Versions) > 0 {
|
|
var foundVersion bool
|
|
for _, version := range endpoint.Versions {
|
|
for _, pingVersion := range versions {
|
|
if version == pingVersion {
|
|
foundVersion = true
|
|
}
|
|
}
|
|
}
|
|
if !foundVersion {
|
|
return nil, errors.New("endpoint does not support v2 API")
|
|
}
|
|
}
|
|
|
|
challengeManager := auth.NewSimpleChallengeManager()
|
|
if err := challengeManager.AddResponse(resp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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...)
|
|
|
|
return client.NewRepository(ctx, repoName, endpoint.URL, tr)
|
|
}
|
|
|
|
func digestFromManifest(m *schema1.SignedManifest, localName string) (digest.Digest, int, error) {
|
|
payload, err := m.Payload()
|
|
if err != nil {
|
|
// If this failed, the signatures section was corrupted
|
|
// or missing. Treat the entire manifest as the payload.
|
|
payload = m.Raw
|
|
}
|
|
manifestDigest, err := digest.FromBytes(payload)
|
|
if err != nil {
|
|
logrus.Infof("Could not compute manifest digest for %s:%s : %v", localName, m.Tag, err)
|
|
}
|
|
return manifestDigest, len(payload), nil
|
|
}
|