cli/command/plugin: remove DCT
Plugins are not widely used, and there's no known plugins that use content-trust. We're working on updating the authentication stack in the CLI, and the trust implementation hinders us in making changes, so removing parts that are not high-priority (ahead of full deprecation of DCT). Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 |
|
||||
|
||||
|
||||
|
||||
@ -3,12 +3,6 @@
|
||||
<!---MARKER_GEN_START-->
|
||||
Push a plugin to a registry
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:-------|:--------|:-------------------|
|
||||
| `--disable-content-trust` | `bool` | `true` | Skip image signing |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@ -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 |
|
||||
|
||||
|
||||
@ -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,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user