diff --git a/cli/command/cli.go b/cli/command/cli.go index 2fc1e7cccb..68ac0e6c91 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -52,20 +52,20 @@ type Cli interface { DefaultVersion() string ManifestStore() manifeststore.Store RegistryClient(bool) registryclient.RegistryClient - IsTrusted() bool + ContentTrustEnabled() bool } // DockerCli is an instance the docker command line client. // Instances of the client can be returned from NewDockerCli. type DockerCli struct { - configFile *configfile.ConfigFile - in *InStream - out *OutStream - err io.Writer - client client.APIClient - serverInfo ServerInfo - clientInfo ClientInfo - isTrusted bool + configFile *configfile.ConfigFile + in *InStream + out *OutStream + err io.Writer + client client.APIClient + serverInfo ServerInfo + clientInfo ClientInfo + contentTrust bool } // DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified. @@ -123,9 +123,10 @@ func (cli *DockerCli) ClientInfo() ClientInfo { return cli.clientInfo } -// IsTrusted returns if content trust is enabled for the cli -func (cli *DockerCli) IsTrusted() bool { - return cli.isTrusted +// ContentTrustEnabled returns if content trust has been enabled by an +// environment variable. +func (cli *DockerCli) ContentTrustEnabled() bool { + return cli.contentTrust } // ManifestStore returns a store for local manifests @@ -245,7 +246,7 @@ func (c ClientInfo) HasKubernetes() bool { // NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool) *DockerCli { - return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, isTrusted: isTrusted} + return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, contentTrust: isTrusted} } // NewAPIClientFromFlags creates a new APIClient from command line flags diff --git a/cli/command/container/create.go b/cli/command/container/create.go index 1358372ac9..7fe4c8f260 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -54,7 +54,7 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command { flags.Bool("help", false, "Print usage") command.AddPlatformFlag(flags, &opts.platform) - command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted()) + command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) copts = addFlags(flags) return cmd } @@ -159,7 +159,6 @@ func newCIDFile(path string) (*cidFile, error) { return &cidFile{path: path, file: f}, nil } -// nolint: gocyclo func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.ContainerCreateCreatedBody, error) { config := containerConfig.Config hostConfig := containerConfig.HostConfig @@ -184,8 +183,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig if named, ok := ref.(reference.Named); ok { namedRef = reference.TagNameOnly(named) - isContentTrustEnabled := !opts.untrusted && dockerCli.IsTrusted() - if taggedRef, ok := namedRef.(reference.NamedTagged); ok && isContentTrustEnabled { + if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted { var err error trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil) if err != nil { diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 1df75b50bc..b786b1f0cc 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -108,8 +108,9 @@ func TestCreateContainerPullsImageIfMissing(t *testing.T) { HostConfig: &container.HostConfig{}, } body, err := createContainer(context.Background(), cli, config, &createOptions{ - name: "name", - platform: runtime.GOOS, + name: "name", + platform: runtime.GOOS, + untrusted: true, }) assert.NilError(t, err) expected := container.ContainerCreateCreatedBody{ID: containerID} diff --git a/cli/command/container/run.go b/cli/command/container/run.go index 1a1a98515e..10b7ab8d9a 100644 --- a/cli/command/container/run.go +++ b/cli/command/container/run.go @@ -63,7 +63,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command { flags.Bool("help", false, "Print usage") command.AddPlatformFlag(flags, &opts.platform) - command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted()) + command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) copts = addFlags(flags) return cmd } diff --git a/cli/command/image/build.go b/cli/command/image/build.go index c812009970..15da4d4318 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -138,7 +138,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command { flags.StringVar(&options.target, "target", "", "Set the target build stage to build.") flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file") - command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.IsTrusted()) + command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled()) command.AddPlatformFlag(flags, &options.platform) flags.BoolVar(&options.squash, "squash", false, "Squash newly built layers into a single new layer") @@ -286,8 +286,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error { defer cancel() var resolvedTags []*resolvedTag - isContentTrustEnabled := !options.untrusted && dockerCli.IsTrusted() - if isContentTrustEnabled { + if !options.untrusted { translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) { return TrustedReference(ctx, dockerCli, ref, nil) } @@ -295,10 +294,10 @@ func runBuild(dockerCli command.Cli, options buildOptions) error { if buildCtx != nil { // Wrap the tar archive to replace the Dockerfile entry with the rewritten // Dockerfile which uses trusted pulls. - buildCtx = replaceDockerfileTarWrapper(ctx, buildCtx, relDockerfile, translator, &resolvedTags, isContentTrustEnabled) + buildCtx = replaceDockerfileForContentTrust(ctx, buildCtx, relDockerfile, translator, &resolvedTags) } else if dockerfileCtx != nil { // if there was not archive context still do the possible replacements in Dockerfile - newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator, isContentTrustEnabled) + newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator, !options.untrusted) if err != nil { return err } @@ -462,7 +461,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error { return err } } - if !options.untrusted && dockerCli.IsTrusted() { + if !options.untrusted { // Since the build was successful, now we must tag any of the resolved // images from the above Dockerfile rewrite. for _, resolved := range resolvedTags { @@ -545,11 +544,10 @@ func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator return buf.Bytes(), resolvedTags, scanner.Err() } -// replaceDockerfileTarWrapper wraps the given input tar archive stream and -// replaces the entry with the given Dockerfile name with the contents of the -// new Dockerfile. Returns a new tar archive stream with the replaced -// Dockerfile. -func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag, istrusted bool) io.ReadCloser { +// replaceDockerfileForContentTrust wraps the given input tar archive stream and +// uses the translator to replace the Dockerfile which uses a trusted reference. +// Returns a new tar archive stream with the replaced Dockerfile. +func replaceDockerfileForContentTrust(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser { pipeReader, pipeWriter := io.Pipe() go func() { tarReader := tar.NewReader(inputTarStream) @@ -576,7 +574,7 @@ func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadClos // generated from a directory on the local filesystem, the // Dockerfile will only appear once in the archive. var newDockerfile []byte - newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator, istrusted) + newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator, true) if err != nil { pipeWriter.CloseWithError(err) return diff --git a/cli/command/image/build_test.go b/cli/command/image/build_test.go index 83a3b61610..fb370f99f5 100644 --- a/cli/command/image/build_test.go +++ b/cli/command/image/build_test.go @@ -107,6 +107,7 @@ COPY data /data options := newBuildOptions() options.context = dir.Path() options.dockerfileName = df.Path() + options.untrusted = true err = runBuild(cli, options) assert.NilError(t, err) diff --git a/cli/command/image/pull.go b/cli/command/image/pull.go index e0723151a6..4f6d4f830d 100644 --- a/cli/command/image/pull.go +++ b/cli/command/image/pull.go @@ -39,7 +39,7 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command { flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository") command.AddPlatformFlag(flags, &opts.platform) - command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted()) + command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) return cmd } @@ -66,7 +66,7 @@ func runPull(cli command.Cli, opts pullOptions) error { // Check if reference has a digest _, isCanonical := distributionRef.(reference.Canonical) - if !opts.untrusted && cli.IsTrusted() && !isCanonical { + if !opts.untrusted && !isCanonical { err = trustedPull(ctx, cli, imgRefAndAuth, opts.platform) } else { err = imagePullPrivileged(ctx, cli, imgRefAndAuth, opts.all, opts.platform) diff --git a/cli/command/image/pull_test.go b/cli/command/image/pull_test.go index 551a296479..6ccbb91a05 100644 --- a/cli/command/image/pull_test.go +++ b/cli/command/image/pull_test.go @@ -110,7 +110,7 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) { imagePullFunc: func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) { return ioutil.NopCloser(strings.NewReader("")), fmt.Errorf("shouldn't try to pull image") }, - }, test.IsTrusted) + }, test.EnableContentTrust) cli.SetNotaryClient(tc.notaryFunc) cmd := NewPullCommand(cli) cmd.SetOutput(ioutil.Discard) diff --git a/cli/command/image/push.go b/cli/command/image/push.go index 2760e047a1..61e1b09d62 100644 --- a/cli/command/image/push.go +++ b/cli/command/image/push.go @@ -32,7 +32,7 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() - command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.IsTrusted()) + command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) return cmd } @@ -55,7 +55,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error { authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push") - if !opts.untrusted && dockerCli.IsTrusted() { + if !opts.untrusted { return TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege) } diff --git a/cli/command/plugin/install.go b/cli/command/plugin/install.go index 20119edef3..40be773bc3 100644 --- a/cli/command/plugin/install.go +++ b/cli/command/plugin/install.go @@ -29,7 +29,7 @@ type pluginOptions struct { 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.IsTrusted()) + command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) } func newInstallCommand(dockerCli command.Cli) *cobra.Command { @@ -91,7 +91,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti remote := ref.String() _, isCanonical := ref.(reference.Canonical) - if !opts.untrusted && dockerCli.IsTrusted() && !isCanonical { + if !opts.untrusted && !isCanonical { ref = reference.TagNameOnly(ref) nt, ok := ref.(reference.NamedTagged) if !ok { diff --git a/cli/command/plugin/push.go b/cli/command/plugin/push.go index 8e6872fd30..5dd039f8bf 100644 --- a/cli/command/plugin/push.go +++ b/cli/command/plugin/push.go @@ -32,7 +32,7 @@ func newPushCommand(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() - command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.IsTrusted()) + command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled()) return cmd } @@ -67,7 +67,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error { } defer responseBody.Close() - if !opts.untrusted && dockerCli.IsTrusted() { + if !opts.untrusted { repoInfo.Class = "plugin" return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody) } diff --git a/cli/command/service/trust.go b/cli/command/service/trust.go index c82d718730..c304a99124 100644 --- a/cli/command/service/trust.go +++ b/cli/command/service/trust.go @@ -16,7 +16,7 @@ import ( ) func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm.ServiceSpec) error { - if !dockerCli.IsTrusted() { + if !dockerCli.ContentTrustEnabled() { // When not using content trust, digest resolution happens later when // contacting the registry to retrieve image information. return nil diff --git a/internal/test/cli.go b/internal/test/cli.go index 352a0cb7df..17fab645ea 100644 --- a/internal/test/cli.go +++ b/internal/test/cli.go @@ -34,7 +34,7 @@ type FakeCli struct { notaryClientFunc NotaryClientFuncType manifestStore manifeststore.Store registryClient registryclient.RegistryClient - isTrusted bool + contentTrust bool } // NewFakeCli returns a fake for the command.Cli interface @@ -158,12 +158,12 @@ func (c *FakeCli) SetRegistryClient(client registryclient.RegistryClient) { c.registryClient = client } -// IsTrusted on the fake cli -func (c *FakeCli) IsTrusted() bool { - return c.isTrusted +// ContentTrustEnabled on the fake cli +func (c *FakeCli) ContentTrustEnabled() bool { + return c.contentTrust } -// IsTrusted sets "enables" content trust on the fake cli -func IsTrusted(c *FakeCli) { - c.isTrusted = true +// EnableContentTrust on the fake cli +func EnableContentTrust(c *FakeCli) { + c.contentTrust = true }