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

Attaching the SBOM and provenance artifact to the Image artifact #1260

Open
wieringen opened this issue Nov 15, 2024 · 13 comments
Open

Attaching the SBOM and provenance artifact to the Image artifact #1260

wieringen opened this issue Nov 15, 2024 · 13 comments

Comments

@wieringen
Copy link

wieringen commented Nov 15, 2024

When I use oras to attach an artifact to an image artifact, it's displayed in a parent/child relation in the UI of Google Cloud Artifact registry.
Image

oras attach --artifact-type doc/example repo/image:digest sbom.json

When I use build-push-action this is not the case. The provenance and sbom artifacts are displayed like normal artifacts and no relationship is visible at first glance.
Image

After comparing some of the manifests, I noticed that oras adds a field called subject to the manifest of the sbom and provenance artifacts with a reference to the digest of the image.
"subject": { "mediaType": "application/vnd.oci.image.index.v1+json", "digest": "sha256:the_digest_of_the_image", "size": 856 },
Can this be done by build-push-action as well?

@crazy-max
Copy link
Member

Can we pull these images to take a look?

Fyi attestations are attached to the root image index, see https://docs.docker.com/build/metadata/attestations/attestation-storage/#attestation-manifest-descriptor

@dvdksn
Copy link
Contributor

dvdksn commented Nov 15, 2024

🤔 Looks like subject was added (to index and manifest) in image spec 1.1.0

@wieringen
Copy link
Author

wieringen commented Nov 15, 2024

Can we pull these images to take a look?

Fyi attestations are attached to the root image index, see https://docs.docker.com/build/metadata/attestations/attestation-storage/#attestation-manifest-descriptor

I'm sorry the images are private. Luckily, it's very easy to replicate.
oras attach --artifact-type doc/example --annotation "key1=val1" --annotation "key2=val2" localhost:5000/hello:v1

Point this at any existing image you have, and it will create an attached artifact at that location.

I know I can look at the manifest to see what kind of artifact it is, but this is a bit of a hassle. There is too much noise at the moment.

@crazy-max
Copy link
Member

crazy-max commented Nov 19, 2024

, it's very easy to replicate.
oras attach --artifact-type doc/example --annotation "key1=val1" --annotation "key2=val2" localhost:5000/hello:v1

Not sure I understand, with buildkit attestations are already attached to the image index like this one: https://explore.ggcr.dev/?image=moby%2Fbuildkit%3Alatest (see this manifest https://explore.ggcr.dev/?image=moby/buildkit@sha256:e9bbe9e3b33be6d4a396fd92bdd03e050d1a8325e0205e87d7aec3c9b81bc243&mt=application%2Fvnd.oci.image.manifest.v1%2Bjson&size=1113)

@dvdksn
Copy link
Contributor

dvdksn commented Nov 19, 2024

@crazy-max IIUC, the attestation manifest can have a subject descriptor that points to the image's index.

@wieringen
Copy link
Author

@crazy-max IIUC, the attestation manifest can have a subject descriptor that points to the image's index.

Exactly! At the moment, only the parent manifest is pointing at the child. It would be great if we can make the child point at the parent as well by adding this subject field.

@crazy-max
Copy link
Member

Exactly! At the moment, only the parent manifest is pointing at the child. It would be great if we can make the child point at the parent as well by adding this subject field.

Ah right sorry I misunderstood, I will take a look on buildkit side.

@crazy-max
Copy link
Member

I took a look on buildkit repo and the subject of the attestation should be set to be the same digest as the target manifest described in the Attestation Manifest Descriptor

With this image for example: https://explore.ggcr.dev/?image=crazymax/diun@sha256:28e86edddcfd912e5122327c7df9bff3f313f1b7bcdfaf178c0bca7ffa21e587&mt=application%2Fvnd.oci.image.index.v1%2Bjson&size=4661 we got this OCI index:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
      "platform": {
        "architecture": "386",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:49833bd7eb9aa57ee06aa6f07ce42ca89dd04c0e938520ab0333fc8a1b08a8c2",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:7bd6d73661700c5742b7e9dc603cc47b80198c1e09afdde00625a22569cdefa6",
      "platform": {
        "architecture": "arm",
        "os": "linux",
        "variant": "v6"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:3d794cb8e715b3fcb017929382fc3896579e62ff654e00f9054e96106c3e9aa3",
      "platform": {
        "architecture": "arm",
        "os": "linux",
        "variant": "v7"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:757ddf46aededfb8996bd9d7b3bf514a1dadb54e8b0bb5c1617b6a0b6299d7bf",
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:3f3111c7752a7704ff1916cd707b74c995eff024a82e6e3e71684c980560581b",
      "platform": {
        "architecture": "ppc64le",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:c490f8c73877edb8daa03f3da2f3da58bd7ce1624eb277b4d982bfea6c07f1a7",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:a71451558d6f8edb86e0df724e24f53577b41d8a8507b4e492fc40885e582f0d",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:49833bd7eb9aa57ee06aa6f07ce42ca89dd04c0e938520ab0333fc8a1b08a8c2",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:96f1c38e83d475fa5a0be6cfa6d1db8eb62f8cd05defeb1ce0eef1feb56b46ee",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:7bd6d73661700c5742b7e9dc603cc47b80198c1e09afdde00625a22569cdefa6",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:c93fe593023b289b7096531d0e4cafff5995c450173da960c38c2b17b133d2cb",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:3d794cb8e715b3fcb017929382fc3896579e62ff654e00f9054e96106c3e9aa3",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:fe54d1223bfafcb71acddb0e9cc1d49ec6bac4f1c30c4f8a68e3690c04ab5876",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:757ddf46aededfb8996bd9d7b3bf514a1dadb54e8b0bb5c1617b6a0b6299d7bf",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:995178b6384802311a70c53473c150d4c0c60e1148e33c7641cacea2c35c5a9c",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:3f3111c7752a7704ff1916cd707b74c995eff024a82e6e3e71684c980560581b",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    }
  ]
}

Looking at linux/386 platform and its digest sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9:

    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 865,
      "digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
      "platform": {
        "architecture": "386",
        "os": "linux"
      }
    },

We have this attestation manifest attached (referred by "vnd.docker.reference.digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"):

    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:c490f8c73877edb8daa03f3da2f3da58bd7ce1624eb277b4d982bfea6c07f1a7",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },

See https://explore.ggcr.dev/?image=crazymax/diun@sha256:c490f8c73877edb8daa03f3da2f3da58bd7ce1624eb277b4d982bfea6c07f1a7&mt=application%2Fvnd.oci.image.manifest.v1%2Bjson&size=841

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 241,
    "digest": "sha256:ccb4a793c99abd5b62a00846e5e9c4331a8b879d93c8bb7a625b6961e0ce0ee6"
  },
  "layers": [
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 1097777,
      "digest": "sha256:7bbc6bc3947181ce99de5585a371cd45a704be70b183b2bc006bb10ed5546ab2",
      "annotations": {
        "in-toto.io/predicate-type": "https://spdx.dev/Document"
      }
    },
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 94175,
      "digest": "sha256:157654f333f0d5bb80cb203ae0c247d4a04f54470f2321f815ae7799195b19ea",
      "annotations": {
        "in-toto.io/predicate-type": "https://slsa.dev/provenance/v0.2"
      }
    }
  ]
}

Looking at the SBOM or provenance layers content:

{
  "subject": [
    {
      "name": "pkg:docker/crazymax/[email protected]?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/crazymax/[email protected]?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/crazymax/diun@4?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/crazymax/diun@latest?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/ghcr.io/crazy-max/[email protected]?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/ghcr.io/crazy-max/[email protected]?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/ghcr.io/crazy-max/diun@4?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    },
    {
      "name": "pkg:docker/ghcr.io/crazy-max/diun@latest?platform=linux%2F386",
      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }
    }
  ],

We can see the subject is set and linked to the parent:

      "digest": {
        "sha256": "33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9"
      }

@wieringen
Copy link
Author

wieringen commented Nov 26, 2024

Thank you for investigating! Ah ok, so the subject field is added, but at a lower level. Google Artifact Registry is expecting this field in the attestation manifest. Something like:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 241,
    "digest": "sha256:ccb4a793c99abd5b62a00846e5e9c4331a8b879d93c8bb7a625b6961e0ce0ee6"
  },
  "layers": [
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 1097777,
      "digest": "sha256:7bbc6bc3947181ce99de5585a371cd45a704be70b183b2bc006bb10ed5546ab2",
      "annotations": {
        "in-toto.io/predicate-type": "https://spdx.dev/Document"
      }
    },
    {
      "mediaType": "application/vnd.in-toto+json",
      "size": 94175,
      "digest": "sha256:157654f333f0d5bb80cb203ae0c247d4a04f54470f2321f815ae7799195b19ea",
      "annotations": {
        "in-toto.io/predicate-type": "https://slsa.dev/provenance/v0.2"
      }
    }
  ],


  "subject": { 
    "digest":"sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9", 
  }
}

@crazy-max
Copy link
Member

@wieringen We had an internal discussion about this today and smth like this would be probably fine:

    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 841,
      "digest": "sha256:c490f8c73877edb8daa03f3da2f3da58bd7ce1624eb277b4d982bfea6c07f1a7",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      },
      "subject": {
        "mediaType": "application/vnd.oci.image.manifest.v1+json",
        "digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
        "size": 865
      },
      "annotations": {
        "vnd.docker.reference.digest": "sha256:33a4e98eda1be1709b8d3b1ccd7f2e68bf2ba6bad91bf8e365abf1d80d4cabe9",
        "vnd.docker.reference.type": "attestation-manifest"
      }
    },

@wieringen
Copy link
Author

wieringen commented Nov 26, 2024

That sounds great! I don't understand how the snippet in your latest comment relates to your example. From my (limited) understanding, the subject field should be added at the root of this file.

https://explore.ggcr.dev/?image=crazymax/diun@sha256:c490f8c73877edb8daa03f3da2f3da58bd7ce1624eb277b4d982bfea6c07f1a7&mt=application%2Fvnd.oci.image.manifest.v1%2Bjson&size=841

Or am I missing something?

@dvdksn
Copy link
Contributor

dvdksn commented Nov 28, 2024

@wieringen correct. So subject would point to the manifest of the corresponding image, not the index as oras seems to do.

@crazy-max
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants