...
1 package service
2
3 import (
4 "encoding/hex"
5
6 "github.com/distribution/reference"
7 "github.com/docker/cli/cli/command"
8 "github.com/docker/cli/cli/trust"
9 "github.com/docker/docker/api/types/swarm"
10 "github.com/docker/docker/registry"
11 "github.com/opencontainers/go-digest"
12 "github.com/pkg/errors"
13 "github.com/sirupsen/logrus"
14 "github.com/theupdateframework/notary/tuf/data"
15 )
16
17 func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm.ServiceSpec) error {
18 if !dockerCli.ContentTrustEnabled() {
19
20
21 return nil
22 }
23
24 ref, err := reference.ParseAnyReference(service.TaskTemplate.ContainerSpec.Image)
25 if err != nil {
26 return errors.Wrapf(err, "invalid reference %s", service.TaskTemplate.ContainerSpec.Image)
27 }
28
29
30 if _, ok := ref.(reference.Digested); !ok {
31 namedRef, ok := ref.(reference.Named)
32 if !ok {
33 return errors.New("failed to resolve image digest using content trust: reference is not named")
34 }
35 namedRef = reference.TagNameOnly(namedRef)
36 taggedRef, ok := namedRef.(reference.NamedTagged)
37 if !ok {
38 return errors.New("failed to resolve image digest using content trust: reference is not tagged")
39 }
40
41 resolvedImage, err := trustedResolveDigest(dockerCli, taggedRef)
42 if err != nil {
43 return errors.Wrap(err, "failed to resolve image digest using content trust")
44 }
45 resolvedFamiliar := reference.FamiliarString(resolvedImage)
46 logrus.Debugf("resolved image tag to %s using content trust", resolvedFamiliar)
47 service.TaskTemplate.ContainerSpec.Image = resolvedFamiliar
48 }
49
50 return nil
51 }
52
53 func trustedResolveDigest(cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
54 repoInfo, err := registry.ParseRepositoryInfo(ref)
55 if err != nil {
56 return nil, err
57 }
58
59 authConfig := command.ResolveAuthConfig(cli.ConfigFile(), repoInfo.Index)
60
61 notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
62 if err != nil {
63 return nil, errors.Wrap(err, "error establishing connection to trust repository")
64 }
65
66 t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
67 if err != nil {
68 return nil, trust.NotaryError(repoInfo.Name.Name(), err)
69 }
70
71
72 if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
73 return nil, trust.NotaryError(repoInfo.Name.Name(), errors.Errorf("No trust data for %s", reference.FamiliarString(ref)))
74 }
75
76 logrus.Debugf("retrieving target for %s role\n", t.Role)
77 h, ok := t.Hashes["sha256"]
78 if !ok {
79 return nil, errors.New("no valid hash, expecting sha256")
80 }
81
82 dgst := digest.NewDigestFromHex("sha256", hex.EncodeToString(h))
83
84
85 return reference.WithDigest(ref, dgst)
86 }
87
View as plain text