Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add experimental support for Cosign signing and verification #296

Merged
merged 1 commit into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion cmd/finch/nerdctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,29 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error {
envVars[evar] = eval
}

passedEnvs := []string{"COSIGN_PASSWORD"}
var passedEnvArgs []string
for _, e := range passedEnvs {
v, b := nc.systemDeps.LookupEnv(e)
if b {
passedEnvArgs = append(passedEnvArgs, fmt.Sprintf("%s=%s", e, v))
}
}

// Add -E to sudo command in order to preserve existing environment variables, more info:
// https://stackoverflow.com/questions/8633461/how-to-keep-environment-variables-when-using-sudo/8633575#8633575
limaArgs := append([]string{"shell", limaInstanceName, "sudo", "-E"}, passedEnvArgs...)

limaArgs = append(limaArgs, []string{nerdctlCmdName, cmdName}...)

var finalArgs []string
for key, val := range envVars {
finalArgs = append(finalArgs, "-e", fmt.Sprintf("%s=%s", key, val))
}
finalArgs = append(finalArgs, nerdctlArgs...)
// Add -E to sudo command in order to preserve existing environment variables, more info:
// https://stackoverflow.com/questions/8633461/how-to-keep-environment-variables-when-using-sudo/8633575#8633575
limaArgs := append([]string{"shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, cmdName}, finalArgs...)
limaArgs = append(limaArgs, finalArgs...)

if nc.shouldReplaceForHelp(cmdName, args) {
return nc.creator.RunWithReplacingStdout([]command.Replacement{{Source: "nerdctl", Target: "finch"}}, limaArgs...)
Expand Down
96 changes: 91 additions & 5 deletions cmd/finch/nerdctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/runfinch/finch/pkg/flog"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/mocks"

"github.com/runfinch/finch/pkg/flog"
)

var testStdoutRs = []command.Replacement{
Expand All @@ -40,19 +40,20 @@ func TestNerdctlCommand_runAdaptor(t *testing.T) {
name string
cmd *cobra.Command
args []string
mockSvc func(*mocks.LimaCmdCreator, *mocks.Logger, *gomock.Controller)
mockSvc func(*mocks.LimaCmdCreator, *mocks.Logger, *gomock.Controller, *mocks.NerdctlCommandSystemDeps)
}{
{
name: "happy path",
cmd: &cobra.Command{
Use: "info",
},
args: []string{},
mockSvc: func(lcc *mocks.LimaCmdCreator, logger *mocks.Logger, ctrl *gomock.Controller) {
mockSvc: func(lcc *mocks.LimaCmdCreator, logger *mocks.Logger, ctrl *gomock.Controller, ncsd *mocks.NerdctlCommandSystemDeps) {
getVMStatusC := mocks.NewCommand(ctrl)
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "info").Return(c)
c.EXPECT().Run()
Expand All @@ -69,7 +70,7 @@ func TestNerdctlCommand_runAdaptor(t *testing.T) {
lcc := mocks.NewLimaCmdCreator(ctrl)
ncsd := mocks.NewNerdctlCommandSystemDeps(ctrl)
logger := mocks.NewLogger(ctrl)
tc.mockSvc(lcc, logger, ctrl)
tc.mockSvc(lcc, logger, ctrl, ncsd)

assert.NoError(t, newNerdctlCommand(lcc, ncsd, logger, nil).runAdapter(tc.cmd, tc.args))
})
Expand Down Expand Up @@ -103,6 +104,7 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "build", "-t", "demo", ".").Return(c)
c.EXPECT().Run()
Expand Down Expand Up @@ -204,6 +206,7 @@ func TestNerdctlCommand_run(t *testing.T) {
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
logger.EXPECT().SetLevel(flog.Debug)
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag").Return(c)
c.EXPECT().Run()
Expand All @@ -229,6 +232,7 @@ func TestNerdctlCommand_run(t *testing.T) {
c := mocks.NewCommand(ctrl)
ncsd.EXPECT().LookupEnv("ARG2")
ncsd.EXPECT().LookupEnv("ARG3")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"-e", "ARG1=val1", "--rm", "alpine:latest", "env").Return(c)
c.EXPECT().Run()
Expand All @@ -254,6 +258,7 @@ func TestNerdctlCommand_run(t *testing.T) {
c := mocks.NewCommand(ctrl)
ncsd.EXPECT().LookupEnv("ARG2")
ncsd.EXPECT().LookupEnv("ARG3").Return("val3", true)
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"-e", "ARG3=val3", "--rm", "alpine:latest", "env").Return(c)
c.EXPECT().Run()
Expand Down Expand Up @@ -282,6 +287,7 @@ func TestNerdctlCommand_run(t *testing.T) {
c := mocks.NewCommand(ctrl)
ncsd.EXPECT().LookupEnv("ARG2")
ncsd.EXPECT().LookupEnv("NOTSETARG")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().
Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run", "-e", "ARG1=val1", "--rm", "alpine:latest", "env").
Return(c)
Expand Down Expand Up @@ -311,6 +317,7 @@ func TestNerdctlCommand_run(t *testing.T) {
c := mocks.NewCommand(ctrl)
ncsd.EXPECT().LookupEnv("ARG2").Return("val2", true)
ncsd.EXPECT().LookupEnv("NOTSETARG")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().
Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run", "-e", "ARG2=val2", "--rm", "alpine:latest", "env").
Return(c)
Expand Down Expand Up @@ -354,6 +361,7 @@ func TestNerdctlCommand_run(t *testing.T) {
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"--rm", "--add-host", "name:192.168.5.2", "alpine:latest").Return(c)
Expand All @@ -377,6 +385,7 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"--rm", "--add-host", "name:0.0.0.0", "alpine:latest").Return(c)
Expand All @@ -400,6 +409,7 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"--rm", "--add-host", "alpine:latest").Return(c)
Expand All @@ -424,6 +434,7 @@ func TestNerdctlCommand_run(t *testing.T) {
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"--rm", "--add-host=name:192.168.5.2", "alpine:latest").Return(c)
Expand All @@ -447,6 +458,7 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "run",
"--rm", "--add-host=name:0.0.0.0", "alpine:latest").Return(c)
Expand All @@ -470,6 +482,7 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().RunWithReplacingStdout(
testStdoutRs, "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag", "--help").Return(nil)
},
Expand All @@ -491,11 +504,84 @@ func TestNerdctlCommand_run(t *testing.T) {
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false)
lcc.EXPECT().RunWithReplacingStdout(
testStdoutRs, "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag", "--help").
Return(fmt.Errorf("failed to replace"))
},
},
{
name: "with COSIGN_PASSWORD env var and --sign=cosign",
cmdName: "push",
args: []string{"--sign=cosign", "test:tag"},
wantErr: nil,
mockSvc: func(
t *testing.T,
lcc *mocks.LimaCmdCreator,
ncsd *mocks.NerdctlCommandSystemDeps,
logger *mocks.Logger,
ctrl *gomock.Controller,
fs afero.Fs,
) {
getVMStatusC := mocks.NewCommand(ctrl)
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", "COSIGN_PASSWORD=test", nerdctlCmdName,
"push", "--sign=cosign", "test:tag").Return(c)
c.EXPECT().Run()
},
},
{
name: "with COSIGN_PASSWORD env var and --verify=cosign",
cmdName: "pull",
args: []string{"--verify=cosign", "test:tag"},
wantErr: nil,
mockSvc: func(
t *testing.T,
lcc *mocks.LimaCmdCreator,
ncsd *mocks.NerdctlCommandSystemDeps,
logger *mocks.Logger,
ctrl *gomock.Controller,
fs afero.Fs,
) {
getVMStatusC := mocks.NewCommand(ctrl)
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", "COSIGN_PASSWORD=test", nerdctlCmdName,
"pull", "--verify=cosign", "test:tag").Return(c)
c.EXPECT().Run()
},
},
{
name: "with COSIGN_PASSWORD env var without cosign arg",
cmdName: "pull",
args: []string{"test:tag"},
wantErr: nil,
mockSvc: func(
t *testing.T,
lcc *mocks.LimaCmdCreator,
ncsd *mocks.NerdctlCommandSystemDeps,
logger *mocks.Logger,
ctrl *gomock.Controller,
fs afero.Fs,
) {
getVMStatusC := mocks.NewCommand(ctrl)
lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC)
getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil)
logger.EXPECT().Debugf("Status of virtual machine: %s", "Running")
ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true)
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", "COSIGN_PASSWORD=test",
nerdctlCmdName, "pull", "test:tag").Return(c)
c.EXPECT().Run()
},
},
}

for _, tc := range testCases {
Expand Down
1 change: 1 addition & 0 deletions e2e/container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func TestContainer(t *testing.T) {
tests.NetworkInspect(o)
tests.NetworkLs(o)
tests.NetworkRm(o)
testCosign(o)
})

gomega.RegisterFailHandler(ginkgo.Fail)
Expand Down
11 changes: 11 additions & 0 deletions e2e/container/cosign_data/test-1.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
OCwicCI6MX0sInNhbHQiOiIvYW9saHRuZEZTSHZsQjBZSnBTOVI1VlcyOE5HUmox
VkJNL2VDZWlvVEV3PSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiJGRGpKU1BTdnN4WmQ0N2orRlgvUjlPbVB0WlpkTVh4dyJ9LCJj
aXBoZXJ0ZXh0IjoibzlCOXJJbmZPNXZaeE9PMFBSdFdjYlNUQmxibXA5OVVWTnEv
ZFhJN0hzd09yZFpVeTA1MmdUT3AyVkFsSjk2aTNFZitiY095QlU1MWt1UDd2R2gy
U1ljU2VkbWQvejEzM3owNUovZytjUll3bHRuNkowOTgwZ0xUR1NKdWxobFNIYWpC
Q25LS1RmY2tIb0dUU0dsZkU1aFk1UFdyRGlQTmc3VVA4bk1lc2JCWlRPMnFjaUdE
bTI0a21ON1RIOEljRlJ4T3Y1NkFNWm1tTUE9PSJ9
-----END ENCRYPTED COSIGN PRIVATE KEY-----
4 changes: 4 additions & 0 deletions e2e/container/cosign_data/test-1.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfkODzHTFabSz0T+X758IqIB6pi3u
Km4JQCcEDFv94s6J4msvNOhmiAv3PQ/b9dutQ7QODWJAdm3cp6CMd87e1w==
-----END PUBLIC KEY-----
11 changes: 11 additions & 0 deletions e2e/container/cosign_data/test-2.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
OCwicCI6MX0sInNhbHQiOiJiYlVrSzkzdmY2dEhIM1czNTJ1UWM2ajNidzduUjdW
cTdReHJaRVlJYXM4PSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiJBWlhuSThncGhjbzdFdDBVOGhzKy91Tk5OdFpyTWNBOSJ9LCJj
aXBoZXJ0ZXh0IjoiaVJsUG9IRlJnQmJTamc2NnhvTTM4dm0vNExwelJXeUlKZi8x
dFIraEJ3dHdRMTQwZjBsQlpHdHRRMXZYcEE4UktHK09vTnNUcFNUSGh6R2phd3VN
ZXNzaVdsWkxHVTVjSTU5UVZ4TW40bGI4ME5iNWF2NlA5ZjVYT2x2aHhXbnMzUnpt
R091L0hCOHd1ZnBUUnBlQlZNLzZkZmFyV05ZbE92VzRYaWVvZXNEQ0hOV3JWbzFJ
WWdCbysxTEFYbzdYWkQ4cXNVWFdJd3ZONkE9PSJ9
-----END ENCRYPTED COSIGN PRIVATE KEY-----
4 changes: 4 additions & 0 deletions e2e/container/cosign_data/test-2.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERyYVqiPX1IGvTiAuJCZIOfPllOm/
HTi7DaswFLwNXVOOC7FLP3L9YzQ0q24bFBqkSQqgWeycKsOOPCbF0nMLHQ==
-----END PUBLIC KEY-----
85 changes: 85 additions & 0 deletions e2e/container/cosign_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package container

import (
"fmt"
"os"
"path/filepath"

"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"github.com/runfinch/common-tests/command"
"github.com/runfinch/common-tests/ffs"
"github.com/runfinch/common-tests/fnet"
"github.com/runfinch/common-tests/option"
)

const (
alpineImage = "public.ecr.aws/docker/library/alpine:latest"
registryImage = "public.ecr.aws/docker/library/registry:latest"
)

var testCosign = func(o *option.Option) {
ginkgo.Describe("Cosign", func() {
var buildContext string
var port int
var registry string
var tag string
ginkgo.BeforeEach(func() {
command.RemoveAll(o)
buildContext = ffs.CreateBuildContext(fmt.Sprintf(`FROM %s
CMD ["echo", "bar"]
`, alpineImage))
ginkgo.DeferCleanup(os.RemoveAll, buildContext)
filename := "htpasswd"
// The htpasswd is generated by
// `<subject> run --entrypoint htpasswd public.ecr.aws/docker/library/httpd:2 -Bbn testUser testPassword`.
// We don't want to generate it on the fly because:
// 1. Pulling the httpd image can take a long time, sometimes even more 10 seconds.
// 2. It's unlikely that we will have to update this in the future.
// 3. It's not the thing we want to validate by the functional tests. We only want the output produced by it.
//nolint:gosec // This password is only used for testing purpose.
htpasswd := "testUser:$2y$05$wE0sj3r9O9K9q7R0MXcfPuIerl/06L1IsxXkCuUr3QZ8lHWwicIdS"
htpasswdDir := filepath.Dir(ffs.CreateTempFile(filename, htpasswd))
ginkgo.DeferCleanup(os.RemoveAll, htpasswdDir)
port = fnet.GetFreePort()
command.Run(o, "run",
"-dp", fmt.Sprintf("%d:5000", port),
"--name", "registry",
"-v", fmt.Sprintf("%s:/auth", htpasswdDir),
"-e", "REGISTRY_AUTH=htpasswd",
"-e", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm",
"-e", fmt.Sprintf("REGISTRY_AUTH_HTPASSWD_PATH=/auth/%s", filename),
registryImage)
registry = fmt.Sprintf(`localhost:%d`, port)
tag = fmt.Sprintf(`%s/test-login:tag`, registry)
})

ginkgo.AfterEach(func() {
command.RemoveAll(o)
})

ginkgo.It("should succeed to verify the signature of the image only when it is signed with the matched key", func() {
command.Run(o, "build", "-t", tag, buildContext)
gomega.Expect(os.Setenv("COSIGN_PASSWORD", "test-1")).To(gomega.Succeed())
command.Run(o, "login", registry, "-u", "testUser", "-p", "testPassword")
ginkgo.DeferCleanup(func() {
command.Run(o, "logout", registry)
})
command.Run(o, "push", "--sign=cosign", "--cosign-key=./cosign_data/test-1.key", tag)
command.Run(o, "pull", "--verify=cosign", "--cosign-key=./cosign_data/test-1.pub", tag)
command.Run(o, "run", "-d", "--verify=cosign", "--cosign-key=./cosign_data/test-1.pub", tag)

gomega.Expect(command.RunWithoutSuccessfulExit(o, "pull", "--verify=cosign", "--cosign-key=./cosign_data/test-2.pub",
tag).Err.Contents()).Should(gomega.ContainSubstring("no matching signatures"))
gomega.Expect(command.RunWithoutSuccessfulExit(o, "run", "-d", "--verify=cosign", "--cosign-key=./cosign_data/test-2.pub",
tag).Err.Contents()).Should(gomega.ContainSubstring("no matching signatures"))
gomega.Expect(command.RunWithoutSuccessfulExit(o, "pull", "--verify=cosign", "--cosign-key=./cosign_data/test-2.pub",
alpineImage).Err.Contents()).Should(gomega.ContainSubstring("no matching signatures"))
gomega.Expect(command.RunWithoutSuccessfulExit(o, "run", "-d", "--verify=cosign", "--cosign-key=./cosign_data/test-2.pub",
alpineImage).Err.Contents()).Should(gomega.ContainSubstring("no matching signatures"))
})
})
}