box-project / box

πŸ“¦πŸš€ Fast, zero config application bundler with PHARs.
https://box-project.github.io/box
MIT License
1.12k stars 101 forks source link

Know more about PHAR build contents #841

Closed llaville closed 1 year ago

llaville commented 1 year ago

Feature Request

Those who know me a little, already know that I've tried in past to include a manifest into the official BOX project. Even if this feature is not available, a fork with patch was born : https://github.com/llaville/box-manifest

That allow to include in metadata field, the list of dependency constraints and versions installed. Something like this :

info

Now, with this feature request, I would like to ask if we could see the BOX version used to build the PHAR contents with the box info command. Contents such as we see with box --version command.

That will allow to learn more about PHAR version generated, and perharps diagnose possible issues !

What do you think about this little add-on ?

Box info command will look like:

Box version 4.2.0@afc3a47 2022-11-21 22:20:19 UTC
API Version: 1.1.0

Compression: GZ

Signature: SHA-1
Signature Hash: 6E7E8BD57996B6B907BD3606C5B5A3996ED068BF

Metadata:

Contents: 1487 files (11.91MB)

 // Use the --list|-l option to list the content of the PHAR.
theofidry commented 1 year ago

Hi @llaville!

I do remember your work on this, and had it in the back of my mind ever since then ;) Recently there's been some work on SBOM which in my mind is a perfect fit between what you're doing, and providing an internationally supported and understood format.

I briefly remember https://github.com/CycloneDX/cyclonedx-php-composer but ideally, after talking with Sebastian Bergmann, I think it is kind of expected of Composer to provide this at some point.

I unfortunately could not dig into any of this any further. I do not know if there is any alternative to cycloneDX, how it is expected to be shipped & co. Also even with it, I think it would be interesting to have a human readable format like you are proposing. But maybe this one can be based on the SBOM as the source of truth instead?

I am also not sure if this should be in the Metadata section and instead maybe it could be an entirely new section.

WDYT?

llaville commented 1 year ago

Hello ThΓ©o,

Thanks for your feedback and especially to point to me the SBOM standard solution. If it's related to my work on a PHAR manifest, I think it's could be pretty cool to have a possibility to embed such results into a PHAR. I don't think it may be too much difficult to have a bridge with https://github.com/CycloneDX/cyclonedx-php-library and my fork of BOX v4 (https://github.com/llaville/box-manifest). I'll investigate later, when I'll have finished the major rewrites of https://github.com/overtrue/phplint v9.0

But, this feature report is not to talk about a manifest or SBOM or something equivalent. No, this report is just to add a little version about the product maker (BOX v4), as an indicator like API version.

Always ready to heard your proposals about BOX. I like this project.

llaville commented 1 year ago

As my works on PHPLint 9.0 is over, I'll be able now to work on a version of BOX Manifest that support SBOM format. Keep an eye open, solution will come in next days ...

llaville commented 1 year ago

@theofidry Integration of CycloneDX SBOM feature is very easy. Code is ready for preview: Need more tests and polish for a final version !!!

An operational prototype is already available (see commit https://github.com/llaville/box-manifest/commit/75fd43731c6b5722e8aff5ba5b45cb4fe7d8d53b) on my repository (sbom branch).

IMPORTANT notes:

If you want to give it a try for another project than BOX-Manifest itself, don't forget to provide --boostrap vendor/autoload.php (to load your project autoloader) on box compile invocation.

But If you review code of static manifest builder calls, a new specification may be include easily : https://github.com/llaville/box-manifest/blob/sbom/src/Composer/ManifestFactory.php#L97-L105

Here are some examples of SBOM manifest production:

XML format (for specification 1.3)

With "metadata": "Bartlett\\BoxManifest\\Composer\\ManifestFactory::toSbomXml1dot3" setting in your box.json config file

Output of `box compile` command ```text Box version 4.2.0@afc3a47 // Loading the configuration file "/shared/backups/bartlett/box-manifest/box.json". πŸ”¨ Building the PHAR "/shared/backups/bartlett/box-manifest/box-manifest.phar" ? No compactor to register ? Adding main file: /shared/backups/bartlett/box-manifest/bin/box ? Adding requirements checker ? Adding binary files > 24 file(s) ? Auto-discover files? No ? Exclude dev files? Yes ? Adding files > 3181 file(s) ? Generating new stub - Using shebang line: #!/usr/bin/env php - Using banner: > Generated by Humbug Box 4.2.0@afc3a47. > > @link https://github.com/humbug/box ? Setting metadata - Using composer.json : /shared/backups/bartlett/box-manifest/composer.json - Using composer.lock : /shared/backups/bartlett/box-manifest/composer.lock - ? Dumping the Composer autoloader ... MORE ... ```

JSON format (for specification 1.3)

With "metadata": "Bartlett\\BoxManifest\\Composer\\ManifestFactory::toSbomJson1dot3" setting in your box.json config file

Output of `box compile` command ```text Box version 4.2.0@afc3a47 // Loading the configuration file "/shared/backups/bartlett/box-manifest/box.json". πŸ”¨ Building the PHAR "/shared/backups/bartlett/box-manifest/box-manifest.phar" ? No compactor to register ? Adding main file: /shared/backups/bartlett/box-manifest/bin/box ? Adding requirements checker ? Adding binary files > 24 file(s) ? Auto-discover files? No ? Exclude dev files? Yes ? Adding files > 3181 file(s) ? Generating new stub - Using shebang line: #!/usr/bin/env php - Using banner: > Generated by Humbug Box 4.2.0@afc3a47. > > @link https://github.com/humbug/box ? Setting metadata - Using composer.json : /shared/backups/bartlett/box-manifest/composer.json - Using composer.lock : /shared/backups/bartlett/box-manifest/composer.lock - { "$schema": "http://cyclonedx.org/schema/bom-1.3.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3", "version": 1, "components": [ { "bom-ref": "BomRef.63e4d9734534f6.38451246", "type": "library", "name": "bartlett/box-manifest", "version": "2.x-dev@781abd9", "description": "Create a manifest to a PHP Archive (PHAR) for the BOX project (https://github.com/box-project/box)", "licenses": [ { "license": { "id": "MIT" } } ], "purl": "pkg:pkg/composer/bartlett/box-manifest@2.x-dev%40781abd9" }, { "bom-ref": "BomRef.63e4d9734535a9.32620257", "type": "library", "name": "amphp/amp", "version": "v2.6.2" }, { "bom-ref": "BomRef.63e4d9734535f1.45766001", "type": "library", "name": "amphp/byte-stream", "version": "v1.8.1" }, { "bom-ref": "BomRef.63e4d973453657.79591835", "type": "library", "name": "amphp/parallel", "version": "v1.4.2" }, { "bom-ref": "BomRef.63e4d9734536a1.53425918", "type": "library", "name": "amphp/parallel-functions", "version": "v1.1.0" }, { "bom-ref": "BomRef.63e4d9734536f5.01557534", "type": "library", "name": "amphp/parser", "version": "v1.1.0" }, { "bom-ref": "BomRef.63e4d973453749.60432189", "type": "library", "name": "amphp/process", "version": "v1.1.4" }, { "bom-ref": "BomRef.63e4d973453793.01513239", "type": "library", "name": "amphp/serialization", "version": "v1.0.0" }, { "bom-ref": "BomRef.63e4d9734537f3.95248878", "type": "library", "name": "amphp/sync", "version": "v1.4.2" }, { "bom-ref": "BomRef.63e4d973453844.80145505", "type": "library", "name": "composer/ca-bundle", "version": "1.3.5" }, { "bom-ref": "BomRef.63e4d973453893.65497216", "type": "library", "name": "composer/class-map-generator", "version": "1.0.0" }, { "bom-ref": "BomRef.63e4d9734538e5.83391063", "type": "library", "name": "composer/composer", "version": "2.5.2" }, { "bom-ref": "BomRef.63e4d973453943.58706484", "type": "library", "name": "composer/metadata-minifier", "version": "1.0.0" }, { "bom-ref": "BomRef.63e4d973453999.05140837", "type": "library", "name": "composer/pcre", "version": "3.1.0" }, { "bom-ref": "BomRef.63e4d9734539e6.55954756", "type": "library", "name": "composer/semver", "version": "3.3.2" }, { "bom-ref": "BomRef.63e4d973453a30.04146509", "type": "library", "name": "composer/spdx-licenses", "version": "1.5.7" }, { "bom-ref": "BomRef.63e4d973453a93.12001829", "type": "library", "name": "composer/xdebug-handler", "version": "3.0.3" }, { "bom-ref": "BomRef.63e4d973453ae7.40314373", "type": "library", "name": "cweagans/composer-patches", "version": "1.7.3" }, { "bom-ref": "BomRef.63e4d973453b35.57954406", "type": "library", "name": "cyclonedx/cyclonedx-library", "version": "v1.6.3" }, { "bom-ref": "BomRef.63e4d973453b84.91307449", "type": "library", "name": "fidry/console", "version": "0.5.5" }, { "bom-ref": "BomRef.63e4d973453bd9.85296233", "type": "library", "name": "humbug/box", "version": "4.2.0" }, { "bom-ref": "BomRef.63e4d973453c20.34079885", "type": "library", "name": "humbug/php-scoper", "version": "0.18.2" }, { "bom-ref": "BomRef.63e4d973453c80.84227468", "type": "library", "name": "jetbrains/phpstorm-stubs", "version": "v2022.3" }, { "bom-ref": "BomRef.63e4d973453cd2.53088170", "type": "library", "name": "justinrainbow/json-schema", "version": "5.2.12" }, { "bom-ref": "BomRef.63e4d973453d21.60672700", "type": "library", "name": "laravel/serializable-closure", "version": "v1.3.0" }, { "bom-ref": "BomRef.63e4d973453d76.20112253", "type": "library", "name": "nikic/iter", "version": "v2.2.0" }, { "bom-ref": "BomRef.63e4d973453dc8.14147066", "type": "library", "name": "nikic/php-parser", "version": "v4.15.3" }, { "bom-ref": "BomRef.63e4d973453e16.92947232", "type": "library", "name": "package-url/packageurl-php", "version": "1.0.4" }, { "bom-ref": "BomRef.63e4d973453e76.88297640", "type": "library", "name": "paragonie/constant_time_encoding", "version": "v2.6.3" }, { "bom-ref": "BomRef.63e4d973453ec2.07295699", "type": "library", "name": "paragonie/pharaoh", "version": "v0.6.0" }, { "bom-ref": "BomRef.63e4d973453f17.99014230", "type": "library", "name": "phpdocumentor/reflection-common", "version": "2.2.0" }, { "bom-ref": "BomRef.63e4d973453f67.86064717", "type": "library", "name": "phpdocumentor/reflection-docblock", "version": "5.3.0" }, { "bom-ref": "BomRef.63e4d973453fb4.10919146", "type": "library", "name": "phpdocumentor/type-resolver", "version": "1.6.2" }, { "bom-ref": "BomRef.63e4d973454015.51823671", "type": "library", "name": "phplang/scope-exit", "version": "1.0.0" }, { "bom-ref": "BomRef.63e4d973454063.32484167", "type": "library", "name": "psr/container", "version": "2.0.2" }, { "bom-ref": "BomRef.63e4d9734540b4.97123813", "type": "library", "name": "psr/event-dispatcher", "version": "1.0.0" }, { "bom-ref": "BomRef.63e4d973454105.15869587", "type": "library", "name": "psr/log", "version": "3.0.0" }, { "bom-ref": "BomRef.63e4d973454155.62619226", "type": "library", "name": "react/promise", "version": "v2.9.0" }, { "bom-ref": "BomRef.63e4d9734541a6.08183031", "type": "library", "name": "seld/jsonlint", "version": "1.9.0" }, { "bom-ref": "BomRef.63e4d973454205.28327426", "type": "library", "name": "seld/phar-utils", "version": "1.2.1" }, { "bom-ref": "BomRef.63e4d973454251.29611770", "type": "library", "name": "seld/signal-handler", "version": "2.0.1" }, { "bom-ref": "BomRef.63e4d9734542a2.89308850", "type": "library", "name": "swaggest/json-diff", "version": "v3.10.4" }, { "bom-ref": "BomRef.63e4d9734542f6.01989774", "type": "library", "name": "swaggest/json-schema", "version": "v0.12.41" }, { "bom-ref": "BomRef.63e4d973454342.28675285", "type": "library", "name": "symfony/console", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d973454391.75533651", "type": "library", "name": "symfony/deprecation-contracts", "version": "v3.2.0" }, { "bom-ref": "BomRef.63e4d9734543e6.61754380", "type": "library", "name": "symfony/event-dispatcher-contracts", "version": "v3.2.0" }, { "bom-ref": "BomRef.63e4d973454446.81767806", "type": "library", "name": "symfony/filesystem", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d973454492.30985668", "type": "library", "name": "symfony/finder", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d9734544e5.23377575", "type": "library", "name": "symfony/polyfill-ctype", "version": "v1.27.0" }, { "bom-ref": "BomRef.63e4d973454538.15317547", "type": "library", "name": "symfony/polyfill-intl-grapheme", "version": "v1.27.0" }, { "bom-ref": "BomRef.63e4d973454588.49421534", "type": "library", "name": "symfony/polyfill-intl-normalizer", "version": "v1.27.0" }, { "bom-ref": "BomRef.63e4d9734545d6.10792906", "type": "library", "name": "symfony/polyfill-mbstring", "version": "v1.27.0" }, { "bom-ref": "BomRef.63e4d973454627.86577271", "type": "library", "name": "symfony/polyfill-php73", "version": "v1.27.0" }, { "bom-ref": "BomRef.63e4d973454688.53312552", "type": "library", "name": "symfony/process", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d9734546d6.66926150", "type": "library", "name": "symfony/serializer", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d973454722.78083635", "type": "library", "name": "symfony/service-contracts", "version": "v3.2.0" }, { "bom-ref": "BomRef.63e4d973454771.20632414", "type": "library", "name": "symfony/string", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d9734547c2.51140716", "type": "library", "name": "symfony/var-dumper", "version": "v6.2.5" }, { "bom-ref": "BomRef.63e4d973454816.67915846", "type": "library", "name": "thecodingmachine/safe", "version": "v2.4.0" }, { "bom-ref": "BomRef.63e4d973454869.33785473", "type": "library", "name": "ulrichsg/getopt-php", "version": "v3.4.0" }, { "bom-ref": "BomRef.63e4d9734548c4.95591137", "type": "library", "name": "webmozart/assert", "version": "1.11.0" } ], "dependencies": [ { "ref": "BomRef.63e4d9734534f6.38451246" }, { "ref": "BomRef.63e4d9734535a9.32620257" }, { "ref": "BomRef.63e4d9734535f1.45766001" }, { "ref": "BomRef.63e4d973453657.79591835" }, { "ref": "BomRef.63e4d9734536a1.53425918" }, { "ref": "BomRef.63e4d9734536f5.01557534" }, { "ref": "BomRef.63e4d973453749.60432189" }, { "ref": "BomRef.63e4d973453793.01513239" }, { "ref": "BomRef.63e4d9734537f3.95248878" }, { "ref": "BomRef.63e4d973453844.80145505" }, { "ref": "BomRef.63e4d973453893.65497216" }, { "ref": "BomRef.63e4d9734538e5.83391063" }, { "ref": "BomRef.63e4d973453943.58706484" }, { "ref": "BomRef.63e4d973453999.05140837" }, { "ref": "BomRef.63e4d9734539e6.55954756" }, { "ref": "BomRef.63e4d973453a30.04146509" }, { "ref": "BomRef.63e4d973453a93.12001829" }, { "ref": "BomRef.63e4d973453ae7.40314373" }, { "ref": "BomRef.63e4d973453b35.57954406" }, { "ref": "BomRef.63e4d973453b84.91307449" }, { "ref": "BomRef.63e4d973453bd9.85296233" }, { "ref": "BomRef.63e4d973453c20.34079885" }, { "ref": "BomRef.63e4d973453c80.84227468" }, { "ref": "BomRef.63e4d973453cd2.53088170" }, { "ref": "BomRef.63e4d973453d21.60672700" }, { "ref": "BomRef.63e4d973453d76.20112253" }, { "ref": "BomRef.63e4d973453dc8.14147066" }, { "ref": "BomRef.63e4d973453e16.92947232" }, { "ref": "BomRef.63e4d973453e76.88297640" }, { "ref": "BomRef.63e4d973453ec2.07295699" }, { "ref": "BomRef.63e4d973453f17.99014230" }, { "ref": "BomRef.63e4d973453f67.86064717" }, { "ref": "BomRef.63e4d973453fb4.10919146" }, { "ref": "BomRef.63e4d973454015.51823671" }, { "ref": "BomRef.63e4d973454063.32484167" }, { "ref": "BomRef.63e4d9734540b4.97123813" }, { "ref": "BomRef.63e4d973454105.15869587" }, { "ref": "BomRef.63e4d973454155.62619226" }, { "ref": "BomRef.63e4d9734541a6.08183031" }, { "ref": "BomRef.63e4d973454205.28327426" }, { "ref": "BomRef.63e4d973454251.29611770" }, { "ref": "BomRef.63e4d9734542a2.89308850" }, { "ref": "BomRef.63e4d9734542f6.01989774" }, { "ref": "BomRef.63e4d973454342.28675285" }, { "ref": "BomRef.63e4d973454391.75533651" }, { "ref": "BomRef.63e4d9734543e6.61754380" }, { "ref": "BomRef.63e4d973454446.81767806" }, { "ref": "BomRef.63e4d973454492.30985668" }, { "ref": "BomRef.63e4d9734544e5.23377575" }, { "ref": "BomRef.63e4d973454538.15317547" }, { "ref": "BomRef.63e4d973454588.49421534" }, { "ref": "BomRef.63e4d9734545d6.10792906" }, { "ref": "BomRef.63e4d973454627.86577271" }, { "ref": "BomRef.63e4d973454688.53312552" }, { "ref": "BomRef.63e4d9734546d6.66926150" }, { "ref": "BomRef.63e4d973454722.78083635" }, { "ref": "BomRef.63e4d973454771.20632414" }, { "ref": "BomRef.63e4d9734547c2.51140716" }, { "ref": "BomRef.63e4d973454816.67915846" }, { "ref": "BomRef.63e4d973454869.33785473" }, { "ref": "BomRef.63e4d9734548c4.95591137" } ] } ? Dumping the Composer autoloader ... MORE ... ```
llaville commented 1 year ago

To validate contents of SBOM generated by CycloneDX, use the https://github.com/CycloneDX/cyclonedx-cli project.

With Docker version:

REPOSITORY                      TAG                IMAGE ID       CREATED         SIZE
cyclonedx/cyclonedx-cli         latest             9548cf5241e3   4 months ago    151MB

Run following command:

docker run --rm --user $(id -u):$(id -g) --mount type=bind,source=$PWD,target=/tmp -w /tmp cyclonedx/cyclonedx-cli validate --input-file sbom.xml

Change input file sbom.xml by sbom.json depending of format generated

And you will get expected result : BOM validated successfully.

llaville commented 1 year ago

@sebastianbergmann FYI : this purpose may interrest you even if I don't consider this as a PHPUnit issue. (I use actually the latest version 10.0.7)

The PHPUnit SBOM generation script => https://github.com/sebastianbergmann/phpunit/blob/10.0.7/build/scripts/phar-manifest.php#L54 use the CycloneDX solution (specification 1.4)

But it seems that the contents generated do not pass validation : at least with https://github.com/CycloneDX/cyclonedx-cli#validate-command (that support all specifications)

Here is my try :

With Docker image

REPOSITORY                TAG      DIGEST                                                                    IMAGE ID       CREATED         SIZE
cyclonedx/cyclonedx-cli   latest   sha256:c7d71852320da2d24fdc3f3dea8895b562e411cce43abb4c6817dc155bf54689   9548cf5241e3   4 months ago    151MB
phpunit-10.0.7.phar --sbom > phpunit-10.0.7-sbom.xml
Contents of `phpunit-10.0.7-sbom.xml` file ``` phpunit phpunit 10.0.7 The PHP Unit Testing framework. BSD-3-Clause pkg:composer/phpunit/phpunit@10.0.7 myclabs deep-copy 1.11.0 Create deep copies (clones) of your objects MIT pkg:composer/myclabs/deep-copy@1.11.0 nikic php-parser v4.15.3 A PHP parser written in PHP BSD-3-Clause pkg:composer/nikic/php-parser@v4.15.3 phar-io manifest 2.0.3 Component for reading phar.io manifest information from a PHP Archive (PHAR) BSD-3-Clause pkg:composer/phar-io/manifest@2.0.3 phar-io version 3.2.1 Library for handling version information and constraints BSD-3-Clause pkg:composer/phar-io/version@3.2.1 phpunit php-code-coverage 10.0.0 Library that provides collection, processing, and rendering functionality for PHP code coverage information. BSD-3-Clause pkg:composer/phpunit/php-code-coverage@10.0.0 phpunit php-file-iterator 4.0.0 FilterIterator implementation that filters files based on a list of suffixes. BSD-3-Clause pkg:composer/phpunit/php-file-iterator@4.0.0 phpunit php-invoker 4.0.0 Invoke callables with a timeout BSD-3-Clause pkg:composer/phpunit/php-invoker@4.0.0 phpunit php-text-template 3.0.0 Simple template engine. BSD-3-Clause pkg:composer/phpunit/php-text-template@3.0.0 phpunit php-timer 6.0.0 Utility class for timing BSD-3-Clause pkg:composer/phpunit/php-timer@6.0.0 sebastian cli-parser 2.0.0 Library for parsing CLI options BSD-3-Clause pkg:composer/sebastian/cli-parser@2.0.0 sebastian code-unit 2.0.0 Collection of value objects that represent the PHP code units BSD-3-Clause pkg:composer/sebastian/code-unit@2.0.0 sebastian code-unit-reverse-lookup 3.0.0 Looks up which function or method a line of code belongs to BSD-3-Clause pkg:composer/sebastian/code-unit-reverse-lookup@3.0.0 sebastian comparator 5.0.0 Provides the functionality to compare PHP values for equality BSD-3-Clause pkg:composer/sebastian/comparator@5.0.0 sebastian complexity 3.0.0 Library for calculating the complexity of PHP code units BSD-3-Clause pkg:composer/sebastian/complexity@3.0.0 sebastian diff 5.0.0 Diff implementation BSD-3-Clause pkg:composer/sebastian/diff@5.0.0 sebastian environment 6.0.0 Provides functionality to handle HHVM/PHP environments BSD-3-Clause pkg:composer/sebastian/environment@6.0.0 sebastian exporter 5.0.0 Provides the functionality to export PHP variables for visualization BSD-3-Clause pkg:composer/sebastian/exporter@5.0.0 sebastian global-state 6.0.0 Snapshotting of global state BSD-3-Clause pkg:composer/sebastian/global-state@6.0.0 sebastian lines-of-code 2.0.0 Library for counting the lines of code in PHP source code BSD-3-Clause pkg:composer/sebastian/lines-of-code@2.0.0 sebastian object-enumerator 5.0.0 Traverses array structures and object graphs to enumerate all referenced objects BSD-3-Clause pkg:composer/sebastian/object-enumerator@5.0.0 sebastian object-reflector 3.0.0 Allows reflection of object attributes, including inherited and non-public ones BSD-3-Clause pkg:composer/sebastian/object-reflector@3.0.0 sebastian recursion-context 5.0.0 Provides functionality to recursively process PHP variables BSD-3-Clause pkg:composer/sebastian/recursion-context@5.0.0 sebastian type 4.0.0 Collection of value objects that represent the types of the PHP type system BSD-3-Clause pkg:composer/sebastian/type@4.0.0 sebastian version 4.0.1 Library that helps with managing the version number of Git-hosted PHP projects BSD-3-Clause pkg:composer/sebastian/version@4.0.1 theseer tokenizer 1.2.1 A small library for converting tokenized PHP source code into XML and potentially other formats BSD-3-Clause pkg:composer/theseer/tokenizer@1.2.1 ```
docker run --rm --user $(id -u):$(id -g) --mount type=bind,source=$PWD,target=/tmp -w /tmp cyclonedx/cyclonedx-cli validate --input-file phpunit-10.0.7-sbom.xml

Prints

Unable to validate against any XML schemas.
BOM is not valid.
sebastianbergmann commented 1 year ago

This is not a useful and actionable error:

Unable to validate against any XML schemas. BOM is not valid.

Trying to use xmllint to validate PHPUnit's SBOM against the XSD fails with this error:

$ xmllint --schema cyclonedx-1.4.xsd sbom.xml --noout
error : Unknown IO error
warning: failed to load external entity "http://cyclonedx.org/schema/spdx"
cyclonedx-1.4.xsd:27: element import: Schemas parser warning : Element '{http://www.w3.org/2001/XMLSchema}import': Failed to locate a schema at location 'http://cyclonedx.org/schema/spdx'. Skipping the import.
cyclonedx-1.4.xsd:444: element element: Schemas parser error : element decl. '{http://cyclonedx.org/schema/bom/1.4}id', attribute 'type': The QName value '{http://cyclonedx.org/schema/spdx}licenseId' does not resolve to a(n) type definition.
WXS schema cyclonedx-1.4.xsd failed to compile

Not sure what is going on here. It would be helful to know what is actually wrong. But this should not be discussed here. I have opened https://github.com/sebastianbergmann/phpunit/issues/5186 for this. Thank you for bringing this to my attention.

llaville commented 1 year ago

@theofidry Code is now completed. Tell me if you think it's acceptable, or if you want more !

Chunk of box compile command output with "metadata": "Bartlett\\BoxManifest\\Composer\\ManifestFactory::toSbomJson1dot3" setting on Box-Manifest project itself

? Setting metadata
  - Using composer.json : /shared/backups/bartlett/box-manifest/composer.json
  - Using composer.lock : /shared/backups/bartlett/box-manifest/composer.lock
  - {
    "$schema": "http://cyclonedx.org/schema/bom-1.3.schema.json",
    "bomFormat": "CycloneDX",
    "specVersion": "1.3",
    "version": 1,
    "metadata": {
        "tools": [
            {
                "vendor": "box-project",
                "name": "box",
                "version": "4.2.0@afc3a47"
            }
        ],
        "component": {
            "bom-ref": "BomRef.63e56378e5b904.73643295",
            "type": "application",
            "name": "box-manifest",
            "version": "2.x-dev@781abd9",
            "group": "bartlett",
            "description": "Create a manifest to a PHP Archive (PHAR) for the BOX project (https://github.com/box-project/box)",
            "licenses": [
                {
                    "license": {
                        "id": "MIT"
                    }
                }
            ],
            "purl": "pkg:composer/bartlett/box-manifest@2.x-dev%40781abd9"
        }
    },
    "components": [
        {
            "bom-ref": "BomRef.63e56378e5a414.90121867",
            "type": "library",
            "name": "amp",
            "version": "v2.6.2",
            "group": "amphp",
            "purl": "pkg:composer/amphp/amp@v2.6.2"
        },
theofidry commented 1 year ago

Caught up with it!

So ideally I would like the SBOM to be handled by Composer itself, but I don't see any plan for that now so I'm happy to integrate it in Box.

I think however I would prefer to see it as a regular file rather than metadata. If then wouldn't need the metadata change and also could just be a regular setting.

For sure the Info command would need to be enriched to check for it and show it, the same way I would like it to give more info regarding the requirement checker.

llaville commented 1 year ago

@theofidry I think cdxgen of CylconeDX may require your attention, because it may be generate BOM 1.4 XML or JSON results of any PHP project, even if there are still some minor issues (I've already reported in https://github.com/CycloneDX/cdxgen/issues/236)

jkowalleck commented 1 year ago

re: https://github.com/box-project/box/issues/841#issuecomment-1424942646

So ideally I would like the SBOM to be handled by Composer itself [...]

Have you tried the composer plugin cyclonedx/cyclonedx-php-composer? It utilizes composer itself to gather the evidences for creating CycloneDX. Unlike cdxgen and others, it does not need NodeJS or python installed or some other binary downloaded.

llaville commented 1 year ago

Hello @jkowalleck As you've perharps noticed, I've already created a solution (https://github.com/llaville/box-manifest/blob/sbom/src/Composer/Manifest/SbomManifestBuilder.php) based on the cyclonedx/cyclonedx-library.

Box-Manisfest was born for historical reason, and even if it's a fork/patched version of main BOX project, I'm happy of results produced. I regret just that the cyclonedx php lib does not support spec 1.4 ;-)

jkowalleck commented 1 year ago

Was rereffing to https://github.com/box-project/box/issues/841#issuecomment-1424942646

the manifesto you came up with is better for the job here, since not all phars are composer-based.

What features of CycloneDX 1.4 do you actually need? There are not that many changes from 1.3 to 1.4 - just externalReferences, releaseNotes, some annotation and the big block for vulnerability-disclosure/vulnerabilities. @llaville , please let me know, or feature-request them for the upcoming cyclonedx/cyclonedx-library@v2

llaville commented 1 year ago

@jkowalleck I don't have any new feature requests for v2. Just waiting stable release :) And when I'll have more free time, my manifest builder should be able to use either stable spec 1.3, and upcoming 1.4 with a bridge !

llaville commented 1 year ago

@theofidry I've just created a prototype of a new Manifest command that may be able to generate any manifest results as implementations available.

Related to my question https://github.com/theofidry/console/issues/145, I don't know how to lazy load any new command (e.g in the contrib namespace) without to alter the https://github.com/box-project/box/blob/4.3.7/src/Console/Application.php#L78-L91

My new manifest command invocation will look like php -d phar.readonly=0 bin/manifest contrib:add-manifest to print result on standard output (by default), but may be also able to write directly to a file that can be include later when we try to bin/box compile any project. PS: bin/manifest is same as bin/box just for testing purpose.

box-4 3_manifest

contrib:add-manifest command is able just right now to generate results in the same format as https://github.com/llaville/box-manifest did, including SBOM format (Spec 1.3) and soon (Spec 1.4)

We are closed to realize a dream to add finally the manifest feature in official Box project. That will allow to me to let down maintaince of my bartlett/box-manifest project.

llaville commented 1 year ago

@theofidry Meanwhile your feedback, I'll release soon the last major release 3..0.0 of bartlett/box-manifest that will support this new command rather than patching the humbug/box like I did in past with help of cweagans/composer-patches

llaville commented 1 year ago

Final major version 3.0 of bartlett/box-manifest is ready.

I just want to polish some details and perharps prepare a bridge for CycloneDX spec 1.4 with (upcoming cyclonedx/cyclonedx-library v2.0 still in development)

But code is fully operational with full documentation (available on branch 3.x)

The Dream became a reality :

llaville commented 1 year ago

And to conclude my implementation, an example of free format and how to build it ! See https://github.com/llaville/box-manifest/commit/89849329b476f780406a6476eb31011722cfcc7b

Preview, when BOX compile with its contents !

custom-manifest

theofidry commented 1 year ago

Thank you @llaville, will check it out ASAP

llaville commented 1 year ago

In case of anybody want to use it as a bridge, here are with commit https://github.com/llaville/box-manifest/commit/261d1eea628d9fafe253e732a86ef793ceed9bd7 an example script to follow !

And console logs to preview, if you don't have a chance or time to run it !

llaville commented 1 year ago

With PR 925 my work on adding a manifest feature to official BOX project is now completed (for me).

Awaiting feedbacks

theofidry commented 1 year ago

I think with the emergence of the BOM standard, it makes more sense to go towards that solution rather than arbitrary alternative manifest formats. I think PHPUnit was a good and interesting source of inspiration and I like the initial proposal of the manifest that you did, but unlike PHPUnit, we do not need a special format so picking the standard makes more sense.

So reviewing your work and the PR, my initial thoughts are:

It's a bit late so might be a bit messy...

llaville commented 1 year ago

To summarize the situation that have changed since last time.

  1. If I've well understood, you don't want to have multiple manifest format supported, but I'm opposite to this idea (sorry) ! I want that the final users are free to choose the format that will match their needs: plain text, decorated text, SBOM (XML or JSON) and everything else.

    This is the reason why I'll keep the BOX-Manifest project opened (and will publish a major version 3.0)

  2. I've closed PR #925 because we can solve it with default stub setting and a custom version (e.g: https://github.com/llaville/box-manifest/commit/07f14a00f4f53ea4d9af907ffa01dfabaf39c0eb)

Purpose of this stub version is to display one of the manifest file it could found into root of the PHP Archive (choice are : first find on the priority list ['manifest.txt', 'manifest.xml', 'sbom.xml', 'sbom.json'], or a specific file identified)

Example runs:

command $ ./app-fixtures.phar --manifest man.txt
 output $ Manifest "man.txt" is not available in this PHP Archive.
command $ ./app-fixtures.phar --manifest
 output $ 
<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1">
  <metadata>
    <tools>
      <tool>
        <vendor><![CDATA[box-project]]></vendor>
        <name><![CDATA[box]]></name>
        <version><![CDATA[4.3.8@5534406]]></version>
      </tool>
    </tools>
  </metadata>
  <components>
    <component type="library" bom-ref="pkg:composer/psr/log@3.0.0">
      <group><![CDATA[psr]]></group>
      <name><![CDATA[log]]></name>
      <version><![CDATA[3.0.0]]></version>
      <purl><![CDATA[pkg:composer/psr/log@3.0.0]]></purl>
    </component>
  </components>
  <dependencies>
    <dependency ref="pkg:composer/psr/log@3.0.0"/>
  </dependencies>
</bom>
  1. BOX-Manifest 3.0 has code refactorized again since last time. The new manifest command in now a pure Symfony Command, to avoid all questions about fidry/console.

There are two binary commands :

Thanks to symfony/runtime that allow to make it so easy. BTW I've an enhanced version of your autoload_runtime.templateto support PHAR !

Sources :

llaville commented 1 year ago

I've just finished to write a tutorial to learn about BOX-Manifest v3 features. This feature request is no more necessary, because all behaviors (at least on my side) have now a solution.

theofidry commented 1 year ago

Would you be open to do a voice call over this topic? I do have several questions but feel like there would be a lot of back and forth (and we already had some)

llaville commented 1 year ago

Time for contribution is now over ! Answers and solutions are available with https://github.com/llaville/box-manifest/releases/tag/3.0.0