-
Notifications
You must be signed in to change notification settings - Fork 71
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
Add run image SBOM #186
base: main
Are you sure you want to change the base?
Add run image SBOM #186
Conversation
Maintainers, As you review this RFC please queue up issues to be created using the following commands:
Issues(none) |
0c1fd35
to
0e8719d
Compare
text/0000-run-image-sbom.md
Outdated
This RFC proposes the following - | ||
|
||
- A run image can contain a layer holding an SBOM (in format of CycloneDX or SBOM) of installed packages at `/sbom/bom.<ext>.json`, where `<ext>` will be `cdx` for CycloneDX documents and `spdx` for SPDX documents. These will initially be the only 2 supported SBOM types. | ||
- The digest of this layer is written as a `LABEL` on the corresponding run image with the key: `io.buildpacks.sbom`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that https://github.com/buildpacks/rfcs/blob/main/text/0095-sbom.md doesn't actually specify the label name for the layer containing the buildpack-provided SBOM. Maybe io.buildpacks.sbom.build
and io.buildpacks.sbom.base
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or io.buildpacks.sbom.buildpack
for buildpack-provided SBOM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My original intention was for this to be a key inside the lifecycle metadata label, but we can move it to a separate label if that helps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During our last discussion, we centered around:
io.buildpacks.app.sbom
for buildpack SBoMs label
io.buildpacks.base.sbom
for run-image SBoM label
text/0000-run-image-sbom.md
Outdated
|
||
And a label with key of `io.buildpacks.sbom`, and value of the digest of this layer, stored as metadata on the run image. | ||
|
||
When the lifecycle comes across a run image with this label and valid digest, it will attempt to merge this SBOM with any SBOMs delivered by buildpacks (during the build phase) and output them at `/layers/config/<type>/sbom/bom.<ext>`, per [#RFC 95: SBOM](https://github.com/buildpacks/rfcs/blob/main/text/0095-sbom.md). Initially this merging will only be supported for CycloneDX as it has a well-defined and efficient way of merging multiple `bom` files. A reference implementation can be found at the [`cyclonedx-cli`](https://github.com/CycloneDX/cyclonedx-cli) project. In the future we may add support for merging SPDX `bom` files as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will this work for rebase? It might be helpful to be a bit more explicit about exactly how many SBOM layers there are, and what they hold. I am thinking that one layer for buildpack-provided SBOMs, another for run-image-provided SBOMs, and another containing the "merged" SBOMs (with a separate label containing the diff ID for each) would make this process more straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on the clarity around how merges would work around rebase. This was part of the reason I left this out of the original RFC since I didn't have a good enough idea on how to implement it while still keeping rebase fast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During our last discussion, we decided to keep merging out of scope for this RFC. As of right now, 2 sBOM layers (and 2 labels) are proposed: 1 for run-image, and 1 buildpack. Downstream tooling can do the "merging", if desired.
text/0000-run-image-sbom.md
Outdated
This RFC proposes the following - | ||
|
||
- A run image can contain a layer holding an SBOM (in format of CycloneDX or SBOM) of installed packages at `/sbom/bom.<ext>.json`, where `<ext>` will be `cdx` for CycloneDX documents and `spdx` for SPDX documents. These will initially be the only 2 supported SBOM types. | ||
- The digest of this layer is written as a `LABEL` on the corresponding run image with the key: `io.buildpacks.sbom`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My original intention was for this to be a key inside the lifecycle metadata label, but we can move it to a separate label if that helps.
text/0000-run-image-sbom.md
Outdated
|
||
And a label with key of `io.buildpacks.sbom`, and value of the digest of this layer, stored as metadata on the run image. | ||
|
||
When the lifecycle comes across a run image with this label and valid digest, it will attempt to merge this SBOM with any SBOMs delivered by buildpacks (during the build phase) and output them at `/layers/config/<type>/sbom/bom.<ext>`, per [#RFC 95: SBOM](https://github.com/buildpacks/rfcs/blob/main/text/0095-sbom.md). Initially this merging will only be supported for CycloneDX as it has a well-defined and efficient way of merging multiple `bom` files. A reference implementation can be found at the [`cyclonedx-cli`](https://github.com/CycloneDX/cyclonedx-cli) project. In the future we may add support for merging SPDX `bom` files as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on the clarity around how merges would work around rebase. This was part of the reason I left this out of the original RFC since I didn't have a good enough idea on how to implement it while still keeping rebase fast.
0e8719d
to
4817490
Compare
text/0000-run-image-sbom.md
Outdated
|
||
This RFC proposes the following - | ||
|
||
- A run image can contain a layer holding an SBOM (in format of CycloneDX or SPDX or Syft) of installed packages at `/cnb/sbom/bom.<ext>.json`, where `<ext>` will be `cdx` for CycloneDX documents, `spdx` for SPDX documents, and `syft` for Syft documents. These will initially be the only 3 supported SBOM types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest that we use /cnb/sbom/launch/bom.<ext>.json
, so that both the build-time and runtime SBoM could be included in the future, but that would make it difficult to use the same base image as both a runtime and build-time base image.
Ideally, the build-time and runtime base image SBoM could be included in the final image without needing to modify either of their corresponding layers.
Instead, maybe we could use /cnb/sbom/<id>.<ext>.json
, where <id>
is the first 8 characters of the original base image digest. E.g., /cnb/sbom/ef3945a2.cdx.json
.
Uniquely labeling the SBoM with a digest means that we could also include unextended SBoMs when the Dockerfiles RFC is implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put together a POC for attaching base image SBoMs in this format: https://github.com/sclevine/cnb-sbom
(You can also use it to read both base image and app layer SBoMs.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in Office Hours, on Nov 18, w/ @samj1912. There's disagreement about the complexity that this (the <id>
, 8 characters of original base image digest) would introduce.
--
edit: Based on the following, I'm retracting my comment above and re-introducing the <id>
format.
- A run image can contain a layer holding an SBOM (in format of CycloneDX or SPDX or Syft) of installed packages at `/cnb/sbom/bom.<ext>.json`, where `<ext>` will be `cdx` for CycloneDX documents, `spdx` for SPDX documents, and `syft` for Syft documents. These will initially be the only 3 supported SBOM types. | ||
- The digest of this layer is written as a `LABEL` on the corresponding run image with the key: `io.buildpacks.base.sbom`. | ||
- For the sake of parity, the digest of buildpack SBOM layers (created by lifecycle) is written as a `LABEL` on the corresponding run image with the key: `io.buildpacks.app.sbom`. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future, we may want to add a flag to lifecycle to include build-time SBoMs in the app image. We could use labels like io.buildpacks.build.base.sbom
and io.buildpacks.build.app.sbom
.
I don't think this means we should rename io.buildpacks.base.sbom
to io.buildpacks.launch.base.sbom
-- just thought it might be worth pointing this out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we may. I personally find it hard to base decisions purely on what may happen. I'd be curious if others explicitly have this use-case.
text/0000-run-image-sbom.md
Outdated
This RFC proposes the following - | ||
|
||
- A run image can contain a layer holding an SBOM (in format of CycloneDX or SPDX or Syft) of installed packages at `/cnb/sbom/bom.<ext>.json`, where `<ext>` will be `cdx` for CycloneDX documents, `spdx` for SPDX documents, and `syft` for Syft documents. These will initially be the only 3 supported SBOM types. | ||
- The digest of this layer is written as a `LABEL` on the corresponding run image with the key: `io.buildpacks.base.sbom`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the diffID instead of the digest, to match io.buildpacks.app.sbom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
4817490
to
0349697
Compare
Hey @aemengo! What's the status of this RFC? I haven't been able to attend the CNB working group meeting. I ask because I am working on a Paketo RFC that relies on this RFC, and wondering if you plan to make more changes and what the timeline is if so? Thanks!! |
@sophiewigmore Thank you for asking. Unfortunately, I'm afraid that more changes will be required on this RFC. At the very least, more discussion needs to happen. During our last working group meeting, we had concerns about the workflow of attaching a BOM to an already-built base image, and thereby polluting the image. As of right now, the timeline is unknown. If your Paketo RFC is pending Paketo concerns, it might be more expedient to move at your own pace. Finally, I want remind (in a non-patronizing way) that buildpack RFCs are soon to close when all the core team members have voted and the "Final Comment Period" status is applied. |
0349697
to
2e72469
Compare
26d8797
to
4347716
Compare
@aemengo really sorry to be going back and forth on this, but @natalieparellano and I were discussing the genpkgs implementation (https://buildpacks.slack.com/archives/CCP60GJLS/p1639669644077300) and it might make the implementation easier if the output file name did not use the digest - especially for implementing it in pack where the digest for the output run image may not be available until the lifecycle actually goes ahead and exports it (and in this case the lifecycle might have to export the output run image to the registry to get the digest). The other issue is that image digests are sometimes not preserved across registry transfers which makes it even more of an issue. I think we should instead solve it this way - use the diffid in the label and have the lifecycle ensure that it loads the bom from that diffid only if it is the last layer in the output image. |
Signed-off-by: Anthony Emengo <aemengo@vmware.com>
4347716
to
2e371b7
Compare
└── bom.<ext>.json | ||
``` | ||
|
||
And a label with key of `io.buildpacks.base.sbom`, and value of the diffID of this layer, stored as metadata on the run image. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also add the condition here that this must be the last layer on the image for the lifecycle to consider it a valid sbom? This is to prevent further extensions from re-using the same sbom.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please clarify. How would other extensions use an SBOM depending on the layer order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aemengo I meant something like the following -
let's say someone takes the above base run image with the SBOm and label+diffid and extends it as
FROM valid-run-image-with-sbom
USER root
RUN apt-get install my-package
This new image will still have the above specified SBOM and label with the appropriate diffid of the SBOM layer, but the SBOM will be incorrect/stale.
With my proposal, the above extension will cause other layers to be added after the SBOM layer which might be a good way to indicate to the lifecycle that the SBOM is potentially stale since the layer with the SBOM diffid won't be the last layer anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also add the condition here that this must be the last layer on the image for the lifecycle to consider it a valid sbom?
@samj1912 If we go this route maybe we can loosen this a little to be SHOULD? I think a warning might be sufficient here.
Also, I am not sure what "must" would imply here. Would the build/rebase fail? Would the lifecycle remove the io.buildpacks.base.sbom` entirely.
How will this work for Stack Extensions that replace the run image? |
|
||
## Tooling | ||
|
||
To facilitate adherence to this specification, the CNB project will create tooling that consumes a given run container image and a given SBOM json file, to create a new image with the SBOM information embedded at the correct location and diffID metadata attached. This allows for generation of SBOM files both within the image and outside it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this inteneded to be separate tooling or a part of pack
. I would like to see the answer that question in this RFC.
Once we know which sub-team is responsible I think it's fine to punt the details of the interface to a sub-team specific RFC but it would be good to align generally about who this RFC is handing the baton to.
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A Label is one alternative albeit an unappealing one b/c of the containerd label size issue.
An annotation is another alternative. The drawbacks to an annotation are consistency with buildpack-generated SBOM and the impossibility of doing something sensible in the daemon case.
@natalieparellano volunteering to take this over. |
Summary of WG Discussion 02/17/22 There is lingering discomfort around storing this SBOM in the run image because:
Although we can solve problem 1 with custom tooling. Problem 2 cannot be completely solved. While the lifecycle can use the layer order as a hint about whether the SBOM is out of date, the lifecycle cannot guarantee accuracy. Efforts to solve for or mitigate problem 1 and mitigate problem 2 feel like a waste of effort given problem 3. It feels especially bad to bake new temporary interfaces into the spec, given that we would like to move towards spec stability. We discussed moving the SBOM out of the run image, and making it a responsibility of the platform to supply an accurate run-image SBOM to the lifecycle for export, at which point it will be included in the sbom layer with the buildpacks generated SBOM. This free platforms up to be as strict or flexible as they want and to adapt to evolving specifications around sbom and attestation format/storage. (cc @samj1912 @natalieparellano @jabrown85 @sclevine @jromero ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ekcasey based on your latest comment do we have someone adopting this RFC to make the necessary changes or creating a superseding RFC? It sounds like we would still need an RFC for the SBOM contribution to the exporter.
Readable