Implement License Scanning SBOM scanner
<!-- Implementation issues are used break-up a large piece of work into small, discrete tasks that can move independently through the build workflow steps. They're typically used to populate a Feature Epic. Once created, an implementation issue is usually refined in order to populate and review the implementation plan and weight. Example workflow: https://about.gitlab.com/handbook/engineering/development/threat-management/planning/diagram.html#plan --> ## Why are we doing this work To achieve https://gitlab.com/groups/gitlab-org/-/epics/9400+, we need to implement a License Scanning SBOM Scanner that inherits `LicenseScanning::BaseScanner`, and that returns licenses of project dependencies using the SBOM reports. NOTE: The SBOM Scanner is behind a feature flag. See https://gitlab.com/gitlab-org/gitlab/-/issues/384935+ ## Further details The [`SbomScanner`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/license_scanning/sbom_scanner.rb) class has been introduced in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105747 but its methods haven't been implemented. The SBOM scanner responds to `report`, `has_data?`, and `data_available?`. See https://gitlab.com/gitlab-org/gitlab/-/issues/384934 `#report` should do the following: 1. Fetch projet dependencies for the given project or pipeline using SBOM component fetchers. 2. TBD: Normalize component names, unless the SBOM component fetchers already do it. See https://gitlab.com/gitlab-org/gitlab/-/issues/384932#note_1230139272 3. Get the licenses of package versions using another fetcher. 4. Build and return a [`Ci::Reports::LicenseScanning::Report`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/ci/reports/license_scanning/report.rb). The SBOM scanner works even when the SBOM reports don't contain normalized component names. For instance, it should return the correct licenses for a component whose PURL is `pkg:pypi/djanGO`. (Canonical name is `Django`, and normalized name is `django`.) `#has_data?` and `#data_available?` should behave as documented in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105533: | method | description | | -- | -- | | `#has_data?` | Evaluates if the scanner had license scanning data. In terms of the artifact scanner, it will evaluate to true if there was a job that returns a `license_scanning` report. For the SBoM scanner, this may materialize as having SBoM generator jobs. | | `#data_available?` | Evaluates if the scanner has completed "scanning". In terms of artifact scanning, this is determined if the pipeline with the license scanning report has a status of `success`. | `PipelineComponents` needs to be updated to return a name that can't be directly compared to `pm_packages.name`. It's normalized, and it includes the namespace (npm) or group ID (Maven). Code: `#{component.purl.namespace}/#{component.purl.name}` See https://gitlab.com/gitlab-org/gitlab/-/issues/384932#note_1243704431 ## Relevant links - Existing skeleton: https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/license_scanning/sbom_scanner.rb - Definition of the Scanner interface: https://gitlab.com/gitlab-org/gitlab/-/issues/384934 - Implementation of SBOM fetchers: https://gitlab.com/gitlab-org/gitlab/-/issues/384536 - Implementation of licenses fetcher: https://gitlab.com/gitlab-org/gitlab/-/issues/384888 ## Non-functional requirements - [ ] Documentation: https://gitlab.com/gitlab-org/gitlab/-/issues/388439 - [ ] Feature flag: TBD - [ ] Performance: toggle feature flag and compare response time (SBOM Scanner vs Artifact Scanner) - [ ] Testing: implement specs in https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/spec/lib/gitlab/license_scanning/sbom_scanner_spec.rb ## Implementation plan - [ ] Update `PipelineComponents` to return full normalized names. See https://gitlab.com/gitlab-org/gitlab/-/issues/384932#note_1243704431 - [ ] Implement the `SbomScanner`, and update its specs. - [ ] Add a new `license_scanning_sbom_scanner` feature flag. - [ ] Change [Gitlab::LicenseScanning.scanner_class](https://gitlab.com/gitlab-org/gitlab/-/blob/39536a8451e1b00eec06bf2f51568f2888c949fb/ee/lib/gitlab/license_scanning.rb#L21-23) to use `SbomScanner` instead of `ArtifactScanner` when the `license_scanning_sbom_scanner` is enabled. ## Verification steps Check `license_scanning_sbom_scanner` feature flag. Enable `license_scanning_sbom_scanner` feature flag in a project where Dependency Scanning is used to generate SBOMs: 1. Set up a project supported by Dependency Scanning and License DB. 1. Enable feature flag for that project. See #384935 1. Add Dependency Scanning to the CI config, and add dependencies to project. 1. Check licenses in `License Compliance` page. 1. Check other features that have already been refactored as part of https://gitlab.com/groups/gitlab-org/-/epics/8532. Non-regression test * Go to a projet where License Scanning has been configured, and that has License Scanning artifacts. * Use any License Scanning feature that's been refactored as part of https://gitlab.com/groups/gitlab-org/-/epics/8532+. * Make sure that there's no regression. The verification tests are blocked by https://gitlab.com/gitlab-org/gitlab/-/issues/384935+. Also, check whether https://gitlab.com/gitlab-org/gitlab/-/issues/333839+ is fixed when enabling `license_scanning_sbom_scanner`. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109447#note_1263301787
issue