containers / skopeo

Work with remote images registries - retrieving information, images, signing content
Apache License 2.0
8.03k stars 766 forks source link

copy: skopeo should look for sigstore-style signature artifacts by default #2061

Closed dmesser closed 1 year ago

dmesser commented 1 year ago

Found in version: skopeo v1.13.1

Reproducible: always

Expected behavior: when running skopeo copy or skopeo sync it should be possible to copy image signatures that were created with cosign as part of mirroring the actual image. For example, when running

skopeo copy docker://quay.io/dmesser/cosign-test:example docker://localhost:8080/testorg/cosign-test:example

with quay.io/dmesser/cosign-test:example containing a sigstore-style signature at quay.io/dmesser/cosign-test:sha256-1a937a8ac67aa71a1d7617153c27639986600d570a21b5e580270f70f690669f.sig I would expect skopeo that skopeo mirrors the image and the signature artifact to my destination registry by default, so that I can do a cosign verify on the destination image successfully. This is different from #1533 where skopeo on the fly creates a new sigstore-style signature. It would transparently handle the case when no signature artifact is found at the source. Optionally it can be asked to generate a warning when no signature is found.

As a user I want to be able to copy the images using skopeo from a source location along with its sigstore-style signature artifacts so that I can keep validating the trust chain of the image at the destination without making skopeo part of or aware of that trust chain.

It would rely on the same behavior that currently controls the treatment of simple-signing signatures via --remove-signatures. Later, this feature can be expanded by leveraging the OCI 1.1 Referrers API to optionally include any referring artifact (e.g. SBOMs, attestations, etc) during copy and sync operations at the users request.

Actual behavior: skopeo only copies the image referred to in source-image to the destination registry. I need to specifically craft a second copy command to also get the signature, which may not exist. By default I cannot run cosign verify at the destination with my original signing key/identity to ensure that the image hasn't changed or been tampered with during one or more copy steps.

mtrmac commented 1 year ago

Thanks for your report.

This works for me, if the registry/repo in question is configured in registries.d with use-sigstore-attachments (which is also required for skopeo --sign-by-sigstore*):

Getting image source signatures
DEBU[0001] Looking for sigstore attachments in quay.io/dmesser/cosign-test:sha256-1a937a8ac67aa71a1d7617153c27639986600d570a21b5e580270f70f690669f.sig 
…
DEBU[0001] Found a sigstore attachment manifest with 1 layers 
…
Storing signatures
…
DEBU[0002] Fetching sigstore attachment manifest failed, assuming it does not exist: reading manifest sha256-1a937a8ac67aa71a1d7617153c27639986600d570a21b5e580270f70f690669f.sig in DEST:5000/repo2/dest: manifest unknown 
…
DEBU[0002] Uploading sigstore attachment manifest       
DEBU[0002] PUT http://DEST:5000/v2/repo2/dest/manifests/sha256-1a937a8ac67aa71a1d7617153c27639986600d570a21b5e580270f70f690669f.sig

If enabling use-sigstore-attachments does not help, please provide more details, at the very least a --debug log.


Now, admittedly, that’s not enabled by default, but exactly because there is the OCI 1.1 referrers API, and the OCI 1.1 referrers backward compatibility mechanism (which differs from the sigstore tag convention), I don’t think it makes sense to look for all three on every image access/copy right now. The sigstore signatures are, AFAICT, just way too rare to pay that overhead; that might very well change over time — but if it does, one of the three mechanisms will probably become dominant, and it’s not clear to me which one.

So, for now, whether sigstore signatures are read, and how they are stored, requires explicit configuration in registries.d. (And the OCI 1.1 mechanisms are not yet implemented, though that’s coming hopefully soon.)

dmesser commented 1 year ago

Ok, with that background I was able to verify that this works. It only worked for me when I added the use-sigstore-attachments to both source and target registry below the docker directive. I would have expected it to work below docker-default as well. Is this expected?

This is very hard to discover from the documentation. The link to registries.d is wrong here: https://github.com/containers/skopeo/blob/main/docs/skopeo.1.md#files and use-sigstore-attachments coverage is thin: https://github.com/containers/image/blob/main/docs/containers-registries.d.5.md#individual-configuration-sections

What attachments are actually supported? The original PR said cosign-attachment, with sigstore-attachments, does this include SBOMs and in-toto attachments?

Also, what happens with images that do not have attachments with the setting set to true, will they be ignored or will the mirror fail?

I think we can close this issue, but the docs needs some love. If you can respond to the questions above, I am happy to create a PR.

mtrmac commented 1 year ago

I would have expected it to work below docker-default as well. Is this expected?

That’s how I have tested with your reproducer, and that’s how it worked for me. Note that the field is default-docker.


What attachments are actually supported?

Everything in .sig. Compare https://github.com/containers/image/issues/1946 .

Also, what happens with images that do not have attachments with the setting set to true, will they be ignored or will the mirror fail?

No, they will be treated as valid images with nothing attached. (policy.json may then cause their usage to be rejected.)


This is very hard to discover from the documentation.

That’s very likely. A PR would be great.

github-actions[bot] commented 1 year ago

A friendly reminder that this issue had no activity for 30 days.

mtrmac commented 1 year ago

The link to registries.d is wrong here: https://github.com/containers/skopeo/blob/main/docs/skopeo.1.md#files

I have filed https://github.com/containers/skopeo/pull/2103 to fix that.

More documentation / features would probably happen in the c/image repo of the underlying implementation.