mirror of https://github.com/docker/cli.git
Refactor content_trust cli/flags handling
Remove the global variable used. Allows easier unit testing. Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
82f325ed81
commit
6e21829af4
|
@ -52,6 +52,7 @@ type Cli interface {
|
|||
DefaultVersion() string
|
||||
ManifestStore() manifeststore.Store
|
||||
RegistryClient(bool) registryclient.RegistryClient
|
||||
IsTrusted() bool
|
||||
}
|
||||
|
||||
// DockerCli is an instance the docker command line client.
|
||||
|
@ -64,6 +65,7 @@ type DockerCli struct {
|
|||
client client.APIClient
|
||||
serverInfo ServerInfo
|
||||
clientInfo ClientInfo
|
||||
isTrusted bool
|
||||
}
|
||||
|
||||
// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified.
|
||||
|
@ -121,6 +123,11 @@ 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
|
||||
}
|
||||
|
||||
// ManifestStore returns a store for local manifests
|
||||
func (cli *DockerCli) ManifestStore() manifeststore.Store {
|
||||
// TODO: support override default location from config file
|
||||
|
@ -237,8 +244,8 @@ 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) *DockerCli {
|
||||
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: 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}
|
||||
}
|
||||
|
||||
// NewAPIClientFromFlags creates a new APIClient from command line flags
|
||||
|
|
|
@ -21,8 +21,9 @@ import (
|
|||
)
|
||||
|
||||
type createOptions struct {
|
||||
name string
|
||||
platform string
|
||||
name string
|
||||
platform string
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
// NewCreateCommand creates a new cobra.Command for `docker create`
|
||||
|
@ -53,7 +54,7 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
|
|||
flags.Bool("help", false, "Print usage")
|
||||
|
||||
command.AddPlatformFlag(flags, &opts.platform)
|
||||
command.AddTrustVerificationFlags(flags)
|
||||
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
copts = addFlags(flags)
|
||||
return cmd
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *createOptions,
|
|||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts.name, opts.platform)
|
||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -158,7 +159,8 @@ func newCIDFile(path string) (*cidFile, error) {
|
|||
return &cidFile{path: path, file: f}, nil
|
||||
}
|
||||
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, name string, platform string) (*container.ContainerCreateCreatedBody, error) {
|
||||
// nolint: gocyclo
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.ContainerCreateCreatedBody, error) {
|
||||
config := containerConfig.Config
|
||||
hostConfig := containerConfig.HostConfig
|
||||
networkingConfig := containerConfig.NetworkingConfig
|
||||
|
@ -182,7 +184,8 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
|||
if named, ok := ref.(reference.Named); ok {
|
||||
namedRef = reference.TagNameOnly(named)
|
||||
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && command.IsTrusted() {
|
||||
isContentTrustEnabled := !opts.untrusted && dockerCli.IsTrusted()
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && isContentTrustEnabled {
|
||||
var err error
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
|
||||
if err != nil {
|
||||
|
@ -193,7 +196,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
|||
}
|
||||
|
||||
//create the container
|
||||
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
|
||||
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
|
||||
|
||||
//if image not found try to pull it
|
||||
if err != nil {
|
||||
|
@ -201,7 +204,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
|||
fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", reference.FamiliarString(namedRef))
|
||||
|
||||
// we don't want to write to stdout anything apart from container.ID
|
||||
if err := pullImage(ctx, dockerCli, config.Image, platform, stderr); err != nil {
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, stderr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
|
||||
|
@ -211,7 +214,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
|||
}
|
||||
// Retry
|
||||
var retryErr error
|
||||
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
|
||||
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
|
||||
if retryErr != nil {
|
||||
return nil, retryErr
|
||||
}
|
||||
|
|
|
@ -107,7 +107,10 @@ func TestCreateContainerPullsImageIfMissing(t *testing.T) {
|
|||
},
|
||||
HostConfig: &container.HostConfig{},
|
||||
}
|
||||
body, err := createContainer(context.Background(), cli, config, "name", runtime.GOOS)
|
||||
body, err := createContainer(context.Background(), cli, config, &createOptions{
|
||||
name: "name",
|
||||
platform: runtime.GOOS,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
expected := container.ContainerCreateCreatedBody{ID: containerID}
|
||||
assert.Check(t, is.DeepEqual(expected, *body))
|
||||
|
|
|
@ -25,11 +25,10 @@ import (
|
|||
)
|
||||
|
||||
type runOptions struct {
|
||||
createOptions
|
||||
detach bool
|
||||
sigProxy bool
|
||||
name string
|
||||
detachKeys string
|
||||
platform string
|
||||
}
|
||||
|
||||
// NewRunCommand create a new `docker run` command
|
||||
|
@ -64,7 +63,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
|
|||
flags.Bool("help", false, "Print usage")
|
||||
|
||||
command.AddPlatformFlag(flags, &opts.platform)
|
||||
command.AddTrustVerificationFlags(flags)
|
||||
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
copts = addFlags(flags)
|
||||
return cmd
|
||||
}
|
||||
|
@ -162,7 +161,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
|
|||
|
||||
ctx, cancelFun := context.WithCancel(context.Background())
|
||||
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerConfig, opts.name, opts.platform)
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerConfig, &opts.createOptions)
|
||||
if err != nil {
|
||||
reportError(stderr, cmdPath, err.Error(), true)
|
||||
return runStartContainerErr(err)
|
||||
|
|
|
@ -67,6 +67,7 @@ type buildOptions struct {
|
|||
imageIDFile string
|
||||
stream bool
|
||||
platform string
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
// dockerfileFromStdin returns true when the user specified that the Dockerfile
|
||||
|
@ -137,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)
|
||||
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.IsTrusted())
|
||||
command.AddPlatformFlag(flags, &options.platform)
|
||||
|
||||
flags.BoolVar(&options.squash, "squash", false, "Squash newly built layers into a single new layer")
|
||||
|
@ -285,7 +286,8 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
|||
defer cancel()
|
||||
|
||||
var resolvedTags []*resolvedTag
|
||||
if command.IsTrusted() {
|
||||
isContentTrustEnabled := !options.untrusted && dockerCli.IsTrusted()
|
||||
if isContentTrustEnabled {
|
||||
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
return TrustedReference(ctx, dockerCli, ref, nil)
|
||||
}
|
||||
|
@ -293,10 +295,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)
|
||||
buildCtx = replaceDockerfileTarWrapper(ctx, buildCtx, relDockerfile, translator, &resolvedTags, isContentTrustEnabled)
|
||||
} else if dockerfileCtx != nil {
|
||||
// if there was not archive context still do the possible replacements in Dockerfile
|
||||
newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator)
|
||||
newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator, isContentTrustEnabled)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -460,7 +462,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if command.IsTrusted() {
|
||||
if !options.untrusted && dockerCli.IsTrusted() {
|
||||
// Since the build was successful, now we must tag any of the resolved
|
||||
// images from the above Dockerfile rewrite.
|
||||
for _, resolved := range resolvedTags {
|
||||
|
@ -503,7 +505,7 @@ type resolvedTag struct {
|
|||
// "FROM <image>" instructions to a digest reference. `translator` is a
|
||||
// function that takes a repository name and tag reference and returns a
|
||||
// trusted digest reference.
|
||||
func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
|
||||
func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator translatorFunc, istrusted bool) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
|
||||
scanner := bufio.NewScanner(dockerfile)
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
|
@ -520,7 +522,7 @@ func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator
|
|||
return nil, nil, err
|
||||
}
|
||||
ref = reference.TagNameOnly(ref)
|
||||
if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() {
|
||||
if ref, ok := ref.(reference.NamedTagged); ok && istrusted {
|
||||
trustedRef, err := translator(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -547,7 +549,7 @@ func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator
|
|||
// 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) io.ReadCloser {
|
||||
func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag, istrusted bool) io.ReadCloser {
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
go func() {
|
||||
tarReader := tar.NewReader(inputTarStream)
|
||||
|
@ -574,7 +576,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)
|
||||
newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator, istrusted)
|
||||
if err != nil {
|
||||
pipeWriter.CloseWithError(err)
|
||||
return
|
||||
|
|
|
@ -14,9 +14,10 @@ import (
|
|||
)
|
||||
|
||||
type pullOptions struct {
|
||||
remote string
|
||||
all bool
|
||||
platform string
|
||||
remote string
|
||||
all bool
|
||||
platform string
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
// NewPullCommand creates a new `docker pull` command
|
||||
|
@ -38,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)
|
||||
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ func runPull(cli command.Cli, opts pullOptions) error {
|
|||
|
||||
// Check if reference has a digest
|
||||
_, isCanonical := distributionRef.(reference.Canonical)
|
||||
if command.IsTrusted() && !isCanonical {
|
||||
if !opts.untrusted && cli.IsTrusted() && !isCanonical {
|
||||
err = trustedPull(ctx, cli, imgRefAndAuth, opts.platform)
|
||||
} else {
|
||||
err = imagePullPrivileged(ctx, cli, imgRefAndAuth, opts.all, opts.platform)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
|
@ -77,3 +78,44 @@ func TestNewPullCommandSuccess(t *testing.T) {
|
|||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("pull-command-success.%s.golden", tc.name))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectedError string
|
||||
notaryFunc test.NotaryClientFuncType
|
||||
}{
|
||||
{
|
||||
name: "offline-notary-server",
|
||||
notaryFunc: notary.GetOfflineNotaryRepository,
|
||||
expectedError: "client is offline",
|
||||
args: []string{"image:tag"},
|
||||
},
|
||||
{
|
||||
name: "empty-notary-server",
|
||||
notaryFunc: notary.GetUninitializedNotaryRepository,
|
||||
expectedError: "remote trust data does not exist",
|
||||
args: []string{"image:tag"},
|
||||
},
|
||||
{
|
||||
name: "empty-notary-server",
|
||||
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
|
||||
expectedError: "No valid trust data for tag",
|
||||
args: []string{"image:tag"},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
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)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
cmd := NewPullCommand(cli)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.ErrorContains(t, err, tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,26 +11,34 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type pushOptions struct {
|
||||
remote string
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
// NewPushCommand creates a new `docker push` command
|
||||
func NewPushCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts pushOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "push [OPTIONS] NAME[:TAG]",
|
||||
Short: "Push an image or a repository to a registry",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPush(dockerCli, args[0])
|
||||
opts.remote = args[0]
|
||||
return runPush(dockerCli, opts)
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
command.AddTrustSigningFlags(flags)
|
||||
command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPush(dockerCli command.Cli, remote string) error {
|
||||
ref, err := reference.ParseNormalizedNamed(remote)
|
||||
func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
ref, err := reference.ParseNormalizedNamed(opts.remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -47,7 +55,7 @@ func runPush(dockerCli command.Cli, remote string) error {
|
|||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
|
||||
|
||||
if command.IsTrusted() {
|
||||
if !opts.untrusted && dockerCli.IsTrusted() {
|
||||
return TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,11 +37,6 @@ func TestNewPushCommandErrors(t *testing.T) {
|
|||
return ioutil.NopCloser(strings.NewReader("")), errors.Errorf("Failed to push")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "trust-error",
|
||||
args: []string{"--disable-content-trust=false", "image:repo"},
|
||||
expectedError: "you are not authorized to perform this operation: server returned 401.",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{imagePushFunc: tc.imagePushFunc})
|
||||
|
|
|
@ -24,11 +24,12 @@ type pluginOptions struct {
|
|||
disable bool
|
||||
args []string
|
||||
skipRemoteCheck bool
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
func loadPullFlags(opts *pluginOptions, flags *pflag.FlagSet) {
|
||||
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)
|
||||
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
}
|
||||
|
||||
func newInstallCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
@ -47,7 +48,7 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command {
|
|||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
loadPullFlags(&options, flags)
|
||||
loadPullFlags(dockerCli, &options, flags)
|
||||
flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install")
|
||||
flags.StringVar(&options.localName, "alias", "", "Local name for plugin")
|
||||
return cmd
|
||||
|
@ -90,7 +91,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
|||
remote := ref.String()
|
||||
|
||||
_, isCanonical := ref.(reference.Canonical)
|
||||
if command.IsTrusted() && !isCanonical {
|
||||
if !opts.untrusted && dockerCli.IsTrusted() && !isCanonical {
|
||||
ref = reference.TagNameOnly(ref)
|
||||
nt, ok := ref.(reference.NamedTagged)
|
||||
if !ok {
|
||||
|
|
|
@ -13,30 +13,37 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type pushOptions struct {
|
||||
name string
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
func newPushCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts pushOptions
|
||||
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 {
|
||||
return runPush(dockerCli, args[0])
|
||||
opts.name = args[0]
|
||||
return runPush(dockerCli, opts)
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
command.AddTrustSigningFlags(flags)
|
||||
command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.IsTrusted())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPush(dockerCli command.Cli, name string) error {
|
||||
named, err := reference.ParseNormalizedNamed(name)
|
||||
func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
named, err := reference.ParseNormalizedNamed(opts.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := named.(reference.Canonical); ok {
|
||||
return errors.Errorf("invalid name: %s", name)
|
||||
return errors.Errorf("invalid name: %s", opts.name)
|
||||
}
|
||||
|
||||
named = reference.TagNameOnly(named)
|
||||
|
@ -60,7 +67,7 @@ func runPush(dockerCli command.Cli, name string) error {
|
|||
}
|
||||
defer responseBody.Close()
|
||||
|
||||
if command.IsTrusted() {
|
||||
if !opts.untrusted && dockerCli.IsTrusted() {
|
||||
repoInfo.Class = "plugin"
|
||||
return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ func newUpgradeCommand(dockerCli command.Cli) *cobra.Command {
|
|||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
loadPullFlags(&options, flags)
|
||||
loadPullFlags(dockerCli, &options, flags)
|
||||
flags.BoolVar(&options.skipRemoteCheck, "skip-remote-check", false, "Do not check if specified remote plugin matches existing plugin image")
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm.ServiceSpec) error {
|
||||
if !command.IsTrusted() {
|
||||
if !dockerCli.IsTrusted() {
|
||||
// When not using content trust, digest resolution happens later when
|
||||
// contacting the registry to retrieve image information.
|
||||
return nil
|
||||
|
|
|
@ -1,47 +1,15 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO: make this not global
|
||||
untrusted bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
untrusted = !getDefaultTrustState()
|
||||
}
|
||||
|
||||
// AddTrustVerificationFlags adds content trust flags to the provided flagset
|
||||
func AddTrustVerificationFlags(fs *pflag.FlagSet) {
|
||||
trusted := getDefaultTrustState()
|
||||
fs.BoolVar(&untrusted, "disable-content-trust", !trusted, "Skip image verification")
|
||||
func AddTrustVerificationFlags(fs *pflag.FlagSet, v *bool, trusted bool) {
|
||||
fs.BoolVar(v, "disable-content-trust", !trusted, "Skip image verification")
|
||||
}
|
||||
|
||||
// AddTrustSigningFlags adds "signing" flags to the provided flagset
|
||||
func AddTrustSigningFlags(fs *pflag.FlagSet) {
|
||||
trusted := getDefaultTrustState()
|
||||
fs.BoolVar(&untrusted, "disable-content-trust", !trusted, "Skip image signing")
|
||||
}
|
||||
|
||||
// getDefaultTrustState returns true if content trust is enabled through the $DOCKER_CONTENT_TRUST environment variable.
|
||||
func getDefaultTrustState() bool {
|
||||
var trusted bool
|
||||
if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" {
|
||||
if t, err := strconv.ParseBool(e); t || err != nil {
|
||||
// treat any other value as true
|
||||
trusted = true
|
||||
}
|
||||
}
|
||||
return trusted
|
||||
}
|
||||
|
||||
// IsTrusted returns true if content trust is enabled, either through the $DOCKER_CONTENT_TRUST environment variable,
|
||||
// or through `--disabled-content-trust=false` on a command.
|
||||
func IsTrusted() bool {
|
||||
return !untrusted
|
||||
func AddTrustSigningFlags(fs *pflag.FlagSet, v *bool, trusted bool) {
|
||||
fs.BoolVar(v, "disable-content-trust", !trusted, "Skip image signing")
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
)
|
||||
|
@ -46,14 +47,14 @@ func TestTrustInspectCommandErrors(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandOfflineErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetOfflineNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"nonexistent-reg-name.io/image"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "No signatures or cannot access nonexistent-reg-name.io/image")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetOfflineNotaryRepository)
|
||||
cmd = newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"nonexistent-reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -62,7 +63,7 @@ func TestTrustInspectCommandOfflineErrors(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandUninitializedErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetUninitializedNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/unsigned-img"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -70,7 +71,7 @@ func TestTrustInspectCommandUninitializedErrors(t *testing.T) {
|
|||
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-uninitialized.golden")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetUninitializedNotaryRepository)
|
||||
cmd = newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/unsigned-img:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -80,7 +81,7 @@ func TestTrustInspectCommandUninitializedErrors(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandEmptyNotaryRepo(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/img:unsigned-tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -90,7 +91,7 @@ func TestTrustInspectCommandEmptyNotaryRepo(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandFullRepoWithoutSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetLoadedWithNoSignersNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -99,7 +100,7 @@ func TestTrustInspectCommandFullRepoWithoutSigners(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandOneTagWithoutSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetLoadedWithNoSignersNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo:green"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -108,7 +109,7 @@ func TestTrustInspectCommandOneTagWithoutSigners(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandFullRepoWithSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetLoadedNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -117,7 +118,7 @@ func TestTrustInspectCommandFullRepoWithSigners(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandMultipleFullReposWithSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetLoadedNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo", "signed-repo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -126,7 +127,7 @@ func TestTrustInspectCommandMultipleFullReposWithSigners(t *testing.T) {
|
|||
|
||||
func TestTrustInspectCommandUnsignedTagInSignedRepo(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetLoadedNotaryRepository)
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo:unsigned"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/theupdateframework/notary/client"
|
||||
|
@ -55,7 +56,7 @@ func TestTrustRevokeCommandErrors(t *testing.T) {
|
|||
|
||||
func TestTrustRevokeCommandOfflineErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetOfflineNotaryRepository)
|
||||
cmd := newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -63,13 +64,13 @@ func TestTrustRevokeCommandOfflineErrors(t *testing.T) {
|
|||
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action."))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetOfflineNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetOfflineNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -78,7 +79,7 @@ func TestTrustRevokeCommandOfflineErrors(t *testing.T) {
|
|||
|
||||
func TestTrustRevokeCommandUninitializedErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetUninitializedNotaryRepository)
|
||||
cmd := newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -86,14 +87,14 @@ func TestTrustRevokeCommandUninitializedErrors(t *testing.T) {
|
|||
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action."))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetUninitializedNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image: does not have trust data for")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetUninitializedNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -102,7 +103,7 @@ func TestTrustRevokeCommandUninitializedErrors(t *testing.T) {
|
|||
|
||||
func TestTrustRevokeCommandEmptyNotaryRepo(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -110,14 +111,14 @@ func TestTrustRevokeCommandEmptyNotaryRepo(t *testing.T) {
|
|||
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action."))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetEmptyTargetsNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image: no signed tags to remove")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetEmptyTargetsNotaryRepository)
|
||||
cmd = newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -126,7 +127,7 @@ func TestTrustRevokeCommandEmptyNotaryRepo(t *testing.T) {
|
|||
|
||||
func TestNewRevokeTrustAllSigConfirmation(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notary.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newRevokeCommand(cli)
|
||||
cmd.SetArgs([]string{"alpine"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/cli/internal/test"
|
||||
notaryfake "github.com/docker/cli/internal/test/notary"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
|
@ -76,7 +77,7 @@ func TestTrustSignCommandErrors(t *testing.T) {
|
|||
|
||||
func TestTrustSignCommandOfflineErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
cmd := newSignCommand(cli)
|
||||
cmd.SetArgs([]string{"reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -282,7 +283,7 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
|
|||
|
||||
config.SetDir(tmpDir)
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
cmd := newSignCommand(cli)
|
||||
cmd.SetArgs([]string{"ubuntu:latest"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -299,7 +300,7 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
|
|||
|
||||
func TestSignCommandLocalFlag(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newSignCommand(cli)
|
||||
cmd.SetArgs([]string{"--local", "reg-name.io/image:red"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/internal/test"
|
||||
notaryfake "github.com/docker/cli/internal/test/notary"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/theupdateframework/notary"
|
||||
|
@ -58,7 +59,7 @@ func TestTrustSignerAddErrors(t *testing.T) {
|
|||
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
cmd := newSignerAddCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -77,7 +78,7 @@ func TestSignerAddCommandNoTargetsKey(t *testing.T) {
|
|||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newSignerAddCommand(cli)
|
||||
cmd.SetArgs([]string{"--key", tmpfile.Name(), "alice", "alpine", "linuxkit/alpine"})
|
||||
|
||||
|
@ -92,7 +93,7 @@ func TestSignerAddCommandBadKeyPath(t *testing.T) {
|
|||
config.SetDir(tmpDir)
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newSignerAddCommand(cli)
|
||||
cmd.SetArgs([]string{"--key", "/path/to/key.pem", "alice", "alpine"})
|
||||
|
||||
|
@ -117,7 +118,7 @@ func TestSignerAddCommandInvalidRepoName(t *testing.T) {
|
|||
assert.NilError(t, ioutil.WriteFile(pubKeyFilepath, pubKeyFixture, notary.PrivNoExecPerms))
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetUninitializedNotaryRepository)
|
||||
cmd := newSignerAddCommand(cli)
|
||||
imageName := "870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"
|
||||
cmd.SetArgs([]string{"--key", pubKeyFilepath, "alice", imageName})
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
notaryfake "github.com/docker/cli/internal/test/notary"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/theupdateframework/notary/client"
|
||||
|
@ -57,7 +58,7 @@ func TestTrustSignerRemoveErrors(t *testing.T) {
|
|||
}
|
||||
for _, tc := range testCasesWithOutput {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
cmd := newSignerRemoveCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -69,7 +70,7 @@ func TestTrustSignerRemoveErrors(t *testing.T) {
|
|||
|
||||
func TestRemoveSingleSigner(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
err := removeSingleSigner(cli, "signed-repo", "test", true)
|
||||
assert.Error(t, err, "No signer test for repository signed-repo")
|
||||
err = removeSingleSigner(cli, "signed-repo", "releases", true)
|
||||
|
@ -78,7 +79,7 @@ func TestRemoveSingleSigner(t *testing.T) {
|
|||
|
||||
func TestRemoveMultipleSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
err := removeSigner(cli, signerRemoveOptions{signer: "test", repos: []string{"signed-repo", "signed-repo"}, forceYes: true})
|
||||
assert.Error(t, err, "Error removing signer from: signed-repo, signed-repo")
|
||||
assert.Check(t, is.Contains(cli.ErrBuffer().String(),
|
||||
|
@ -87,7 +88,7 @@ func TestRemoveMultipleSigners(t *testing.T) {
|
|||
}
|
||||
func TestRemoveLastSignerWarning(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
|
||||
err := removeSigner(cli, signerRemoveOptions{signer: "alice", repos: []string{"signed-repo"}, forceYes: false})
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/cli/internal/test"
|
||||
notaryfake "github.com/docker/cli/internal/test/notary"
|
||||
dockerClient "github.com/docker/docker/client"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
|
@ -57,14 +58,14 @@ func TestTrustViewCommandErrors(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandOfflineErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"nonexistent-reg-name.io/image"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "No signatures or cannot access nonexistent-reg-name.io/image")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getOfflineNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
cmd = newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"nonexistent-reg-name.io/image:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -73,14 +74,14 @@ func TestTrustViewCommandOfflineErrors(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandUninitializedErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetUninitializedNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/unsigned-img"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "No signatures or cannot access reg/unsigned-img")
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getUninitializedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetUninitializedNotaryRepository)
|
||||
cmd = newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/unsigned-img:tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -89,7 +90,7 @@ func TestTrustViewCommandUninitializedErrors(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandEmptyNotaryRepoErrors(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/img:unsigned-tag"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -98,7 +99,7 @@ func TestTrustViewCommandEmptyNotaryRepoErrors(t *testing.T) {
|
|||
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Administrative keys for reg/img:"))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
|
||||
cmd = newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"reg/img"})
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
|
@ -109,7 +110,7 @@ func TestTrustViewCommandEmptyNotaryRepoErrors(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandFullRepoWithoutSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedWithNoSignersNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -119,7 +120,7 @@ func TestTrustViewCommandFullRepoWithoutSigners(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandOneTagWithoutSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedWithNoSignersNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo:green"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -129,7 +130,7 @@ func TestTrustViewCommandOneTagWithoutSigners(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandFullRepoWithSigners(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
@ -139,7 +140,7 @@ func TestTrustViewCommandFullRepoWithSigners(t *testing.T) {
|
|||
|
||||
func TestTrustViewCommandUnsignedTagInSignedRepo(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||
cli.SetNotaryClient(notaryfake.GetLoadedNotaryRepository)
|
||||
cmd := newViewCommand(cli)
|
||||
cmd.SetArgs([]string{"signed-repo:unsigned"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
|
@ -155,7 +156,7 @@ func main() {
|
|||
stdin, stdout, stderr := term.StdStreams()
|
||||
logrus.SetOutput(stderr)
|
||||
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr, isContentTrustEnabled())
|
||||
cmd := newDockerCommand(dockerCli)
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
|
@ -175,6 +176,16 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func isContentTrustEnabled() bool {
|
||||
if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" {
|
||||
if t, err := strconv.ParseBool(e); t || err != nil {
|
||||
// treat any other value as true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func showVersion() {
|
||||
fmt.Printf("Docker version %s, build %s\n", cli.Version, cli.GitCommit)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestClientDebugEnabled(t *testing.T) {
|
|||
|
||||
func TestExitStatusForInvalidSubcommandWithHelpFlag(t *testing.T) {
|
||||
discard := ioutil.Discard
|
||||
cmd := newDockerCommand(command.NewDockerCli(os.Stdin, discard, discard))
|
||||
cmd := newDockerCommand(command.NewDockerCli(os.Stdin, discard, discard, false))
|
||||
cmd.SetArgs([]string{"help", "invalid"})
|
||||
err := cmd.Execute()
|
||||
assert.Error(t, err, "unknown help topic: invalid")
|
||||
|
|
|
@ -19,7 +19,7 @@ const descriptionSourcePath = "docs/reference/commandline/"
|
|||
|
||||
func generateCliYaml(opts *options) error {
|
||||
stdin, stdout, stderr := term.StdStreams()
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false)
|
||||
cmd := &cobra.Command{Use: "docker"}
|
||||
commands.AddCommands(cmd, dockerCli)
|
||||
source := filepath.Join(opts.source, descriptionSourcePath)
|
||||
|
|
|
@ -16,7 +16,8 @@ import (
|
|||
notaryclient "github.com/theupdateframework/notary/client"
|
||||
)
|
||||
|
||||
type notaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
||||
// NotaryClientFuncType defines a function that returns a fake notary client
|
||||
type NotaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
||||
type clientInfoFuncType func() command.ClientInfo
|
||||
|
||||
// FakeCli emulates the default DockerCli
|
||||
|
@ -30,16 +31,17 @@ type FakeCli struct {
|
|||
in *command.InStream
|
||||
server command.ServerInfo
|
||||
clientInfoFunc clientInfoFuncType
|
||||
notaryClientFunc notaryClientFuncType
|
||||
notaryClientFunc NotaryClientFuncType
|
||||
manifestStore manifeststore.Store
|
||||
registryClient registryclient.RegistryClient
|
||||
isTrusted bool
|
||||
}
|
||||
|
||||
// NewFakeCli returns a fake for the command.Cli interface
|
||||
func NewFakeCli(client client.APIClient) *FakeCli {
|
||||
func NewFakeCli(client client.APIClient, opts ...func(*FakeCli)) *FakeCli {
|
||||
outBuffer := new(bytes.Buffer)
|
||||
errBuffer := new(bytes.Buffer)
|
||||
return &FakeCli{
|
||||
c := &FakeCli{
|
||||
client: client,
|
||||
out: command.NewOutStream(outBuffer),
|
||||
outBuffer: outBuffer,
|
||||
|
@ -49,6 +51,10 @@ func NewFakeCli(client client.APIClient) *FakeCli {
|
|||
// Set cli.ConfigFile().Filename to a tempfile to support Save.
|
||||
configfile: configfile.New(""),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// SetIn sets the input of the cli to the specified ReadCloser
|
||||
|
@ -120,7 +126,7 @@ func (c *FakeCli) ErrBuffer() *bytes.Buffer {
|
|||
}
|
||||
|
||||
// SetNotaryClient sets the internal getter for retrieving a NotaryClient
|
||||
func (c *FakeCli) SetNotaryClient(notaryClientFunc notaryClientFuncType) {
|
||||
func (c *FakeCli) SetNotaryClient(notaryClientFunc NotaryClientFuncType) {
|
||||
c.notaryClientFunc = notaryClientFunc
|
||||
}
|
||||
|
||||
|
@ -151,3 +157,13 @@ func (c *FakeCli) SetManifestStore(store manifeststore.Store) {
|
|||
func (c *FakeCli) SetRegistryClient(client registryclient.RegistryClient) {
|
||||
c.registryClient = client
|
||||
}
|
||||
|
||||
// IsTrusted on the fake cli
|
||||
func (c *FakeCli) IsTrusted() bool {
|
||||
return c.isTrusted
|
||||
}
|
||||
|
||||
// IsTrusted sets "enables" content trust on the fake cli
|
||||
func IsTrusted(c *FakeCli) {
|
||||
c.isTrusted = true
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package trust
|
||||
package notary
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/cli/trust"
|
||||
|
@ -12,107 +12,142 @@ import (
|
|||
"github.com/theupdateframework/notary/tuf/signed"
|
||||
)
|
||||
|
||||
// Sample mock CLI interfaces
|
||||
|
||||
func getOfflineNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
// GetOfflineNotaryRepository returns a OfflineNotaryRepository
|
||||
func GetOfflineNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
return OfflineNotaryRepository{}, nil
|
||||
}
|
||||
|
||||
// OfflineNotaryRepository is a mock Notary repository that is offline
|
||||
type OfflineNotaryRepository struct{}
|
||||
|
||||
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||
// TUF repository.
|
||||
func (o OfflineNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
|
||||
return storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// InitializeWithCertificate initializes the repository with root keys and their corresponding certificates
|
||||
func (o OfflineNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
|
||||
return storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// Publish pushes the local changes in signed material to the remote notary-server
|
||||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
func (o OfflineNotaryRepository) Publish() error {
|
||||
return storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// AddTarget creates new changelist entries to add a target to the given roles
|
||||
// in the repository when the changelist gets applied at publish time.
|
||||
func (o OfflineNotaryRepository) AddTarget(target *client.Target, roles ...data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveTarget creates new changelist entries to remove a target from the given
|
||||
// roles in the repository when the changelist gets applied at publish time.
|
||||
func (o OfflineNotaryRepository) RemoveTarget(targetName string, roles ...data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
func (o OfflineNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
|
||||
return nil, storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name.
|
||||
func (o OfflineNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
|
||||
return nil, storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
func (o OfflineNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
|
||||
return nil, storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// GetChangelist returns the list of the repository's unpublished changes
|
||||
func (o OfflineNotaryRepository) GetChangelist() (changelist.Changelist, error) {
|
||||
return changelist.NewMemChangelist(), nil
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
func (o OfflineNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
|
||||
return nil, storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
func (o OfflineNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
|
||||
return nil, storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// AddDelegation creates changelist entries to add provided delegation public keys and paths.
|
||||
func (o OfflineNotaryRepository) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddDelegationRoleAndKeys creates a changelist entry to add provided delegation public keys.
|
||||
func (o OfflineNotaryRepository) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddDelegationPaths creates a changelist entry to add provided paths to an existing delegation.
|
||||
func (o OfflineNotaryRepository) AddDelegationPaths(name data.RoleName, paths []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and paths.
|
||||
func (o OfflineNotaryRepository) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDelegationRole creates a changelist to remove all paths and keys from a role, and delete the role in its entirety.
|
||||
func (o OfflineNotaryRepository) RemoveDelegationRole(name data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDelegationPaths creates a changelist entry to remove provided paths from an existing delegation.
|
||||
func (o OfflineNotaryRepository) RemoveDelegationPaths(name data.RoleName, paths []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDelegationKeys creates a changelist entry to remove provided keys from an existing delegation.
|
||||
func (o OfflineNotaryRepository) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearDelegationPaths creates a changelist entry to remove all paths from an existing delegation.
|
||||
func (o OfflineNotaryRepository) ClearDelegationPaths(name data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Witness creates change objects to witness (i.e. re-sign) the given
|
||||
// roles on the next publish. One change is created per role
|
||||
func (o OfflineNotaryRepository) Witness(roles ...data.RoleName) ([]data.RoleName, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// RotateKey rotates a private key and returns the public component from the remote server
|
||||
func (o OfflineNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
|
||||
return storage.ErrOffline{}
|
||||
}
|
||||
|
||||
// GetCryptoService is the getter for the repository's CryptoService
|
||||
func (o OfflineNotaryRepository) GetCryptoService() signed.CryptoService {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLegacyVersions allows the number of legacy versions of the root
|
||||
// to be inspected for old signing keys to be configured.
|
||||
func (o OfflineNotaryRepository) SetLegacyVersions(version int) {}
|
||||
|
||||
// GetGUN is a getter for the GUN object from a Repository
|
||||
func (o OfflineNotaryRepository) GetGUN() data.GUN {
|
||||
return data.GUN("gun")
|
||||
}
|
||||
|
||||
func getUninitializedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
// GetUninitializedNotaryRepository returns an UninitializedNotaryRepository
|
||||
func GetUninitializedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
return UninitializedNotaryRepository{}, nil
|
||||
}
|
||||
|
||||
|
@ -123,42 +158,57 @@ type UninitializedNotaryRepository struct {
|
|||
OfflineNotaryRepository
|
||||
}
|
||||
|
||||
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||
// TUF repository.
|
||||
func (u UninitializedNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
|
||||
return client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// InitializeWithCertificate initializes the repository with root keys and their corresponding certificates
|
||||
func (u UninitializedNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
|
||||
return client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// Publish pushes the local changes in signed material to the remote notary-server
|
||||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
func (u UninitializedNotaryRepository) Publish() error {
|
||||
return client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
func (u UninitializedNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
|
||||
return nil, client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name.
|
||||
func (u UninitializedNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
|
||||
return nil, client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
func (u UninitializedNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
|
||||
return nil, client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
func (u UninitializedNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
|
||||
return nil, client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
func (u UninitializedNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
|
||||
return nil, client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
// RotateKey rotates a private key and returns the public component from the remote server
|
||||
func (u UninitializedNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
|
||||
return client.ErrRepositoryNotExist{}
|
||||
}
|
||||
|
||||
func getEmptyTargetsNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
// GetEmptyTargetsNotaryRepository returns an EmptyTargetsNotaryRepository
|
||||
func GetEmptyTargetsNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
return EmptyTargetsNotaryRepository{}, nil
|
||||
}
|
||||
|
||||
|
@ -168,29 +218,41 @@ type EmptyTargetsNotaryRepository struct {
|
|||
OfflineNotaryRepository
|
||||
}
|
||||
|
||||
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||
// TUF repository.
|
||||
func (e EmptyTargetsNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitializeWithCertificate initializes the repository with root keys and their corresponding certificates
|
||||
func (e EmptyTargetsNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Publish pushes the local changes in signed material to the remote notary-server
|
||||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
func (e EmptyTargetsNotaryRepository) Publish() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
func (e EmptyTargetsNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
|
||||
return []*client.TargetWithRole{}, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name.
|
||||
func (e EmptyTargetsNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
|
||||
return nil, client.ErrNoSuchTarget(name)
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
func (e EmptyTargetsNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
|
||||
return nil, client.ErrNoSuchTarget(name)
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
func (e EmptyTargetsNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
|
||||
rootRole := data.Role{
|
||||
RootRole: data.RootRole{
|
||||
|
@ -212,15 +274,18 @@ func (e EmptyTargetsNotaryRepository) ListRoles() ([]client.RoleWithSignatures,
|
|||
{Role: targetsRole}}, nil
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
func (e EmptyTargetsNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
|
||||
return []data.Role{}, nil
|
||||
}
|
||||
|
||||
// RotateKey rotates a private key and returns the public component from the remote server
|
||||
func (e EmptyTargetsNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLoadedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
// GetLoadedNotaryRepository returns a LoadedNotaryRepository
|
||||
func GetLoadedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
return LoadedNotaryRepository{}, nil
|
||||
}
|
||||
|
||||
|
@ -316,6 +381,7 @@ var loadedTargets = []client.TargetSignedStruct{
|
|||
{Target: loadedGreenTarget, Role: loadedReleasesRole},
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
func (l LoadedNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
|
||||
rootRole := data.Role{
|
||||
RootRole: data.RootRole{
|
||||
|
@ -368,6 +434,8 @@ func (l LoadedNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error)
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
func (l LoadedNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
|
||||
filteredTargets := []*client.TargetWithRole{}
|
||||
for _, tgt := range loadedTargets {
|
||||
|
@ -378,6 +446,7 @@ func (l LoadedNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.T
|
|||
return filteredTargets, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name.
|
||||
func (l LoadedNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
|
||||
for _, tgt := range loadedTargets {
|
||||
if name == tgt.Target.Name {
|
||||
|
@ -389,6 +458,8 @@ func (l LoadedNotaryRepository) GetTargetByName(name string, roles ...data.RoleN
|
|||
return nil, client.ErrNoSuchTarget(name)
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
func (l LoadedNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
|
||||
if name == "" {
|
||||
return loadedTargets, nil
|
||||
|
@ -405,14 +476,17 @@ func (l LoadedNotaryRepository) GetAllTargetMetadataByName(name string) ([]clien
|
|||
return filteredTargets, nil
|
||||
}
|
||||
|
||||
// GetGUN is a getter for the GUN object from a Repository
|
||||
func (l LoadedNotaryRepository) GetGUN() data.GUN {
|
||||
return data.GUN("signed-repo")
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
func (l LoadedNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
|
||||
return loadedDelegationRoles, nil
|
||||
}
|
||||
|
||||
// GetCryptoService is the getter for the repository's CryptoService
|
||||
func (l LoadedNotaryRepository) GetCryptoService() signed.CryptoService {
|
||||
if l.statefulCryptoService == nil {
|
||||
// give it an in-memory cryptoservice with a root key and targets key
|
||||
|
@ -423,7 +497,8 @@ func (l LoadedNotaryRepository) GetCryptoService() signed.CryptoService {
|
|||
return l.statefulCryptoService
|
||||
}
|
||||
|
||||
func getLoadedWithNoSignersNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
// GetLoadedWithNoSignersNotaryRepository returns a LoadedWithNoSignersNotaryRepository
|
||||
func GetLoadedWithNoSignersNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
|
||||
return LoadedWithNoSignersNotaryRepository{}, nil
|
||||
}
|
||||
|
||||
|
@ -433,6 +508,8 @@ type LoadedWithNoSignersNotaryRepository struct {
|
|||
LoadedNotaryRepository
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
func (l LoadedWithNoSignersNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
|
||||
filteredTargets := []*client.TargetWithRole{}
|
||||
for _, tgt := range loadedTargets {
|
||||
|
@ -443,6 +520,7 @@ func (l LoadedWithNoSignersNotaryRepository) ListTargets(roles ...data.RoleName)
|
|||
return filteredTargets, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name.
|
||||
func (l LoadedWithNoSignersNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
|
||||
if name == "" || name == loadedGreenTarget.Name {
|
||||
return &client.TargetWithRole{Target: loadedGreenTarget, Role: data.CanonicalTargetsRole}, nil
|
||||
|
@ -450,6 +528,8 @@ func (l LoadedWithNoSignersNotaryRepository) GetTargetByName(name string, roles
|
|||
return nil, client.ErrNoSuchTarget(name)
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
func (l LoadedWithNoSignersNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
|
||||
if name == "" || name == loadedGreenTarget.Name {
|
||||
return []client.TargetSignedStruct{{Target: loadedGreenTarget, Role: loadedTargetsRole}}, nil
|
||||
|
@ -457,6 +537,7 @@ func (l LoadedWithNoSignersNotaryRepository) GetAllTargetMetadataByName(name str
|
|||
return nil, client.ErrNoSuchTarget(name)
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
func (l LoadedWithNoSignersNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
|
||||
return []data.Role{}, nil
|
||||
}
|
|
@ -25,7 +25,7 @@ func generateManPages(opts *options) error {
|
|||
}
|
||||
|
||||
stdin, stdout, stderr := term.StdStreams()
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
|
||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false)
|
||||
cmd := &cobra.Command{Use: "docker"}
|
||||
commands.AddCommands(cmd, dockerCli)
|
||||
source := filepath.Join(opts.source, descriptionSourcePath)
|
||||
|
|
Loading…
Reference in New Issue