diff --git a/cli/command/trust/sign.go b/cli/command/trust/sign.go index e67373659a..0d471fdfda 100644 --- a/cli/command/trust/sign.go +++ b/cli/command/trust/sign.go @@ -18,19 +18,29 @@ import ( "github.com/spf13/cobra" ) +type signOptions struct { + local bool + imageName string +} + func newSignCommand(dockerCli command.Cli) *cobra.Command { + options := signOptions{} cmd := &cobra.Command{ Use: "sign IMAGE:TAG", Short: "Sign an image", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return runSignImage(dockerCli, args[0]) + options.imageName = args[0] + return runSignImage(dockerCli, options) }, } + flags := cmd.Flags() + flags.BoolVar(&options.local, "local", false, "Sign a locally tagged image") return cmd } -func runSignImage(cli command.Cli, imageName string) error { +func runSignImage(cli command.Cli, options signOptions) error { + imageName := options.imageName ctx := context.Background() imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName) if err != nil { @@ -71,13 +81,15 @@ func runSignImage(cli command.Cli, imageName string) error { } requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "push") target, err := createTarget(notaryRepo, imgRefAndAuth.Tag()) - if err != nil { + if err != nil || options.local { switch err := err.(type) { - case client.ErrNoSuchTarget, client.ErrRepositoryNotExist: + // If the error is nil then the local flag is set + case client.ErrNoSuchTarget, client.ErrRepositoryNotExist, nil: // Fail fast if the image doesn't exist locally if err := checkLocalImageExistence(ctx, cli, imageName); err != nil { return err } + fmt.Fprintf(cli.Err(), "Signing and pushing trust data for local image %s, may overwrite remote trust data\n", imageName) return image.TrustedPush(ctx, cli, imgRefAndAuth.RepoInfo(), imgRefAndAuth.Reference(), *imgRefAndAuth.AuthConfig(), requestPrivilege) default: return err diff --git a/cli/command/trust/sign_test.go b/cli/command/trust/sign_test.go index ec9a5dc59f..ccaaa7ff37 100644 --- a/cli/command/trust/sign_test.go +++ b/cli/command/trust/sign_test.go @@ -295,3 +295,13 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) { require.NoError(t, err) assert.Equal(t, len(cl.List()), 0) } + +func TestSignCommandLocalFlag(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{}) + cli.SetNotaryClient(getEmptyTargetsNotaryRepository) + cmd := newSignCommand(cli) + cmd.SetArgs([]string{"--local", "reg-name.io/image:red"}) + cmd.SetOutput(ioutil.Discard) + testutil.ErrorContains(t, cmd.Execute(), "error during connect: Get /images/reg-name.io/image:red/json: unsupported protocol scheme") + +} diff --git a/docs/reference/commandline/trust_sign.md b/docs/reference/commandline/trust_sign.md index d3f22fdc12..15567fdbbd 100644 --- a/docs/reference/commandline/trust_sign.md +++ b/docs/reference/commandline/trust_sign.md @@ -16,10 +16,14 @@ keywords: "sign, notary, trust" # trust sign ```markdown -Usage: docker trust sign IMAGE:TAG +Usage: docker trust sign [OPTIONS] IMAGE:TAG Sign an image +Options: + --help print usage + --local force the signing of a local image + ``` ## Description