Add more content trust tests
Importing from moby's DockerTrustSuite tests.
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 8b00c5cfd8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
committed by
Sebastiaan van Stijn
parent
a20423b7f7
commit
bc28daf367
@ -2,6 +2,7 @@ package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -10,6 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
@ -119,6 +121,51 @@ func TestCreateContainerPullsImageIfMissing(t *testing.T) {
|
||||
assert.Check(t, is.Contains(stderr, "Unable to find image 'does-not-exist-locally:latest' locally"))
|
||||
}
|
||||
|
||||
func TestNewCreateCommandWithContentTrustErrors(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: "uninitialized-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{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
containerName string,
|
||||
) (container.ContainerCreateCreatedBody, error) {
|
||||
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
cmd := NewCreateCommand(cli)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.ErrorContains(t, err, tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeNotFound struct{}
|
||||
|
||||
func (f fakeNotFound) NotFound() bool { return true }
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestRunLabel(t *testing.T) {
|
||||
@ -23,3 +26,48 @@ func TestRunLabel(t *testing.T) {
|
||||
cmd.SetArgs([]string{"--label", "foo", "busybox"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
}
|
||||
|
||||
func TestRunCommandWithContentTrustErrors(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: "uninitialized-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{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
containerName string,
|
||||
) (container.ContainerCreateCreatedBody, error) {
|
||||
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
cmd := NewRunCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, is.Contains(cli.ErrBuffer().String(), tc.expectedError))
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
|
||||
|
||||
options := newBuildOptions()
|
||||
options.context = dir.Path()
|
||||
options.untrusted = true
|
||||
|
||||
err := runBuild(cli, options)
|
||||
assert.NilError(t, err)
|
||||
|
||||
@ -57,6 +57,7 @@ func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||
options.compress = true
|
||||
options.dockerfileName = "-"
|
||||
options.context = dir
|
||||
options.untrusted = true
|
||||
|
||||
err = runBuild(cli, options)
|
||||
assert.NilError(t, err)
|
||||
@ -191,6 +192,7 @@ RUN echo hello world
|
||||
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
|
||||
options := newBuildOptions()
|
||||
options.context = tmpDir.Join("context-link")
|
||||
options.untrusted = true
|
||||
assert.NilError(t, runBuild(cli, options))
|
||||
|
||||
assert.DeepEqual(t, files, []string{"Dockerfile"})
|
||||
|
||||
@ -59,7 +59,7 @@ func runPull(cli command.Cli, opts pullOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
|
||||
args: []string{"image:tag"},
|
||||
},
|
||||
{
|
||||
name: "empty-notary-server",
|
||||
name: "uninitialized-notary-server",
|
||||
notaryFunc: notary.GetUninitializedNotaryRepository,
|
||||
expectedError: "remote trust data does not exist",
|
||||
args: []string{"image:tag"},
|
||||
|
||||
@ -198,7 +198,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -293,35 +293,24 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
|
||||
|
||||
// TrustedReference returns the canonical trusted reference for an image reference
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
|
||||
var (
|
||||
repoInfo *registry.RepositoryInfo
|
||||
err error
|
||||
)
|
||||
if rs != nil {
|
||||
repoInfo, err = rs.ResolveRepository(ref)
|
||||
} else {
|
||||
repoInfo, err = registry.ParseRepositoryInfo(ref)
|
||||
}
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Resolve the Auth config relevant for this server
|
||||
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
|
||||
|
||||
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
|
||||
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, []string{"pull"})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error establishing connection to trust repository")
|
||||
}
|
||||
|
||||
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
|
||||
if err != nil {
|
||||
return nil, trust.NotaryError(repoInfo.Name.Name(), err)
|
||||
return nil, trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), err)
|
||||
}
|
||||
// Only list tags in the top level targets role or the releases delegation role - ignore
|
||||
// all other delegation roles
|
||||
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
|
||||
return nil, trust.NotaryError(repoInfo.Name.Name(), client.ErrNoSuchTarget(ref.Tag()))
|
||||
return nil, trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), client.ErrNoSuchTarget(ref.Tag()))
|
||||
}
|
||||
r, err := convertTarget(t.Target)
|
||||
if err != nil {
|
||||
|
||||
@ -66,7 +66,7 @@ type trustKey struct {
|
||||
// This information is to be pretty printed or serialized into a machine-readable format.
|
||||
func lookupTrustInfo(cli command.Cli, remote string) (trustTagRowList, []client.RoleWithSignatures, []data.Role, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return trustTagRowList{}, []client.RoleWithSignatures{}, []data.Role{}, err
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ func newSignCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runSignImage(cli command.Cli, options signOptions) error {
|
||||
imageName := options.imageName
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ func addSigner(cli command.Cli, options signerAddOptions) error {
|
||||
|
||||
func addSignerToRepo(cli command.Cli, signerName string, repoName string, signerPubKeys []data.PublicKey) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ func isLastSignerForReleases(roleWithSig data.Role, allRoles []client.RoleWithSi
|
||||
|
||||
func removeSingleSigner(cli command.Cli, repoName, signerName string, forceYes bool) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -300,14 +300,23 @@ type ImageRefAndAuth struct {
|
||||
|
||||
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
|
||||
// as an ImageRefAndAuth struct
|
||||
func GetImageReferencesAndAuth(ctx context.Context, authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig, imgName string) (ImageRefAndAuth, error) {
|
||||
func GetImageReferencesAndAuth(ctx context.Context, rs registry.Service,
|
||||
authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig,
|
||||
imgName string,
|
||||
) (ImageRefAndAuth, error) {
|
||||
ref, err := reference.ParseNormalizedNamed(imgName)
|
||||
if err != nil {
|
||||
return ImageRefAndAuth{}, err
|
||||
}
|
||||
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||
var repoInfo *registry.RepositoryInfo
|
||||
if rs != nil {
|
||||
repoInfo, err = rs.ResolveRepository(ref)
|
||||
} else {
|
||||
repoInfo, err = registry.ParseRepositoryInfo(ref)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return ImageRefAndAuth{}, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user