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

Native SBOM Export support #11693

Open
naderman opened this issue Oct 19, 2023 · 22 comments
Open

Native SBOM Export support #11693

naderman opened this issue Oct 19, 2023 · 22 comments
Labels
Milestone

Comments

@naderman
Copy link
Member

naderman commented Oct 19, 2023

Composer should have a built in command to export an SBOM (Software Bill of Materials). Need to still work out what format(s) to support and what kind of options may be necessary to make this useful.

@fredden

This comment has been minimized.

@paolomainardi
Copy link

Thanks Nils, the first question I have, should the integration of an external Golang dependency (Like Anchore Syft) could be an option ? I don't think it is a good option anyway.

Otherwise other PHP-based options to look into are:

  1. https://github.com/CycloneDX/cyclonedx-php-composer
  2. https://github.com/composer/spdx-licenses this one just talks about licenses but I suspect it can be expanded to work with other metadata too.

@naderman
Copy link
Member Author

@fredden yes, sorry made this in a hurry just to have a reference point, updated the issue now.

@naderman
Copy link
Member Author

@paolomainardi Adding a golang dependency is definitely not an option. Those two you mention would have been my starting point too. Question is a bit if we want to/need to pick one or if we want to support multiple options?

@paolomainardi
Copy link

For the third-party Golang binary, it's agreeable and understandable; I just wanted to be sure before getting out the idea from the table.

That was my question, too; binding to only CycloneDX or SPDX is limiting and opinionated. The best would be having a way to choose your preferred format from the most used ones, with the downside of maintaining ideally much more code.

Before considering a custom solution, I would like to dive deep into Syft/Trivy/BOM to understand how they solved this issue.

I can do that and come back with some findings.

@stof
Copy link
Contributor

stof commented Oct 19, 2023

https://github.com/composer/spdx-licenses is not a SBOM solution at all. It is a validator for SPDX license identifiers (which is already used inside composer, which is the reason why it was created in the first place).

@paolomainardi
Copy link

Ok thanks for clarifying @stof

@jkowalleck
Copy link

jkowalleck commented Oct 20, 2023

👋 Hi there,
if you have any question regarding SBOM or CycloneDX, reach out to me, as I am a member of the CycloneDX Core Working Group and the author/maintainer of the PHP standard implementations in this subject.
I helped the npm and the conan2 team to implement native/first party support for SBOM/CycloneDX.

Before considering a custom solution, I would like to dive deep into Syft/Trivy/BOM to understand how they solved this issue.

Just read how https://github.com/CycloneDX/cyclonedx-php-composer works. It is a plugin for composer that utilizes composer's internals.

Previous feature requests for native SBOM support in compoer: #8251

@paolomainardi
Copy link

Ok thanks @jkowalleck I will reach out to you soon, thanks.

The question was mostly related to how support multiple formats, like the other tools I mentioned above and how they handle (if they) convert from/to different formats.

@ktomk
Copy link
Contributor

ktomk commented Oct 22, 2023

@naderman as you're asking for the format and native is in the title, the file format should be JSON Text based as the rest in Composer.

And what would be useful is to seal the project incl. vendor as otherwise an SBOM would not make much sense as being only volatile and temporal, not manifested. Which makes me thinking: It could be part of the lock file as it contains already a "bill of materials" and then an SBOM would be from that transaction. That would indeed be a benefit of being native in Composer, as it could be made part of the update process and taking care of the vendor folder remains the obligation of the user (as well as taking care of the lock file itself etc.), so no overhead of sealing it etc. natively in Composer, as it is not needed.

Once solved per a root project, it could be made reciprocal and then each composer.json can ship with their bill and per each vendor folder, the information collected. So there could be for package authors an option to commit/export the SBOM from the lock file to the composer.json file for publishing.

Just my 2 cents.

@stof
Copy link
Contributor

stof commented Oct 23, 2023

Dependencies don't have a lock file (nor a vendor folder)

@theofidry
Copy link
Contributor

theofidry commented Oct 24, 2023

After an initial round of testing within Box, I think:

  • It is best to keep it out of the composer.lock:
    • it is an artifact on its own with different rules, constraints and purpose. Maybe there is a ideal world where it could be completely re-used for composer.lock, but I'm also afraid of how difficult it would be to conciliate the two.
    • it would likely require non-trivial changes to the .lock, which in turn can break a number of plugins in the wild. In practice we know the .lock is not covered by the Composer BC policy, but there is also no reason to add more friction unless worth it.
    • A .lock file can be skipped (composer.json#lock=false) and you likely will want to dissociate the SBOM file from it.
  • Choice of the format: personally unless making the XML out of the JSON one is incredibly difficult, I would suggest the JSON, at the very least as the default, as it is already a required extension to have Composer working unlike XML.
  • For various purposes, it is likely valuable to have a dedicated Composer command to generate the SBOM. This could also provide the flexibility to generate one in a different spec/format if needed; The version/format used could also be configured within composer.json, but having those as part of the command options would allow to generate a different one if desired (e.g. a one time thing before publishing the app or for testing purposes).
  • Regarding the artifact itself, personally I have no opinion as to whether it should be next to the composer.lock or to the installed.php
  • I feel the current API of https://github.com/CycloneDX/cyclonedx-php-composer could be streamlined a bit. Ideally something along the lines of: See Native SBOM Export support #11693 (comment)
SBOMFactory::generate(
  CycloneDXVersion $version,
  CycloneDXFormat $format,
  array $decodedComposerJsonContent,
  ?array $decodedComposerLockContent, // May not be present, e.g. if skipped
  array $composerInstalledPhpContent,  // May not be present if deps are not installed; but I don't think you can have a reliable SBOM without
): string { ... };

In which case CycloneDX/cyclonedx-php-composer should likely be re-purposed to be made independent from the Composer plugin API. This would make its integration easier both within Composer itself and for other projects such as Box.

@jkowalleck
Copy link

jkowalleck commented Oct 24, 2023

I feel the current API of https://github.com/CycloneDX/cyclonedx-php-composer could be streamlined a bit. Ideally something along the lines of:

Whatever you are referring to, this is just wrong. The https://github.com/CycloneDX/cyclonedx-php-composer does NOT offer any public API.
Each and every structure of this project is marked as @internal mostly with an abstract that you should not use any structures outside the project.
It is even written in fat in the README here: https://github.com/CycloneDX/cyclonedx-php-composer#internals

It offers a CLI and nothing more, no API.

@theofidry
Copy link
Contributor

theofidry commented Oct 24, 2023

@jkowalleck sorry, honestly I don't know what's your beef, I'm trying to provide helpful feedback, maybe stop a bit with "no this is wrong/hijicking" kind of attitude?

I am not as organised or I sometimes struggle to articulate my thoughts, apologies for it. But also that's just who I am, no need to be aggressive or take it as if I purposely do this to rub you off the wrong way. And at some point, you can also take the feedback and re-organise it to fit your standards. If you can't, then let's please ignore each other for both of our sake, it's draining on me too.


On your comment regarding the package, then let's me scratch:

I feel the current API of https://github.com/CycloneDX/cyclonedx-php-composer could be streamlined a bit. Ideally something along the lines of:

To:

I find the consumer API offered by https://github.com/CycloneDX/cyclonedx-php-composer inadequate for the purpose of integrating CycloneDX within Composer†/Box/other third party††.

†: I have no authority there, it is only my opinion given my limited knowledge of how Composer works.
††: I take Box as a "random third-party".

What I think would help is the following API (same as suggested above):

SBOMFactory::generate(
  CycloneDXVersion $version,
  CycloneDXFormat $format,
  array $decodedComposerJsonContent,
  ?array $decodedComposerLockContent, // May not be present, e.g. if skipped
  array $composerInstalledPhpContent,  // May not be present if deps are not installed; but I don't think you can have a reliable SBOM without
): string { ... };

It could be an interface, doesn't need to be static... This is details, I think the above captures well enough the intent and need.

Given such a package exposing this API, then be it Composer/Box or even the current https://github.com/CycloneDX/cyclonedx-php-composer, would IMO be easier.

@jkowalleck
Copy link

jkowalleck commented Oct 25, 2023

@theofidry, I very sorry, I did not mean to offend you personally.
I critiqued the previously provided information, as it was false claims. Should not point out that things are wrong?

I am sure you had the best intention with your post, and you will find my reaction purely and fact-based, focussing on the idea and not on the person that wrote it. (for example, I wrote "this is just wrong", not "you are just wrong").
I did not intend to address my message to you personally (this is why I did not even mention you in the article, unlike this time), it was addressed to every reader who might got on the wrong track by previous false claims or misleading ideas.

If my language sound rude to your ears, this might be because English is a pidgin language for me. I am no native speaker.
Are we cool? ❤️


I find the consumer API offered by https://github.com/CycloneDX/cyclonedx-php-composer inadequate for the purpose

Which one?
There is no consumer API offered by https://github.com/CycloneDX/cyclonedx-php-composer at all.
The project offers a CLI and nothing more. The internals are not for public use, as described here, here and here.
I already explained to you, @theofidry, that this specific project is targeting proper composer projects, not your box-related edge case build processes/purpose (see below) nor is it for any non-composer-specific setups.
You may read my answers again here, here and here

Could we please stop talking about utilizing https://github.com/CycloneDX/cyclonedx-php-composer in the first place?
It is a de facto reference implementation for generating SBOMs from composer projects.
In its current state, it integrates with composer, it is not an implementation to consider integrating into composer/box/other third party.

This is no personal offense:
Please refrain from proposing changes to https://github.com/CycloneDX/cyclonedx-php-composer
so that it meats your needs for box.
I feel bad for you, since you failed to adopt the SBOM features that were submitted by your community, so https://github.com/llaville/box-manifest was created. So I understand your need for a native SBOM support in composer.


Since we are all here to improve composer, let's be constructive.

Based on analysis of box and other projects I encountered during my years of work on https://github.com/CycloneDX/cyclonedx-php-composer I saw the following:
There are projects out there, that drop/move/rename essential composer-related files/folders.

  • on "build time", they keep only the vendor folder, they remove composer.json and remove composer.lock and remove vendor/composer/installed.*;
    and they want to generate SBOM after build time.
  • on "build time", they remove not all but some parts of the things mentioned above,
    and they generate SBOM after build time.
  • they move/rename the vendor folder elsewhere (which was no problem if it was announced in vendor-dir config )

The previous mentioned edge cases exist.
It is to the composer team, to consider if they find it reasonable and technical feasible to generate SBOMs for such contexts.
(The take of https://github.com/CycloneDX/cyclonedx-php-composer is to only support such cases to a technically feasible extend, as they could simply generate the SBOM before they modify/"build" the project.)

@theofidry, could you take box as a "random third-party", and explain the edge cases you need to tackle when you "build"/"bundle" phar files with box? I am sure you've seen a lot of broken project setups that you want to be supported.

Question to all: what are your expectations on the SBOM idea here?
What types of edge cases should be considered? What is the expected outcome/quality for an SBOM?

@Seldaek Seldaek added this to the Nice To Have milestone Oct 25, 2023
@Seldaek
Copy link
Member

Seldaek commented Oct 25, 2023

Just a few thoughts here:

  • If people remove lock file or composer.json, then a native/built-in Composer SBOM solution would stop working. That's on them and I will not waste time supporting these cases.
  • cyclonedx/cyclonedx-library requires php 8.1, which is not great considering Composer requires 7.2.
  • Our use case would only require a small subset of what CycloneDX-library does though, like we only need JSON export to the latest version (or let's say any given version) of the format, not all versions. No need to be able to read these files at all IMO. So I hope we may be able to make a bespoke export solution that isn't too complex? But I haven't looked in much detail at the CycloneDX format yet.
  • The other option is to just let anyone interested in this use the plugin which already exists.. It's not as nice as shipping this natively for sure but at least it's there.

@theofidry
Copy link
Contributor

theofidry commented Oct 25, 2023

@jkowalleck maybe I too thinks too much to the heart as well, as there was no ill intent, I apologize as well and let's move forward with this project!


There are projects out there, that drop/move/rename essential composer-related files/folders. [...] It is to the composer team, to consider if they find it reasonable and technical feasible to generate SBOMs for such contexts.

I think for the most part, if the SBOM is dumped alongside the installed.php and will be good enough for most cases.

In the case of PHARs specifically (generated by Box or not), which remains today a very popular method to distribute PHP CLI applications, it will also likely be good enough for most scenarios.

could you take box as a "random third-party", and explain the edge cases you need to tackle when you "build"/"bundle" phar files with box? I am sure you've seen a lot of broken project setups that you want to be supported.

I think the answer largely depends on the answer to this question: if a bundling tool, in our case a PHAR bundler such as Box or Autoload, adds pieces of their own code to the built and distributed PHAR, are they required to have an entry in the SBOM? If yes to what degree?

For context, it is very common for a PHAR bundler to ship their own stub as the PHP default one is really bad. And in the case of Box there it goes further by adding its own (tiny and lightweight) application, the requirement checker, to improve the UX when the environment used fail to meet the requirements to execute the application bundled in the PHAR.

Otherwise, Box largely rely on the project to be a Composer project and for non Composer projects, or cases where the Composer files are removed, there is already extension points to manage it so I would say it falls under the responsibility of the user.

@theseer
Copy link

theseer commented Oct 30, 2023

I think the answer largely depends on the answer to this question: if a bundling tool, in our case a PHAR bundler such as Box or Autoload, adds pieces of their own code to the built and distributed PHAR, are they required to have an entry in the SBOM? If yes to what degree?

I cannot speak for others, but my aforementioned Autoload Project - as the name suggests - merely adds an autoloader as the stub when building a phar. Apart from that the tool needs some major refactoring it doesn't add anything else. While of course technically code, to me a map based autoloader is more a configuration than anything else. And it would be almost identical when not using a phar but my tool to generate the runtime map.

On the other hand: Do we consider the composer generated autoloader as something that needs to be represented in SBOMs? If so, we need to add some sort of entry for either. If not, there is nothing Autoload adds to the package.

@ktomk
Copy link
Contributor

ktomk commented Oct 31, 2023

On the other hand: Do we consider the composer generated autoloader as something that needs to be represented in SBOMs?

Probably, but what constitutes SBOM requirements differs greatly between projects and companies. In general a Composer package (whatever a package is) often is a PHP package and PHP is based on script files (apart from the binaries), therefore 100% path coverage looks legit to me. But I also know that such requirements differ and I can imagine for some projects it's enough if the SBOM is a listing of the packages only (again, whatever a package is) and everything else, including Composer, implicit and not required.

Maybe project maintainers that already have SBOM requirements can chime in and share some feedback from existing practice and tell their requirements are, how those evolved, the rationale behind and how they understand their practice and recommendations from lived practice? Perhaps the Fossology project now being a Composer project for quite some time already has such requirements and can share on that specifically? Just my 2 cents.

@paolomainardi
Copy link

I didn't have much time last week, but I plan to get aligned on the progress you discuss here in the next few days.

In the meantime, could this library https://github.com/CycloneDX/cyclonedx-php-library serve as a starting point for building a native solution?

UPDATE: I don't think so, it requires PHP >= 8.1 and as @Seldaek we have to support from 7.2 on.

@theofidry
Copy link
Contributor

@paolomainardi I would still suggest to use the library as a starting point. It probably will help out to flesh out the requirements and the DX desired.

@jkowalleck
Copy link

the library includes schema validators that you might utilize during your own development processes.
here is an example: https://github.com/CycloneDX/cyclonedx-php-library/blob/3bea464c9b8057d3a3924eac1f04a9db76282922/examples/build_and_serialize.php#L61

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

No branches or pull requests

9 participants