github.com/openshift/moby-moby@v1.13.2-0.20170601211448-f5ec1e2936dc/cli/command/service/trust.go (about)

     1  package service
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  
     7  	"github.com/Sirupsen/logrus"
     8  	"github.com/docker/distribution/digest"
     9  	distreference "github.com/docker/distribution/reference"
    10  	"github.com/docker/docker/api/types/swarm"
    11  	"github.com/docker/docker/cli/command"
    12  	"github.com/docker/docker/cli/trust"
    13  	"github.com/docker/docker/reference"
    14  	"github.com/docker/docker/registry"
    15  	"github.com/docker/notary/tuf/data"
    16  	"github.com/pkg/errors"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  func resolveServiceImageDigest(dockerCli *command.DockerCli, service *swarm.ServiceSpec) error {
    21  	if !command.IsTrusted() {
    22  		// Digests are resolved by the daemon when not using content
    23  		// trust.
    24  		return nil
    25  	}
    26  
    27  	image := service.TaskTemplate.ContainerSpec.Image
    28  
    29  	// We only attempt to resolve the digest if the reference
    30  	// could be parsed as a digest reference. Specifying an image ID
    31  	// is valid but not resolvable. There is no warning message for
    32  	// an image ID because it's valid to use one.
    33  	if _, err := digest.ParseDigest(image); err == nil {
    34  		return nil
    35  	}
    36  
    37  	ref, err := reference.ParseNamed(image)
    38  	if err != nil {
    39  		return fmt.Errorf("Could not parse image reference %s", service.TaskTemplate.ContainerSpec.Image)
    40  	}
    41  	if _, ok := ref.(reference.Canonical); !ok {
    42  		ref = reference.WithDefaultTag(ref)
    43  
    44  		taggedRef, ok := ref.(reference.NamedTagged)
    45  		if !ok {
    46  			// This should never happen because a reference either
    47  			// has a digest, or WithDefaultTag would give it a tag.
    48  			return errors.New("Failed to resolve image digest using content trust: reference is missing a tag")
    49  		}
    50  
    51  		resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
    52  		if err != nil {
    53  			return fmt.Errorf("Failed to resolve image digest using content trust: %v", err)
    54  		}
    55  		logrus.Debugf("resolved image tag to %s using content trust", resolvedImage.String())
    56  		service.TaskTemplate.ContainerSpec.Image = resolvedImage.String()
    57  	}
    58  	return nil
    59  }
    60  
    61  func trustedResolveDigest(ctx context.Context, cli *command.DockerCli, ref reference.NamedTagged) (distreference.Canonical, error) {
    62  	repoInfo, err := registry.ParseRepositoryInfo(ref)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
    68  
    69  	notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull")
    70  	if err != nil {
    71  		return nil, errors.Wrap(err, "error establishing connection to trust repository")
    72  	}
    73  
    74  	t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
    75  	if err != nil {
    76  		return nil, trust.NotaryError(repoInfo.FullName(), err)
    77  	}
    78  	// Only get the tag if it's in the top level targets role or the releases delegation role
    79  	// ignore it if it's in any other delegation roles
    80  	if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
    81  		return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.String()))
    82  	}
    83  
    84  	logrus.Debugf("retrieving target for %s role\n", t.Role)
    85  	h, ok := t.Hashes["sha256"]
    86  	if !ok {
    87  		return nil, errors.New("no valid hash, expecting sha256")
    88  	}
    89  
    90  	dgst := digest.NewDigestFromHex("sha256", hex.EncodeToString(h))
    91  
    92  	// Using distribution reference package to make sure that adding a
    93  	// digest does not erase the tag. When the two reference packages
    94  	// are unified, this will no longer be an issue.
    95  	return distreference.WithDigest(ref, dgst)
    96  }