func (cli *DockerCli) trustedReference(repo string, ref registry.Reference) (registry.Reference, error) { repoInfo, err := registry.ParseRepositoryInfo(repo) if err != nil { return nil, err } // Resolve the Auth config relevant for this server authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index) notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig) if err != nil { fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) return nil, err } t, err := notaryRepo.GetTargetByName(ref.String()) if err != nil { return nil, err } r, err := convertTarget(*t) if err != nil { return nil, err } return registry.DigestReference(r.digest), nil }
func (cli *DockerCli) tagTrusted(repoInfo *registry.RepositoryInfo, trustedRef, ref registry.Reference) error { fullName := trustedRef.ImageName(repoInfo.LocalName) fmt.Fprintf(cli.out, "Tagging %s as %s\n", fullName, ref.ImageName(repoInfo.LocalName)) tv := url.Values{} tv.Set("repo", repoInfo.LocalName) tv.Set("tag", ref.String()) tv.Set("force", "1") if _, _, err := readBody(cli.call("POST", "/images/"+fullName+"/tag?"+tv.Encode(), nil, nil)); err != nil { return err } return nil }
func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege apiclient.RequestPrivilegeFunc) error { var refs []target notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig) if err != nil { fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) return err } if ref.String() == "" { // List all targets targets, err := notaryRepo.ListTargets(releasesRole, data.CanonicalTargetsRole) if err != nil { return notaryError(repoInfo.FullName(), err) } for _, tgt := range targets { t, err := convertTarget(tgt.Target) if err != nil { fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.Name()) continue } refs = append(refs, t) } } else { t, err := notaryRepo.GetTargetByName(ref.String(), releasesRole, data.CanonicalTargetsRole) if err != nil { return notaryError(repoInfo.FullName(), err) } r, err := convertTarget(t.Target) if err != nil { return err } refs = append(refs, r) } for i, r := range refs { displayTag := r.reference.String() if displayTag != "" { displayTag = ":" + displayTag } fmt.Fprintf(cli.out, "Pull (%d of %d): %s%s@%s\n", i+1, len(refs), repoInfo.Name(), displayTag, r.digest) if err := cli.imagePullPrivileged(authConfig, repoInfo.Name(), r.digest.String(), requestPrivilege); err != nil { return err } // If reference is not trusted, tag by trusted reference if !r.reference.HasDigest() { tagged, err := reference.WithTag(repoInfo, r.reference.String()) if err != nil { return err } trustedRef, err := reference.WithDigest(repoInfo, r.digest) if err != nil { return err } if err := cli.tagTrusted(trustedRef, tagged); err != nil { return err } } } return nil }
func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, error) { containerValues := url.Values{} if name != "" { containerValues.Set("name", name) } mergedConfig := runconfig.MergeConfigs(config, hostConfig) var containerIDFile *cidFile if cidfile != "" { var err error if containerIDFile, err = newCIDFile(cidfile); err != nil { return nil, err } defer containerIDFile.Close() } repo, tag := parsers.ParseRepositoryTag(config.Image) if tag == "" { tag = tags.DEFAULTTAG } ref := registry.ParseReference(tag) var trustedRef registry.Reference if isTrusted() && !ref.HasDigest() { var err error trustedRef, err = cli.trustedReference(repo, ref) if err != nil { return nil, err } config.Image = trustedRef.ImageName(repo) } //create the container serverResp, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil) //if image not found try to pull it if serverResp.statusCode == 404 && strings.Contains(err.Error(), config.Image) { fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.ImageName(repo)) // we don't want to write to stdout anything apart from container.ID if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil { return nil, err } if trustedRef != nil && !ref.HasDigest() { repoInfo, err := registry.ParseRepositoryInfo(repo) if err != nil { return nil, err } if err := cli.tagTrusted(repoInfo, trustedRef, ref); err != nil { return nil, err } } // Retry if serverResp, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil); err != nil { return nil, err } } else if err != nil { return nil, err } defer serverResp.body.Close() var response types.ContainerCreateResponse if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { return nil, err } for _, warning := range response.Warnings { fmt.Fprintf(cli.err, "WARNING: %s\n", warning) } if containerIDFile != nil { if err = containerIDFile.Write(response.ID); err != nil { return nil, err } } return &response, nil }
// TrustedPull handles content trust pulling of an image func (cli *DockerCli) TrustedPull(ctx context.Context, repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error { var refs []target notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull") if err != nil { fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) return err } if ref.String() == "" { // List all targets targets, err := notaryRepo.ListTargets(releasesRole, data.CanonicalTargetsRole) if err != nil { return notaryError(repoInfo.FullName(), err) } for _, tgt := range targets { t, err := convertTarget(tgt.Target) if err != nil { fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.Name()) continue } // Only list tags in the top level targets role or the releases delegation role - ignore // all other delegation roles if tgt.Role != releasesRole && tgt.Role != data.CanonicalTargetsRole { continue } refs = append(refs, t) } if len(refs) == 0 { return notaryError(repoInfo.FullName(), fmt.Errorf("No trusted tags for %s", repoInfo.FullName())) } } else { t, err := notaryRepo.GetTargetByName(ref.String(), releasesRole, data.CanonicalTargetsRole) if err != nil { return notaryError(repoInfo.FullName(), err) } // Only get the tag if it's in the top level targets role or the releases delegation role // ignore it if it's in any other delegation roles if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole { return notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.String())) } logrus.Debugf("retrieving target for %s role\n", t.Role) r, err := convertTarget(t.Target) if err != nil { return err } refs = append(refs, r) } for i, r := range refs { displayTag := r.reference.String() if displayTag != "" { displayTag = ":" + displayTag } fmt.Fprintf(cli.out, "Pull (%d of %d): %s%s@%s\n", i+1, len(refs), repoInfo.Name(), displayTag, r.digest) ref, err := reference.WithDigest(repoInfo, r.digest) if err != nil { return err } if err := cli.ImagePullPrivileged(ctx, authConfig, ref.String(), requestPrivilege, false); err != nil { return err } // If reference is not trusted, tag by trusted reference if !r.reference.HasDigest() { tagged, err := reference.WithTag(repoInfo, r.reference.String()) if err != nil { return err } trustedRef, err := reference.WithDigest(repoInfo, r.digest) if err != nil { return err } if err := cli.TagTrusted(ctx, trustedRef, tagged); err != nil { return err } } } return nil }
func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig cliconfig.AuthConfig) error { var ( v = url.Values{} refs = []target{} ) notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig) if err != nil { fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err) return err } if ref.String() == "" { // List all targets targets, err := notaryRepo.ListTargets() if err != nil { return notaryError(err) } for _, tgt := range targets { t, err := convertTarget(*tgt) if err != nil { fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.LocalName) continue } refs = append(refs, t) } } else { t, err := notaryRepo.GetTargetByName(ref.String()) if err != nil { return notaryError(err) } r, err := convertTarget(*t) if err != nil { return err } refs = append(refs, r) } v.Set("fromImage", repoInfo.LocalName) for i, r := range refs { displayTag := r.reference.String() if displayTag != "" { displayTag = ":" + displayTag } fmt.Fprintf(cli.out, "Pull (%d of %d): %s%s@%s\n", i+1, len(refs), repoInfo.LocalName, displayTag, r.digest) v.Set("tag", r.digest.String()) _, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull") if err != nil { return err } // If reference is not trusted, tag by trusted reference if !r.reference.HasDigest() { if err := cli.tagTrusted(repoInfo, registry.DigestReference(r.digest), r.reference); err != nil { return err } } } return nil }