diff --git a/cli/command/plugin/install.go b/cli/command/plugin/install.go index b660ece33..9cb93b3b2 100644 --- a/cli/command/plugin/install.go +++ b/cli/command/plugin/install.go @@ -8,7 +8,6 @@ import ( "github.com/distribution/reference" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" "github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/internal/prompt" "github.com/docker/cli/internal/registry" @@ -17,7 +16,6 @@ import ( "github.com/moby/moby/client" "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) type pluginOptions struct { @@ -27,12 +25,6 @@ type pluginOptions struct { disable bool args []string skipRemoteCheck bool - untrusted bool -} - -func loadPullFlags(dockerCli command.Cli, opts *pluginOptions, flags *pflag.FlagSet) { - flags.BoolVar(&opts.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin") - command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) } func newInstallCommand(dockerCli command.Cli) *cobra.Command { @@ -51,13 +43,15 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command { } flags := cmd.Flags() - loadPullFlags(dockerCli, &options, flags) + flags.BoolVar(&options.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin") flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install") flags.StringVar(&options.localName, "alias", "", "Local name for plugin") + flags.Bool("disable-content-trust", dockerCli.ContentTrustEnabled(), "Skip image verification (deprecated)") + _ = flags.MarkHidden("disable-content-trust") return cmd } -func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOptions) (client.PluginInstallOptions, error) { +func buildPullConfig(dockerCLI command.Cli, opts pluginOptions) (client.PluginInstallOptions, error) { // Names with both tag and digest will be treated by the daemon // as a pull by digest with a local name for the tag // (if no local name is provided). @@ -66,40 +60,21 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti return client.PluginInstallOptions{}, err } - indexInfo := registry.NewIndexInfo(ref) - remote := ref.String() - - _, isCanonical := ref.(reference.Canonical) - if !opts.untrusted && !isCanonical { - ref = reference.TagNameOnly(ref) - nt, ok := ref.(reference.NamedTagged) - if !ok { - return client.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String()) - } - - trusted, err := image.TrustedReference(ctx, dockerCli, nt) - if err != nil { - return client.PluginInstallOptions{}, err - } - remote = reference.FamiliarString(trusted) - } - - authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo) + authConfig := command.ResolveAuthConfig(dockerCLI.ConfigFile(), registry.NewIndexInfo(ref)) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return client.PluginInstallOptions{}, err } - options := client.PluginInstallOptions{ + return client.PluginInstallOptions{ RegistryAuth: encodedAuth, - RemoteRef: remote, + RemoteRef: ref.String(), Disabled: opts.disable, AcceptAllPermissions: opts.grantPerms, - AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote), + AcceptPermissionsFunc: acceptPrivileges(dockerCLI, opts.remote), PrivilegeFunc: nil, Args: opts.args, - } - return options, nil + }, nil } func runInstall(ctx context.Context, dockerCLI command.Cli, opts pluginOptions) error { @@ -115,7 +90,7 @@ func runInstall(ctx context.Context, dockerCLI command.Cli, opts pluginOptions) localName = reference.FamiliarString(reference.TagNameOnly(aref)) } - options, err := buildPullConfig(ctx, dockerCLI, opts) + options, err := buildPullConfig(dockerCLI, opts) if err != nil { return err } diff --git a/cli/command/plugin/install_test.go b/cli/command/plugin/install_test.go index 52a7e14d4..697c00bc6 100644 --- a/cli/command/plugin/install_test.go +++ b/cli/command/plugin/install_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/notary" "github.com/moby/moby/client" "gotest.tools/v3/assert" @@ -65,50 +64,6 @@ func TestInstallErrors(t *testing.T) { } } -func TestInstallContentTrustErrors(t *testing.T) { - testCases := []struct { - description string - args []string - expectedError string - notaryFunc test.NotaryClientFuncType - }{ - { - description: "install plugin, offline notary server", - args: []string{"plugin:tag"}, - expectedError: "client is offline", - notaryFunc: notary.GetOfflineNotaryRepository, - }, - { - description: "install plugin, uninitialized notary server", - args: []string{"plugin:tag"}, - expectedError: "remote trust data does not exist", - notaryFunc: notary.GetUninitializedNotaryRepository, - }, - { - description: "install plugin, empty notary server", - args: []string{"plugin:tag"}, - expectedError: "No valid trust data for tag", - notaryFunc: notary.GetEmptyTargetsNotaryRepository, - }, - } - - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - pluginInstallFunc: func(name string, options client.PluginInstallOptions) (io.ReadCloser, error) { - return nil, errors.New("should not try to install plugin") - }, - }, test.EnableContentTrust) - cli.SetNotaryClient(tc.notaryFunc) - cmd := newInstallCommand(cli) - cmd.SetArgs(tc.args) - cmd.SetOut(io.Discard) - cmd.SetErr(io.Discard) - assert.ErrorContains(t, cmd.Execute(), tc.expectedError) - }) - } -} - func TestInstall(t *testing.T) { testCases := []struct { description string diff --git a/cli/command/plugin/push.go b/cli/command/plugin/push.go index 5962ea2f3..37bf997f6 100644 --- a/cli/command/plugin/push.go +++ b/cli/command/plugin/push.go @@ -2,55 +2,45 @@ package plugin import ( "context" + "fmt" "github.com/distribution/reference" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/trust" "github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/internal/registry" registrytypes "github.com/moby/moby/api/types/registry" - "github.com/pkg/errors" "github.com/spf13/cobra" ) -type pushOptions struct { - name string - untrusted bool -} - -func newPushCommand(dockerCli command.Cli) *cobra.Command { - var opts pushOptions +func newPushCommand(dockerCLI command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "push [OPTIONS] PLUGIN[:TAG]", Short: "Push a plugin to a registry", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.name = args[0] - return runPush(cmd.Context(), dockerCli, opts) + name := args[0] + return runPush(cmd.Context(), dockerCLI, name) }, } flags := cmd.Flags() - - command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) - + flags.Bool("disable-content-trust", dockerCLI.ContentTrustEnabled(), "Skip image verification (deprecated)") + _ = flags.MarkHidden("disable-content-trust") return cmd } -func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error { - named, err := reference.ParseNormalizedNamed(opts.name) +func runPush(ctx context.Context, dockerCli command.Cli, name string) error { + named, err := reference.ParseNormalizedNamed(name) if err != nil { return err } if _, ok := named.(reference.Canonical); ok { - return errors.Errorf("invalid name: %s", opts.name) + return fmt.Errorf("invalid name: %s", name) } named = reference.TagNameOnly(named) - - indexInfo := registry.NewIndexInfo(named) - authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo) + authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), registry.NewIndexInfo(named)) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return err @@ -63,14 +53,5 @@ func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error defer func() { _ = responseBody.Close() }() - - if !opts.untrusted { - repoInfo := &trust.RepositoryInfo{ - Name: reference.TrimNamed(named), - Index: indexInfo, - } - return trust.PushTrustedReference(ctx, dockerCli, repoInfo, named, authConfig, responseBody, command.UserAgent()) - } - return jsonstream.Display(ctx, responseBody, dockerCli.Out()) } diff --git a/cli/command/plugin/upgrade.go b/cli/command/plugin/upgrade.go index 7d4548d42..0e7ca9aca 100644 --- a/cli/command/plugin/upgrade.go +++ b/cli/command/plugin/upgrade.go @@ -31,7 +31,9 @@ func newUpgradeCommand(dockerCli command.Cli) *cobra.Command { } flags := cmd.Flags() - loadPullFlags(dockerCli, &options, flags) + flags.BoolVar(&options.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin") + flags.Bool("disable-content-trust", dockerCli.ContentTrustEnabled(), "Skip image verification (deprecated)") + _ = flags.MarkHidden("disable-content-trust") flags.BoolVar(&options.skipRemoteCheck, "skip-remote-check", false, "Do not check if specified remote plugin matches existing plugin image") return cmd } @@ -73,7 +75,7 @@ func runUpgrade(ctx context.Context, dockerCLI command.Cli, opts pluginOptions) } } - options, err := buildPullConfig(ctx, dockerCLI, opts) + options, err := buildPullConfig(dockerCLI, opts) if err != nil { return err } diff --git a/docs/reference/commandline/plugin_install.md b/docs/reference/commandline/plugin_install.md index 25ceb35c2..38b619b51 100644 --- a/docs/reference/commandline/plugin_install.md +++ b/docs/reference/commandline/plugin_install.md @@ -9,7 +9,6 @@ Install a plugin |:--------------------------|:---------|:--------|:--------------------------------------------------| | `--alias` | `string` | | Local name for plugin | | `--disable` | `bool` | | Do not enable the plugin on install | -| `--disable-content-trust` | `bool` | `true` | Skip image verification | | `--grant-all-permissions` | `bool` | | Grant all permissions necessary to run the plugin | diff --git a/docs/reference/commandline/plugin_push.md b/docs/reference/commandline/plugin_push.md index 3fcfe47f6..155d2d44d 100644 --- a/docs/reference/commandline/plugin_push.md +++ b/docs/reference/commandline/plugin_push.md @@ -3,12 +3,6 @@ Push a plugin to a registry -### Options - -| Name | Type | Default | Description | -|:--------------------------|:-------|:--------|:-------------------| -| `--disable-content-trust` | `bool` | `true` | Skip image signing | - diff --git a/docs/reference/commandline/plugin_upgrade.md b/docs/reference/commandline/plugin_upgrade.md index 39730104d..df4094875 100644 --- a/docs/reference/commandline/plugin_upgrade.md +++ b/docs/reference/commandline/plugin_upgrade.md @@ -7,7 +7,6 @@ Upgrade an existing plugin | Name | Type | Default | Description | |:--------------------------|:-------|:--------|:----------------------------------------------------------------------| -| `--disable-content-trust` | `bool` | `true` | Skip image verification | | `--grant-all-permissions` | `bool` | | Grant all permissions necessary to run the plugin | | `--skip-remote-check` | `bool` | | Do not check if specified remote plugin matches existing plugin image | diff --git a/e2e/plugin/trust_test.go b/e2e/plugin/plugin_test.go similarity index 59% rename from e2e/plugin/trust_test.go rename to e2e/plugin/plugin_test.go index 663c274ce..bcf61392b 100644 --- a/e2e/plugin/trust_test.go +++ b/e2e/plugin/plugin_test.go @@ -2,26 +2,24 @@ package plugin import ( "context" + "fmt" "testing" "github.com/docker/cli/e2e/internal/fixtures" "github.com/docker/cli/e2e/testutils" "github.com/docker/cli/internal/test/environment" - "github.com/moby/moby/api/types/versions" "gotest.tools/v3/icmd" "gotest.tools/v3/skip" ) const registryPrefix = "registry:5000" -func TestInstallWithContentTrust(t *testing.T) { - // TODO(krissetto): remove this skip once the fix (see https://github.com/moby/moby/pull/47299) is deployed to moby versions < 25 - skip.If(t, versions.LessThan(environment.DaemonAPIVersion(t), "1.44")) +func TestCreatePushPull(t *testing.T) { skip.If(t, environment.SkipPluginTests()) - t.Skip("flaky") - const pluginName = registryPrefix + "/plugin-content-trust" + const pluginName = registryPrefix + "/my-plugin" + // TODO(thaJeztah): probably should use a config without the content trust bits. dir := fixtures.SetupConfigFile(t) defer dir.Remove() @@ -33,39 +31,28 @@ func TestInstallWithContentTrust(t *testing.T) { icmd.RunCommand("docker", "plugin", "create", pluginName, pluginDir).Assert(t, icmd.Success) result := icmd.RunCmd(icmd.Command("docker", "plugin", "push", pluginName), fixtures.WithConfig(dir.Path()), - fixtures.WithTrust, - fixtures.WithNotary, fixtures.WithPassphrase("foo", "bar"), ) result.Assert(t, icmd.Expected{ - Out: "Signing and pushing trust metadata", + Out: fmt.Sprintf("The push refers to repository [%s]", pluginName), }) icmd.RunCommand("docker", "plugin", "rm", "-f", pluginName).Assert(t, icmd.Success) result = icmd.RunCmd(icmd.Command("docker", "plugin", "install", "--grant-all-permissions", pluginName), fixtures.WithConfig(dir.Path()), - fixtures.WithTrust, - fixtures.WithNotary, ) result.Assert(t, icmd.Expected{ Out: "Installed plugin " + pluginName, }) } -func TestInstallWithContentTrustUntrusted(t *testing.T) { +func TestInstall(t *testing.T) { skip.If(t, environment.SkipPluginTests()) - dir := fixtures.SetupConfigFile(t) - defer dir.Remove() - - result := icmd.RunCmd(icmd.Command("docker", "plugin", "install", "--grant-all-permissions", "tiborvass/sample-volume-plugin:latest"), - fixtures.WithConfig(dir.Path()), - fixtures.WithTrust, - fixtures.WithNotary, - ) + const pluginName = "tiborvass/sample-volume-plugin:latest" + result := icmd.RunCmd(icmd.Command("docker", "plugin", "install", "--grant-all-permissions", pluginName)) result.Assert(t, icmd.Expected{ - ExitCode: 1, - Err: "Error: remote trust data does not exist", + Out: "Installed plugin " + pluginName, }) }