@@ -3,17 +3,14 @@ package image
33import (
44 "context"
55 "encoding/hex"
6- "encoding/json"
76 "fmt"
87 "io"
9- "sort"
108
119 "github.com/distribution/reference"
1210 "github.com/docker/cli/cli/command"
1311 "github.com/docker/cli/cli/internal/jsonstream"
1412 "github.com/docker/cli/cli/streams"
1513 "github.com/docker/cli/cli/trust"
16- "github.com/docker/docker/api/types"
1714 "github.com/docker/docker/api/types/image"
1815 registrytypes "github.com/docker/docker/api/types/registry"
1916 "github.com/docker/docker/registry"
@@ -55,120 +52,19 @@ func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
5552
5653 defer responseBody .Close ()
5754
58- return PushTrustedReference (ctx , cli , repoInfo , ref , authConfig , responseBody )
55+ return trust . PushTrustedReference (ctx , cli , repoInfo , ref , authConfig , responseBody , command . UserAgent () )
5956}
6057
6158// PushTrustedReference pushes a canonical reference to the trust server.
6259//
63- //nolint:gocyclo
60+ // Deprecated: use [trust.PushTrustedReference] instead. this function was only used internally and will be removed in the next release.
6461func PushTrustedReference (ctx context.Context , ioStreams command.Streams , repoInfo * registry.RepositoryInfo , ref reference.Named , authConfig registrytypes.AuthConfig , in io.Reader ) error {
65- // If it is a trusted push we would like to find the target entry which match the
66- // tag provided in the function and then do an AddTarget later.
67- notaryTarget := & client.Target {}
68- // Count the times of calling for handleTarget,
69- // if it is called more that once, that should be considered an error in a trusted push.
70- cnt := 0
71- handleTarget := func (msg jsonstream.JSONMessage ) {
72- cnt ++
73- if cnt > 1 {
74- // handleTarget should only be called once. This will be treated as an error.
75- return
76- }
77-
78- var pushResult types.PushResult
79- err := json .Unmarshal (* msg .Aux , & pushResult )
80- if err == nil && pushResult .Tag != "" {
81- if dgst , err := digest .Parse (pushResult .Digest ); err == nil {
82- h , err := hex .DecodeString (dgst .Hex ())
83- if err != nil {
84- notaryTarget = nil
85- return
86- }
87- notaryTarget .Name = pushResult .Tag
88- notaryTarget .Hashes = data.Hashes {string (dgst .Algorithm ()): h }
89- notaryTarget .Length = int64 (pushResult .Size )
90- }
91- }
92- }
93-
94- var tag string
95- switch x := ref .(type ) {
96- case reference.Canonical :
97- return errors .New ("cannot push a digest reference" )
98- case reference.NamedTagged :
99- tag = x .Tag ()
100- default :
101- // We want trust signatures to always take an explicit tag,
102- // otherwise it will act as an untrusted push.
103- if err := jsonstream .Display (ctx , in , ioStreams .Out ()); err != nil {
104- return err
105- }
106- _ , _ = fmt .Fprintln (ioStreams .Err (), "No tag specified, skipping trust metadata push" )
107- return nil
108- }
109-
110- if err := jsonstream .Display (ctx , in , ioStreams .Out (), jsonstream .WithAuxCallback (handleTarget )); err != nil {
111- return err
112- }
113-
114- if cnt > 1 {
115- return errors .Errorf ("internal error: only one call to handleTarget expected" )
116- }
117-
118- if notaryTarget == nil {
119- return errors .Errorf ("no targets found, provide a specific tag in order to sign it" )
120- }
121-
122- _ , _ = fmt .Fprintln (ioStreams .Out (), "Signing and pushing trust metadata" )
123-
124- repo , err := trust .GetNotaryRepository (ioStreams .In (), ioStreams .Out (), command .UserAgent (), repoInfo , & authConfig , "push" , "pull" )
125- if err != nil {
126- return errors .Wrap (err , "error establishing connection to trust repository" )
127- }
128-
129- // get the latest repository metadata so we can figure out which roles to sign
130- _ , err = repo .ListTargets ()
131-
132- switch err .(type ) {
133- case client.ErrRepoNotInitialized , client.ErrRepositoryNotExist :
134- keys := repo .GetCryptoService ().ListKeys (data .CanonicalRootRole )
135- var rootKeyID string
136- // always select the first root key
137- if len (keys ) > 0 {
138- sort .Strings (keys )
139- rootKeyID = keys [0 ]
140- } else {
141- rootPublicKey , err := repo .GetCryptoService ().Create (data .CanonicalRootRole , "" , data .ECDSAKey )
142- if err != nil {
143- return err
144- }
145- rootKeyID = rootPublicKey .ID ()
146- }
147-
148- // Initialize the notary repository with a remotely managed snapshot key
149- if err := repo .Initialize ([]string {rootKeyID }, data .CanonicalSnapshotRole ); err != nil {
150- return trust .NotaryError (repoInfo .Name .Name (), err )
151- }
152- _ , _ = fmt .Fprintf (ioStreams .Out (), "Finished initializing %q\n " , repoInfo .Name .Name ())
153- err = repo .AddTarget (notaryTarget , data .CanonicalTargetsRole )
154- case nil :
155- // already initialized and we have successfully downloaded the latest metadata
156- err = trust .AddToAllSignableRoles (repo , notaryTarget )
157- default :
158- return trust .NotaryError (repoInfo .Name .Name (), err )
159- }
160-
161- if err == nil {
162- err = repo .Publish ()
163- }
164-
165- if err != nil {
166- err = errors .Wrapf (err , "failed to sign %s:%s" , repoInfo .Name .Name (), tag )
167- return trust .NotaryError (repoInfo .Name .Name (), err )
168- }
62+ return pushTrustedReference (ctx , ioStreams , repoInfo , ref , authConfig , in )
63+ }
16964
170- _ , _ = fmt .Fprintf (ioStreams .Out (), "Successfully signed %s:%s\n " , repoInfo .Name .Name (), tag )
171- return nil
65+ // pushTrustedReference pushes a canonical reference to the trust server.
66+ func pushTrustedReference (ctx context.Context , ioStreams command.Streams , repoInfo * registry.RepositoryInfo , ref reference.Named , authConfig registrytypes.AuthConfig , in io.Reader ) error {
67+ return trust .PushTrustedReference (ctx , ioStreams , repoInfo , ref , authConfig , in , command .UserAgent ())
17268}
17369
17470// trustedPull handles content trust pulling of an image
0 commit comments