From c4291e35d65199cb7bfbd04deb1c4b78a6046465 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Fri, 10 Nov 2023 12:09:53 +0100 Subject: [PATCH] Add --check-policy option to skopeo inspect When handling images with skopeo it can be useful to be able to check that the image is valid before processing any of its metadata. With the new `--check-policy` flag `skopeo inspect` will error out if the image doesn't pass the policy check. Signed-off-by: Alban Bedel --- cmd/skopeo/inspect.go | 22 +++++++++++++++++++++- docs/skopeo-inspect.1.md | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go index e969caa4c1..5dac13f064 100644 --- a/cmd/skopeo/inspect.go +++ b/cmd/skopeo/inspect.go @@ -29,6 +29,7 @@ type inspectOptions struct { raw bool // Output the raw manifest instead of parsing information about the image config bool // Output the raw config blob instead of parsing information about the image doNotListTags bool // Do not list all tags available in the same repository + checkPolicy bool // Error out if image is not allowed to run } func inspectCmd(global *globalOptions) *cobra.Command { @@ -61,6 +62,7 @@ skopeo inspect --format "Name: {{.Name}} Digest: {{.Digest}}" docker://registry. flags.BoolVar(&opts.config, "config", false, "output configuration") flags.StringVarP(&opts.format, "format", "f", "", "Format the output to a Go template") flags.BoolVarP(&opts.doNotListTags, "no-tags", "n", false, "Do not list the available tags from the repository in the output") + flags.BoolVar(&opts.checkPolicy, "check-policy", false, "Verify that the image pass the policy check") flags.AddFlagSet(&sharedFlags) flags.AddFlagSet(&imageFlags) flags.AddFlagSet(&retryFlags) @@ -106,6 +108,24 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error) } }() + unparsedImage := image.UnparsedInstance(src, nil) + if opts.checkPolicy { + policyContext, err := opts.global.getPolicyContext() + if err != nil { + return fmt.Errorf("Error loading trust policy: %v", err) + } + defer func() { + if err := policyContext.Destroy(); err != nil { + retErr = noteCloseFailure(retErr, "tearing down policy context", err) + } + }() + + // Be paranoid and fail if either return value indicates so. + if allowed, err := policyContext.IsRunningImageAllowed(ctx, unparsedImage); !allowed || err != nil { + return fmt.Errorf("Image rejected: %w", err) + } + } + if err := retry.IfNecessary(ctx, func() error { rawManifest, _, err = src.GetManifest(ctx, nil) return err @@ -122,7 +142,7 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error) return nil } - img, err := image.FromUnparsedImage(ctx, sys, image.UnparsedInstance(src, nil)) + img, err := image.FromUnparsedImage(ctx, sys, unparsedImage) if err != nil { return fmt.Errorf("Error parsing manifest for image: %w", err) } diff --git a/docs/skopeo-inspect.1.md b/docs/skopeo-inspect.1.md index 0c8a50dfae..df95eacf92 100644 --- a/docs/skopeo-inspect.1.md +++ b/docs/skopeo-inspect.1.md @@ -28,6 +28,10 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec Use certificates at _path_ (\*.crt, \*.cert, \*.key) to connect to the registry. +**--check-policy** + +Verify that the image pass the policy check. + **--config** Output configuration in OCI format, default is to format in JSON format.