Skip to content

Commit

Permalink
Add Cosign env pass-through
Browse files Browse the repository at this point in the history
Signed-off-by: Ziwen Ning <[email protected]>
  • Loading branch information
ningziwen committed Mar 17, 2023
1 parent 370a9ef commit fe8ad5d
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 1 deletion.
20 changes: 19 additions & 1 deletion cmd/finch/nerdctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error {
var (
nerdctlArgs, envs, fileEnvs []string
skip bool
cosign bool
)

for i, arg := range args {
Expand Down Expand Up @@ -121,10 +122,27 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error {
arg = fmt.Sprintf("%s%s", arg[0:11], resolvedIP)
}
nerdctlArgs = append(nerdctlArgs, arg)
case arg == "--sign=cosign_data" || arg == "--verify=cosign_data":
cosign = true
nerdctlArgs = append(nerdctlArgs, arg)
default:
nerdctlArgs = append(nerdctlArgs, arg)
}
}
limaArgs := []string{"shell", limaInstanceName, "sudo"}

// The env variables are not passed through by `limactl shell` by default so we need to assign the variables explicitly.
// https://github.com/lima-vm/lima/issues/1419
if cosign {
cosignEnv := "COSIGN_PASSWORD"
v, b := nc.systemDeps.LookupEnv(cosignEnv)
if b {
limaArgs = append(limaArgs, fmt.Sprintf("%s=%s", cosignEnv, v))
}
}

limaArgs = append(limaArgs, nerdctlCmdName, cmdName)

// to handle environment variables properly, we add all entries found via
// env-file includes to the map first and then all command line environment
// flags, making sure that command line overrides environment file options,
Expand All @@ -146,7 +164,7 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error {
}
finalArgs = append(finalArgs, nerdctlArgs...)

limaArgs := append([]string{"shell", limaInstanceName, "sudo", 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
68 changes: 68 additions & 0 deletions cmd/finch/nerdctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,74 @@ func TestNerdctlCommand_run(t *testing.T) {
Return(fmt.Errorf("failed to replace"))
},
},
{
name: "with COSIGN_PASSWORD env var and --sign=cosign_data",
cmdName: "push",
args: []string{"--sign=cosign_data", "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", "COSIGN_PASSWORD=test", nerdctlCmdName, "push", "--sign=cosign_data", "test:tag").Return(c)
c.EXPECT().Run()
},
},
{
name: "with COSIGN_PASSWORD env var and --verify=cosign_data",
cmdName: "pull",
args: []string{"--verify=cosign_data", "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", "COSIGN_PASSWORD=test", nerdctlCmdName, "pull", "--verify=cosign_data", "test:tag").Return(c)
c.EXPECT().Run()
},
},
{
name: "with COSIGN_PASSWORD env var without cosign_data 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")
c := mocks.NewCommand(ctrl)
lcc.EXPECT().Create("shell", limaInstanceName, "sudo", 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-----
53 changes: 53 additions & 0 deletions e2e/container/cosign_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package container

import (
"fmt"
"os"

"github.com/onsi/ginkgo/v2"
"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"
const registryImage = "public.ecr.aws/docker/library/registry:latest"

var testCosign = func(o *option.Option) {
ginkgo.Describe("Cosign", func() {
var buildContext string
var port int

ginkgo.BeforeEach(func() {
command.RemoveAll(o)
buildContext = ffs.CreateBuildContext(fmt.Sprintf(`FROM %s
CMD ["echo", "bar"]
`, alpineImage))
ginkgo.DeferCleanup(os.RemoveAll, buildContext)
port = fnet.GetFreePort()
command.Run(o, "run", "-dp", fmt.Sprintf("%d:5000", port), "--name", "registry", registryImage)
})

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() {
tag := fmt.Sprintf(`localhost:%d/test-push:tag`, port)
command.Run(o, "build", "-t", tag, buildContext)
os.Setenv("COSIGN_PASSWORD", "test-1")
defer os.Unsetenv("COSIGN_PASSWORD")
command.Run(o, "push", "--sign=cosign", "--cosign-key=./e2e/cosign_data/test1.key", tag)
command.Run(o, "pull", "--verify=cosign", "--cosign-key=./e2e/cosign_data/test-1.pub", tag)
command.Run(o, "run", "-d", "--verify=cosign", "--cosign-key=./e2e/cosign_data/test-1.pub", tag)
command.RunWithoutSuccessfulExit(o, "pull", "-d", "--verify=cosign_data", "--cosign-key=./e2e/cosign_data/test-2.pub", tag)
command.RunWithoutSuccessfulExit(o, "run", "-d", "--verify=cosign_data", "--cosign-key=./e2e/cosign_data/test-2.pub", tag)
command.RunWithoutSuccessfulExit(o, "pull", "-d", "--verify=cosign_data", "--cosign-key=./e2e/cosign_data/test-2.pub", alpineImage)
command.RunWithoutSuccessfulExit(o, "run", "-d", "--verify=cosign_data", "--cosign-key=./e2e/cosign_data/test-2.pub", alpineImage)
})
})
}

0 comments on commit fe8ad5d

Please sign in to comment.