github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/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/reference"
     9  	"github.com/docker/docker/api/types/swarm"
    10  	"github.com/docker/docker/cli/command"
    11  	"github.com/docker/docker/cli/trust"
    12  	"github.com/docker/docker/registry"
    13  	"github.com/docker/notary/tuf/data"
    14  	"github.com/opencontainers/go-digest"
    15  	"github.com/pkg/errors"
    16  	"golang.org/x/net/context"
    17  )
    18  
    19  func resolveServiceImageDigest(dockerCli *command.DockerCli, service *swarm.ServiceSpec) error {
    20  	if !command.IsTrusted() {
    21  		// Digests are resolved by the daemon when not using content
    22  		// trust.
    23  		return nil
    24  	}
    25  
    26  	ref, err := reference.ParseAnyReference(service.TaskTemplate.ContainerSpec.Image)
    27  	if err != nil {
    28  		return errors.Wrapf(err, "invalid reference %s", service.TaskTemplate.ContainerSpec.Image)
    29  	}
    30  
    31  	// If reference does not have digest (is not canonical nor image id)
    32  	if _, ok := ref.(reference.Digested); !ok {
    33  		namedRef, ok := ref.(reference.Named)
    34  		if !ok {
    35  			return errors.New("failed to resolve image digest using content trust: reference is not named")
    36  		}
    37  		namedRef = reference.TagNameOnly(namedRef)
    38  		taggedRef, ok := namedRef.(reference.NamedTagged)
    39  		if !ok {
    40  			return errors.New("failed to resolve image digest using content trust: reference is not tagged")
    41  		}
    42  
    43  		resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
    44  		if err != nil {
    45  			return errors.Wrap(err, "failed to resolve image digest using content trust")
    46  		}
    47  		resolvedFamiliar := reference.FamiliarString(resolvedImage)
    48  		logrus.Debugf("resolved image tag to %s using content trust", resolvedFamiliar)
    49  		service.TaskTemplate.ContainerSpec.Image = resolvedFamiliar
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  func trustedResolveDigest(ctx context.Context, cli *command.DockerCli, ref reference.NamedTagged) (reference.Canonical, error) {
    56  	repoInfo, err := registry.ParseRepositoryInfo(ref)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
    62  
    63  	notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull")
    64  	if err != nil {
    65  		return nil, errors.Wrap(err, "error establishing connection to trust repository")
    66  	}
    67  
    68  	t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
    69  	if err != nil {
    70  		return nil, trust.NotaryError(repoInfo.Name.Name(), err)
    71  	}
    72  	// Only get the tag if it's in the top level targets role or the releases delegation role
    73  	// ignore it if it's in any other delegation roles
    74  	if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
    75  		return nil, trust.NotaryError(repoInfo.Name.Name(), fmt.Errorf("No trust data for %s", reference.FamiliarString(ref)))
    76  	}
    77  
    78  	logrus.Debugf("retrieving target for %s role\n", t.Role)
    79  	h, ok := t.Hashes["sha256"]
    80  	if !ok {
    81  		return nil, errors.New("no valid hash, expecting sha256")
    82  	}
    83  
    84  	dgst := digest.NewDigestFromHex("sha256", hex.EncodeToString(h))
    85  
    86  	// Allow returning canonical reference with tag
    87  	return reference.WithDigest(ref, dgst)
    88  }