in JetBrains.SbomUtils/src/JetBrains.SbomUtils/SbomValidator.cs [23:87]
public ValidationResult ValidateInstallation(SbomModel sbomModel, IInstalledSoftwareProvider installedSoftwareProvider, ICollection<string> rootPackageNames, ICollection<string> exceptions, ValidationOptions? validationOptions = null)
{
if (sbomModel == null)
throw new InvalidOperationException("Load an spdx document first");
validationOptions ??= new ValidationOptions();
ICollection<Package> productPackages;
if (rootPackageNames.Any())
{
var rootPackages = _sbomOperations.FindRootPackageByName(sbomModel, rootPackageNames);
if (!rootPackages.Any()) throw new InvalidOperationException($"None of root packages {string.Join(", ", rootPackageNames)} wasn't found in the SBOM");
_logger.LogDebug("Found {count} root packages in the SBOM: {packages}", rootPackages.Count(), string.Join(", ", rootPackages.Select(p => p.Name)));
productPackages = _sbomOperations.GetAllDependantPackages(sbomModel, rootPackages);
}
else
{
productPackages = sbomModel.Packages.Values;
}
_logger.LogDebug("{count} dependent packages were collected", productPackages.Count);
var packagesHashSet = productPackages.ToHashSet();
var (installationFiles, ignoredFiles) = installedSoftwareProvider.GetFiles(exceptions);
ConcurrentBag<MissingFile> missingFiles = new ConcurrentBag<MissingFile>();
ConcurrentBag<FileVerificationResult> fileVerificationResults = new ConcurrentBag<FileVerificationResult>();
ParallelOptions parallelOptions = new ParallelOptions()
{
MaxDegreeOfParallelism = validationOptions.Threads,
};
Parallel.ForEach(installationFiles, parallelOptions, (installationFile, token) =>
{
if (sbomModel.FilesDictionaryByRelativePath.TryGetValue(installationFile, out var sbomFiles))
{
var fileValidationResult = ValidateFile(installedSoftwareProvider, installationFile, sbomFiles, packagesHashSet);
fileVerificationResults.Add(fileValidationResult);
}
else
{
var fileName = Path.GetFileName(installationFile);
if (sbomModel.FilesDictionaryByFileName.TryGetValue(fileName, out var filesFromAnotherPackages))
missingFiles.Add(new MissingFile(installationFile, filesFromAnotherPackages));
else
missingFiles.Add(new MissingFile(installationFile, Array.Empty<FileInfo>()));
}
});
var validationResult = new ValidationResult(
success: !(missingFiles.Any() || fileVerificationResults.Any(f => !f.Success)),
errorMessage: null,
filesChecked: installationFiles.Count,
ignoredFiles: ignoredFiles.ToArray(),
filesMissingInSbom: missingFiles.ToArray(),
fileVerificationResults: fileVerificationResults.ToArray());
return validationResult;
}