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

Image verification for namespaced policies #8212

Merged
merged 9 commits into from
Sep 9, 2024

Conversation

harche
Copy link
Contributor

@harche harche commented May 23, 2024

What type of PR is this?

/kind feature

What this PR does / why we need it:

Adds support for verification using namespaced policies during container creation.

Which issue(s) this PR fixes:

None

Special notes for your reviewer:

Does this PR introduce a user-facing change?

Add support for validating signatures on container creation. Now, if there is a namespaced policy in the `signature_policy_dir`, CRI-O will validate the signature defined in `signature_policy_dir`/`NS`.json for pods in namespace `NS`

@harche harche requested a review from mrunalp as a code owner May 23, 2024 15:32
@openshift-ci openshift-ci bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. labels May 23, 2024
@openshift-ci openshift-ci bot added the do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. label May 23, 2024
@harche harche marked this pull request as draft May 23, 2024 16:06
@saschagrunert
Copy link
Member

@harche feel free to ping here if you need assistance or review.

@harche harche force-pushed the sigstore_namespace branch 3 times, most recently from 8126007 to 8231d9f Compare June 4, 2024 14:36
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 9, 2024
@harche harche force-pushed the sigstore_namespace branch 2 times, most recently from 8853f7b to 6fae2e4 Compare July 12, 2024 15:56
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 12, 2024
@harche harche marked this pull request as ready for review July 12, 2024 15:59
@openshift-ci openshift-ci bot requested a review from littlejawa July 12, 2024 15:59
if err != nil && !errors.Is(err, storage.ErrImageUnknown) {
return fmt.Errorf("error retrieving image %s: %w", configImage, err)
}
if img != nil {
Copy link
Contributor

@rphillips rphillips Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps double check the length of img here.

It should >= 1 in this context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rphillips img is of Image type,

Hence the check for if it is nil.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but the length of the array could be zero, and we are indexing into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rphillips something like,

if img != nil && img.Names != nil && len(img.Names) > 0

?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to retract my comment here... I think the better approach is to check if err != nil if the alternative case, on line 542, and remove the if img != nil entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can have err == nil and img == nil at the same time. It just means that, there was no error looking up in the image store but the image doesn't exist in that store.

Copy link
Member

@saschagrunert saschagrunert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unit test mocks needs to be updated (see GitHub actions).

Is this still work in progress (WIP)?

internal/storage/image.go Outdated Show resolved Hide resolved
@harche harche changed the title WIP: image verificaiton for namespaced policies Image verification for namespaced policies Jul 17, 2024
@openshift-ci openshift-ci bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Jul 17, 2024
@harche
Copy link
Contributor Author

harche commented Jul 17, 2024

/retest-required

Signed-off-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Peter Hunt <pehunt@redhat.com>
which protects us against cases where the user_defined_image isn't
specified (like for container restores)

Signed-off-by: Peter Hunt <pehunt@redhat.com>
We already have access to the storage reference, so we should use it

Signed-off-by: Peter Hunt <pehunt@redhat.com>
…mage

Signed-off-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Peter Hunt <pehunt@redhat.com>
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Sep 9, 2024
@haircommander
Copy link
Member

/lgtm

(had to update the CR test)

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Sep 9, 2024
@haircommander
Copy link
Member

/override ci/prow/ci-rhel-critest

Copy link
Contributor

openshift-ci bot commented Sep 9, 2024

@haircommander: Overrode contexts on behalf of haircommander: ci/prow/ci-rhel-critest

In response to this:

/override ci/prow/ci-rhel-critest

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@haircommander
Copy link
Member

/retest

@haircommander
Copy link
Member

/override ci/prow/ci-rhel-critest
/retest

Copy link
Contributor

openshift-ci bot commented Sep 9, 2024

@haircommander: Overrode contexts on behalf of haircommander: ci/prow/ci-rhel-critest

In response to this:

/override ci/prow/ci-rhel-critest
/retest

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@haircommander
Copy link
Member

/retest

@haircommander
Copy link
Member

/override ci/prow/ci-rhel-critest

Copy link
Contributor

openshift-ci bot commented Sep 9, 2024

@haircommander: Overrode contexts on behalf of haircommander: ci/prow/ci-rhel-critest

In response to this:

/override ci/prow/ci-rhel-critest

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@haircommander
Copy link
Member

/override ci/prow/ci-rhel-critest

Copy link
Contributor

openshift-ci bot commented Sep 9, 2024

@haircommander: Overrode contexts on behalf of haircommander: ci/prow/ci-rhel-critest

In response to this:

/override ci/prow/ci-rhel-critest

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-merge-bot openshift-merge-bot bot merged commit ac758bb into cri-o:main Sep 9, 2024
80 of 82 checks passed
Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Late review … now comprehensive.

I’ll file a PR for some parts, and an issue for the remaining outstanding things.

imageID, err := storage.ParseStorageImageIDFromOutOfProcessData("2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812")
Expect(err).ToNot(HaveOccurred())
otherImageID, err := storage.ParseStorageImageIDFromOutOfProcessData("3a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812")
canonicalImageCandidate, err := reference.WithDigest(imageCandidate.Raw(), digest.Digest("sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not representative; PullImage returns a name@digest, this is name:tag@digest.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #8590 .

@@ -26,7 +26,7 @@ function teardown() {
@test "run container in pod with image ID" {
start_crio
pod_id=$(crictl runp "$TESTDATA"/sandbox_config.json)
jq '.image.image = "'"$REDIS_IMAGEID"'"' \
jq '.image.image = "'"$REDIS_IMAGEID"'" | .image.user_specified_image = "'"$REDIS_IMAGEDIGEST"'"' \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the three instances in this file, image.user_specified_image is already set (to name:tag) in container_config.json; is there a specific need to override that to a digest value?

Or is that just for consistency with the other tests that override both .image.image and .image.user_specified_image?

select(.repoTags[0] == "quay.io/crio/hello-wasm:latest") |
"WASM_IMAGEID=" + .id + "\n" +
"WASM_IMAGEDIGEST=" + .repoDigests[0] + "\n" +
"REDIS_IMAGEREF=" + .repoDigests[0]' <<< "$json")"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a copy&paste error?

@@ -328,7 +332,8 @@ type ContainerOption func(*cri.ContainerConfig) error
func WithImage(image string) ContainerOption {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I can’t see any users of this.)

@@ -316,7 +316,7 @@ func (r *runtimeService) CreatePodSandbox(systemContext *types.SystemContext, po
if imageAuthFile != "" {
sourceCtx.AuthFilePath = imageAuthFile
}
ref, err = r.storageImageServer.PullImage(context.Background(), pauseImage, &ImageCopyOptions{
ref, _, err = r.storageImageServer.PullImage(context.Background(), pauseImage, &ImageCopyOptions{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably good enough because the pause image is ~trusted, and because MCO sets up the signature policy in a way that doesn’t let users loosen it, IIRC.

Ideally the returned repo@digest would be used to determine img below, so that the code uses exactly the just-pulled image.


And then the first return value of PullImage becomes unused and can be dropped entirely, simplifying the code.

Perhaps the repo@digest return value should be a RegistryImageReference, not a raw reference.Canonical.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #8590.

//
// Arguments:
// - ctx: The context for controlling the function's execution
// - systemContext: server's system context for the given namespace
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…, notably might have a customized SignaturePolicyPath.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #8590.

}
}()

if err := svc.checkSignature(ctx, systemContext, policyContext, imageName, imageID); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I’m not sure why splitting this function into two is valuable, but it also doesn’t hurt.)

return nil
}

func (svc *imageService) checkSignature(ctx context.Context, sys *types.SystemContext, policyContext *signature.PolicyContext, imageName RegistryImageReference, imageID StorageImageID) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/imageName/userSpecifiedImage/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #8590.

return nil, fmt.Errorf("get context for namespace: %w", err)
}

if systemCtx.SignaturePolicyPath != "" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, do we want/need this condition here? It basically hard-codes the MCO behavior that the per-namespace policy is never more restrictive than the system policy.

That is fine for us right now, but it might not be true forever.

Does this exist for the container restore RootFSImage{Name,Ref} uses?


I guess that, at the very least, the two conditions (here and in the container restore path) should document this assumption.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented in #8590 .

Comment on lines +251 to +252
// and it is meaningless to try to verify an image that isn't even an image
// (like a checkpointed file is).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think we get here in the container restore path where Image.Image is at tar file; we have already successfully found a c/storage imgResult at this point.

@mtrmac
Copy link
Collaborator

mtrmac commented Sep 11, 2024

I have filed #8590 with various cleanups; I’d be happy to hand off finishing that.
And #8591 for possible new tests; I’m definitely leaving that part to CRI-O maintainers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. lgtm Indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants