github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/cli/command/trust/revoke.go (about) 1 package trust 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 8 "github.com/docker/cli/cli" 9 "github.com/docker/cli/cli/command" 10 "github.com/docker/cli/cli/command/image" 11 "github.com/docker/cli/cli/trust" 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 := command.PromptForConfirmation(os.Stdin, dockerCLI.Out(), fmt.Sprintf("Please confirm you would like to delete all signature data for %s?", remote)) 48 if !deleteRemote { 49 fmt.Fprintf(dockerCLI.Out(), "\nAborting action.\n") 50 return nil 51 } 52 } 53 54 notaryRepo, err := dockerCLI.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull) 55 if err != nil { 56 return err 57 } 58 59 if err = clearChangeList(notaryRepo); err != nil { 60 return err 61 } 62 defer clearChangeList(notaryRepo) 63 if err := revokeSignature(notaryRepo, tag); err != nil { 64 return errors.Wrapf(err, "could not remove signature for %s", remote) 65 } 66 fmt.Fprintf(dockerCLI.Out(), "Successfully deleted signature for %s\n", remote) 67 return nil 68 } 69 70 func revokeSignature(notaryRepo client.Repository, tag string) error { 71 if tag != "" { 72 // Revoke signature for the specified tag 73 if err := revokeSingleSig(notaryRepo, tag); err != nil { 74 return err 75 } 76 } else { 77 // revoke all signatures for the image, as no tag was given 78 if err := revokeAllSigs(notaryRepo); err != nil { 79 return err 80 } 81 } 82 83 // Publish change 84 return notaryRepo.Publish() 85 } 86 87 func revokeSingleSig(notaryRepo client.Repository, tag string) error { 88 releasedTargetWithRole, err := notaryRepo.GetTargetByName(tag, trust.ReleasesRole, data.CanonicalTargetsRole) 89 if err != nil { 90 return err 91 } 92 releasedTarget := releasedTargetWithRole.Target 93 return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo) 94 } 95 96 func revokeAllSigs(notaryRepo client.Repository) error { 97 releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole) 98 if err != nil { 99 return err 100 } 101 102 if len(releasedTargetWithRoleList) == 0 { 103 return fmt.Errorf("no signed tags to remove") 104 } 105 106 // we need all the roles that signed each released target so we can remove from all roles. 107 for _, releasedTargetWithRole := range releasedTargetWithRoleList { 108 // remove from all roles 109 if err := getSignableRolesForTargetAndRemove(releasedTargetWithRole.Target, notaryRepo); err != nil { 110 return err 111 } 112 } 113 return nil 114 } 115 116 // get all the roles that signed the target and removes it from all roles. 117 func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo client.Repository) error { 118 signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget) 119 if err != nil { 120 return err 121 } 122 // remove from all roles 123 return notaryRepo.RemoveTarget(releasedTarget.Name, signableRoles...) 124 }