github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/trust/revoke.go (about) 1 package trust 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/docker/cli/cli" 8 "github.com/docker/cli/cli/command" 9 "github.com/docker/cli/cli/command/image" 10 "github.com/docker/cli/cli/trust" 11 "github.com/docker/docker/errdefs" 12 "github.com/pkg/errors" 13 "github.com/spf13/cobra" 14 "github.com/theupdateframework/notary/client" 15 "github.com/theupdateframework/notary/tuf/data" 16 ) 17 18 type revokeOptions struct { 19 forceYes bool 20 } 21 22 func newRevokeCommand(dockerCLI command.Cli) *cobra.Command { 23 options := revokeOptions{} 24 cmd := &cobra.Command{ 25 Use: "revoke [OPTIONS] IMAGE[:TAG]", 26 Short: "Remove trust for an image", 27 Args: cli.ExactArgs(1), 28 RunE: func(cmd *cobra.Command, args []string) error { 29 return revokeTrust(cmd.Context(), dockerCLI, args[0], options) 30 }, 31 } 32 flags := cmd.Flags() 33 flags.BoolVarP(&options.forceYes, "yes", "y", false, "Do not prompt for confirmation") 34 return cmd 35 } 36 37 func revokeTrust(ctx context.Context, dockerCLI command.Cli, remote string, options revokeOptions) error { 38 imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(dockerCLI), remote) 39 if err != nil { 40 return err 41 } 42 tag := imgRefAndAuth.Tag() 43 if imgRefAndAuth.Tag() == "" && imgRefAndAuth.Digest() != "" { 44 return fmt.Errorf("cannot use a digest reference for IMAGE:TAG") 45 } 46 if imgRefAndAuth.Tag() == "" && !options.forceYes { 47 deleteRemote, err := command.PromptForConfirmation(ctx, dockerCLI.In(), dockerCLI.Out(), fmt.Sprintf("Please confirm you would like to delete all signature data for %s?", remote)) 48 if err != nil { 49 return err 50 } 51 if !deleteRemote { 52 return errdefs.Cancelled(errors.New("trust revoke has been cancelled")) 53 } 54 } 55 56 notaryRepo, err := dockerCLI.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull) 57 if err != nil { 58 return err 59 } 60 61 if err = clearChangeList(notaryRepo); err != nil { 62 return err 63 } 64 defer clearChangeList(notaryRepo) 65 if err := revokeSignature(notaryRepo, tag); err != nil { 66 return errors.Wrapf(err, "could not remove signature for %s", remote) 67 } 68 fmt.Fprintf(dockerCLI.Out(), "Successfully deleted signature for %s\n", remote) 69 return nil 70 } 71 72 func revokeSignature(notaryRepo client.Repository, tag string) error { 73 if tag != "" { 74 // Revoke signature for the specified tag 75 if err := revokeSingleSig(notaryRepo, tag); err != nil { 76 return err 77 } 78 } else { 79 // revoke all signatures for the image, as no tag was given 80 if err := revokeAllSigs(notaryRepo); err != nil { 81 return err 82 } 83 } 84 85 // Publish change 86 return notaryRepo.Publish() 87 } 88 89 func revokeSingleSig(notaryRepo client.Repository, tag string) error { 90 releasedTargetWithRole, err := notaryRepo.GetTargetByName(tag, trust.ReleasesRole, data.CanonicalTargetsRole) 91 if err != nil { 92 return err 93 } 94 releasedTarget := releasedTargetWithRole.Target 95 return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo) 96 } 97 98 func revokeAllSigs(notaryRepo client.Repository) error { 99 releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole) 100 if err != nil { 101 return err 102 } 103 104 if len(releasedTargetWithRoleList) == 0 { 105 return fmt.Errorf("no signed tags to remove") 106 } 107 108 // we need all the roles that signed each released target so we can remove from all roles. 109 for _, releasedTargetWithRole := range releasedTargetWithRoleList { 110 // remove from all roles 111 if err := getSignableRolesForTargetAndRemove(releasedTargetWithRole.Target, notaryRepo); err != nil { 112 return err 113 } 114 } 115 return nil 116 } 117 118 // get all the roles that signed the target and removes it from all roles. 119 func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo client.Repository) error { 120 signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget) 121 if err != nil { 122 return err 123 } 124 // remove from all roles 125 return notaryRepo.RemoveTarget(releasedTarget.Name, signableRoles...) 126 }