From 5dddf7e98e3296ddec07e104ea829bebdb15d98d Mon Sep 17 00:00:00 2001 From: HuKeping Date: Fri, 5 Feb 2016 10:56:43 +0800 Subject: [PATCH 1/2] Refactor trust push Unlike the untrusted push without an explicit tag will push all tags for that repo, the trusted push would expect an explicit tag. So that the code that attempts to do smart logic around signing multiple tags should be removed. Signed-off-by: Hu Keping --- api/client/trust.go | 68 ++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/api/client/trust.go b/api/client/trust.go index 83e052fbaf..ea910dda7d 100644 --- a/api/client/trust.go +++ b/api/client/trust.go @@ -375,34 +375,57 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, defer responseBody.Close() - targets := []target{} + // If it is a trusted push we would like to find the target entry which match the + // tag provided in the function and then do an AddTarget later. + target := &client.Target{} + // Count the times of calling for handleTarget, + // if it is called more that once, that should be considered an error in a trusted push. + cnt := 0 handleTarget := func(aux *json.RawMessage) { + cnt++ + if cnt > 1 { + // handleTarget should only be called one. This will be treated as an error. + return + } + var pushResult distribution.PushResult err := json.Unmarshal(*aux, &pushResult) if err == nil && pushResult.Tag != "" && pushResult.Digest.Validate() == nil { - targets = append(targets, target{ - reference: registry.ParseReference(pushResult.Tag), - digest: pushResult.Digest, - size: int64(pushResult.Size), - }) + h, err := hex.DecodeString(pushResult.Digest.Hex()) + if err != nil { + target = nil + return + } + target.Name = registry.ParseReference(pushResult.Tag).String() + target.Hashes = data.Hashes{string(pushResult.Digest.Algorithm()): h} + target.Length = int64(pushResult.Size) } } - err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget) - if err != nil { + // We want trust signatures to always take an explicit tag, + // otherwise it will act as an untrusted push. + if tag == "" { + if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil); err != nil { + return err + } + fmt.Fprintln(cli.out, "No tag specified, skipping trust metadata push") + return nil + } + + if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget); err != nil { return err } - if tag == "" { - fmt.Fprintf(cli.out, "No tag specified, skipping trust metadata push\n") - return nil + if cnt > 1 { + return fmt.Errorf("internal error: only one call to handleTarget expected") } - if len(targets) == 0 { - fmt.Fprintf(cli.out, "No targets found, skipping trust metadata push\n") + + if target == nil { + fmt.Fprintln(cli.out, "No targets found, please provide a specific tag in order to sign it") return nil } - fmt.Fprintf(cli.out, "Signing and pushing trust metadata\n") + fmt.Fprintln(cli.out, "Signing and pushing trust metadata") repo, err := cli.getNotaryRepository(repoInfo, authConfig, "push", "pull") if err != nil { @@ -410,21 +433,8 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, return err } - for _, target := range targets { - h, err := hex.DecodeString(target.digest.Hex()) - if err != nil { - return err - } - t := &client.Target{ - Name: target.reference.String(), - Hashes: data.Hashes{ - string(target.digest.Algorithm()): h, - }, - Length: int64(target.size), - } - if err := repo.AddTarget(t, releasesRole); err != nil { - return err - } + if err := repo.AddTarget(target, releasesRole); err != nil { + return err } err = repo.Publish() From 1a6866273697361f33ec908f51cf0e071a36b69d Mon Sep 17 00:00:00 2001 From: HuKeping Date: Wed, 24 Feb 2016 12:06:40 +0800 Subject: [PATCH 2/2] Messaging both succeed and failure about the signing It would be good to add a clearer failure or succeed message. Signed-off-by: Hu Keping --- api/client/trust.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/client/trust.go b/api/client/trust.go index ea910dda7d..697326e9ea 100644 --- a/api/client/trust.go +++ b/api/client/trust.go @@ -438,7 +438,11 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string, } err = repo.Publish() - if _, ok := err.(client.ErrRepoNotInitialized); !ok { + if err == nil { + fmt.Fprintf(cli.out, "Successfully signed %q:%s\n", repoInfo.FullName(), tag) + return nil + } else if _, ok := err.(client.ErrRepoNotInitialized); !ok { + fmt.Fprintf(cli.out, "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error()) return notaryError(repoInfo.FullName(), err) }