diff --git a/cmd/cosign/cli/dockerfile.go b/cmd/cosign/cli/dockerfile.go index 28cc0bdcb6b..0d5411acfb7 100644 --- a/cmd/cosign/cli/dockerfile.go +++ b/cmd/cosign/cli/dockerfile.go @@ -112,11 +112,15 @@ func dockerfileResolve() *cobra.Command { o := &options.ResolveDockerfileOptions{} cmd := &cobra.Command{ - Use: "resolve", - Short: "", - Long: ``, - Example: ``, - Args: cobra.ExactArgs(1), + Use: "resolve", + Short: "Resolve the digest of the images and rewrites them with fully qualified image reference", + Long: ``, + Example: ` cosign dockerfile resolve Dockerfile + + # specify output file + cosign dockerfile resolve -o Dockerfile.edited Dockerfile +`, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { v := &dockerfile.ResolveDockerfileCommand{ Output: o.Output, diff --git a/cmd/cosign/cli/dockerfile/resolve.go b/cmd/cosign/cli/dockerfile/resolve.go index 24a7bd9cd53..6628b98b1f0 100644 --- a/cmd/cosign/cli/dockerfile/resolve.go +++ b/cmd/cosign/cli/dockerfile/resolve.go @@ -1,3 +1,17 @@ +// Copyright 2021 The Sigstore Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package dockerfile import ( @@ -6,12 +20,13 @@ import ( "context" "flag" "fmt" - "github.com/google/go-containerregistry/pkg/name" - "github.com/sigstore/cosign/pkg/oci/remote" "io" "os" "strings" + "github.com/google/go-containerregistry/pkg/name" + "github.com/sigstore/cosign/pkg/oci/remote" + "github.com/pkg/errors" ) @@ -38,7 +53,11 @@ func (c *ResolveDockerfileCommand) Exec(ctx context.Context, args []string) erro return fmt.Errorf("failed extracting images from Dockerfile: %w", err) } - fmt.Fprintln(os.Stderr, string(resolvedDockerfile)) + if c.Output != "" { + _ = os.WriteFile(c.Output, resolvedDockerfile, 0600) + } else { + _, _ = fmt.Fprintln(os.Stdout, string(resolvedDockerfile)) + } return nil } diff --git a/cmd/cosign/cli/dockerfile/resolve_test.go b/cmd/cosign/cli/dockerfile/resolve_test.go index 946d9d0c98d..3b43ac3db2c 100644 --- a/cmd/cosign/cli/dockerfile/resolve_test.go +++ b/cmd/cosign/cli/dockerfile/resolve_test.go @@ -1,3 +1,17 @@ +// Copyright 2021 The Sigstore Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package dockerfile import ( diff --git a/cmd/cosign/cli/dockerfile/verify.go b/cmd/cosign/cli/dockerfile/verify.go index e8c381695cf..72af8be668d 100644 --- a/cmd/cosign/cli/dockerfile/verify.go +++ b/cmd/cosign/cli/dockerfile/verify.go @@ -67,7 +67,6 @@ func getImagesFromDockerfile(dockerfile io.Reader) ([]string, error) { fileScanner := bufio.NewScanner(dockerfile) for fileScanner.Scan() { line := strings.TrimSpace(fileScanner.Text()) - // what about the COPY --from=image:tag cases? if strings.HasPrefix(strings.ToUpper(line), "FROM") { switch image := getImageFromLine(line); image { case "scratch": diff --git a/cmd/cosign/cli/options/dockerfile.go b/cmd/cosign/cli/options/dockerfile.go index 674c99087e0..61d8e489b3f 100644 --- a/cmd/cosign/cli/options/dockerfile.go +++ b/cmd/cosign/cli/options/dockerfile.go @@ -1,10 +1,25 @@ +// +// Copyright 2021 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package options import ( "github.com/spf13/cobra" ) -// ResolveDockerfileOptions is the top level wrapper for the `verify blob` command. +// ResolveDockerfileOptions is the top level wrapper for the `dockerfile resolve` command. type ResolveDockerfileOptions struct { Output string } @@ -13,6 +28,6 @@ var _ Interface = (*ResolveDockerfileOptions)(nil) // AddFlags implements Interface func (o *ResolveDockerfileOptions) AddFlags(cmd *cobra.Command) { - cmd.Flags().StringVar(&o.Output, "output", "", - "output an updated Dockerfile to file") -} \ No newline at end of file + cmd.Flags().StringVarP(&o.Output, "output", "o", + "", "output an updated Dockerfile to file") +} diff --git a/doc/cosign_dockerfile.md b/doc/cosign_dockerfile.md index 8a4cd05cce5..e09f8a500b9 100644 --- a/doc/cosign_dockerfile.md +++ b/doc/cosign_dockerfile.md @@ -19,5 +19,6 @@ Provides utilities for discovering images in and performing operations on Docker ### SEE ALSO * [cosign](cosign.md) - +* [cosign dockerfile resolve](cosign_dockerfile_resolve.md) - Resolve the digest of the images and rewrites them with fully qualified image reference * [cosign dockerfile verify](cosign_dockerfile_verify.md) - Verify a signature on the base image specified in the Dockerfile diff --git a/doc/cosign_dockerfile_resolve.md b/doc/cosign_dockerfile_resolve.md new file mode 100644 index 00000000000..4220c11488c --- /dev/null +++ b/doc/cosign_dockerfile_resolve.md @@ -0,0 +1,37 @@ +## cosign dockerfile resolve + +Resolve the digest of the images and rewrites them with fully qualified image reference + +``` +cosign dockerfile resolve [flags] +``` + +### Examples + +``` + cosign dockerfile resolve Dockerfile + + # specify output file + cosign dockerfile resolve -o Dockerfile.edited Dockerfile + +``` + +### Options + +``` + -h, --help help for resolve + -o, --output string output an updated Dockerfile to file +``` + +### Options inherited from parent commands + +``` + --azure-container-registry-config string Path to the file containing Azure container registry configuration information. + --output-file string log output to a file + -d, --verbose log debug output +``` + +### SEE ALSO + +* [cosign dockerfile](cosign_dockerfile.md) - Provides utilities for discovering images in and performing operations on Dockerfiles + diff --git a/test/e2e_test.sh b/test/e2e_test.sh index b480e65e755..76aff31c82d 100755 --- a/test/e2e_test.sh +++ b/test/e2e_test.sh @@ -49,11 +49,17 @@ go test -tags=e2e -race ./... # Test `cosign dockerfile verify` export DISTROLESS_PUB_KEY=distroless.pub wget -O ${DISTROLESS_PUB_KEY} https://raw.githubusercontent.com/GoogleContainerTools/distroless/main/cosign.pub + ./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/single_stage.Dockerfile if (./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/unsigned_build_stage.Dockerfile); then false; fi ./cosign dockerfile verify --base-image-only --key ${DISTROLESS_PUB_KEY} ./test/testdata/unsigned_build_stage.Dockerfile ./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/fancy_from.Dockerfile test_image="gcr.io/distroless/base" ./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/with_arg.Dockerfile + +# Test dockerfile resolve and verify +./cosign dockerfile resolve -o ./test/testdata/fancy_from.Dockerfile.resolved ./test/testdata/fancy_from.Dockerfile +./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/fancy_from.Dockerfile.resolved + # Image exists, but is unsigned if (test_image="ubuntu" ./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/with_arg.Dockerfile); then false; fi ./cosign dockerfile verify --key ${DISTROLESS_PUB_KEY} ./test/testdata/with_lowercase.Dockerfile