CycloneDX / cyclonedx-dotnet

Creates CycloneDX Software Bill of Materials (SBOM) from .NET Projects
https://cyclonedx.org/
Apache License 2.0
167 stars 78 forks source link

Support providing a solution filter #853

Open KieranFoot opened 4 months ago

KieranFoot commented 4 months ago

It would be nice if instead of the current supported file type, we could provide solution filters to the tool. This would allow developers to hand pick the projects that they wish to be part of the BOM.

mtsfoni commented 4 months ago

Can you describe what you understand under "solution filter".

Can you describe a case where using a project- or a solution-file is not sufficient for selecting relevant projects? What is it you are trying to achieve? Is this an A-B Problem?

KieranFoot commented 4 months ago

It's not an issue, it's just an improvement that would assist people that are already using solution filters, but I'll proceed to describe my use case.

I currently have a monolithic solution containing code for many target architectures and operating systems. I have CI/CD pipelines for each target since the code and dependencies cannot be compiled on just any platform.

In both Visual Studio and Rider, you can create a Project Filter from a solution, this is basically a JSON file that describes both the solution and the projects to include (thus filtering the ones not included).

I would like the ability to use a solution filter as I currently use it for all relevant dotnet commands in place of a solution/project and it would be simpler if I could use it here too rather than having to create and manage the lists in several different places.

Also, in my opinion, the solution filter format is much simpler then a solution file to both consume and maintain manually.

For some information on filters, see here

As I say, currently, this is how I separate code to progress through my pipelines per target.

mtsfoni commented 4 months ago

So I assume you use the cyclonedx tool on the solution-file rather than the specific project-file?

When a solution file is targeted, the cyclonedx tool basically creates a bom for each project inside the solution and aggregates those mindlessly. This is not a very clever, smart, or even correct way to build a bom. If there are different output projects that have different versions of dependencies, it gets super messy. Yes, solution filters could reduce that problem.

However, there is an explicit way to get exactly what one needs and want: Call the cyclonedx tool with the project file, that is the actual output (the webserver, windowsservice, .exe etc.). Unless one still uses packages.config files, cyclonedx will read all important information from the nuget-generated project.assets.json file and generate a quite accurate bom with the dependency tree. In my workplace, we generate a seperate frontend bom and a backend bom from the respective projects inside the solution.

That being said. I am not absolute against support for solution filters, however I see calling the tool with a solution file more as a comfortable shortcut than an accurate approach of generating a bom. A program is normal one project (with dependencies); a solution is a bundle of many (usually related) projects. It might be that the Buildalyzer integration that is currently in work might already offer some support, and we just need to add the argument.

Long Story short: Would accept a proper PR, but won't do it by myself as I don't see it really necessary.

KieranFoot commented 4 months ago

Ok, thanks, I'll put together a PR when I have the time.

pepcots commented 2 months ago

I faced that, my workaround was creating a sln from the slnf with an small powershell script. But, in the end, I agree it makes more sense calling cyclone tool pointing to a project instead of a full solution.

Param($SLNFPath, $SLNOutPath)

#Parse snlf json file
$slnf_json = Get-Content -Path "$SLNFPath" | Out-String | ConvertFrom-Json
#Get slnf projects list
$slnf_projs = $slnf_json.solution.projects
#Get full solution project list
$SLNFFolder = (Get-Item "$SLNFPath").DirectoryName
$sln_projs = dotnet sln "$SLNFFolder/$($slnf_json.solution.path)" list 

#Create a copy for the solution file
Copy-Item -Path "$SLNFFolder/$($slnf_json.solution.path)" -Destination $SLNOutPath

#Remove projects that do not appear in the slnf
$sln_projs | Where-Object { $_ -notin $slnf_projs } | ForEach-Object {
    dotnet sln $SLNOutPath remove "$SLNFFolder/$_"
}