github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/service/trust.go (about) 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 // When not using content trust, digest resolution happens later when 20 // contacting the registry to retrieve image information. 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 // If reference does not have digest (is not canonical nor image id) 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 // Only get the tag if it's in the top level targets role or the releases delegation role 71 // ignore it if it's in any other delegation roles 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 // Allow returning canonical reference with tag 85 return reference.WithDigest(ref, dgst) 86 }