-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fb6b4a3
commit 96a8a85
Showing
10 changed files
with
342 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/Microsoft.ComponentDetection.Contracts/ArgumentSets/ManifestFileFormat.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Microsoft.ComponentDetection.Contracts.ArgumentSets | ||
{ | ||
public enum ManifestFileFormat | ||
{ | ||
ComponentDetection, | ||
CycloneDx, | ||
Spdx, | ||
} | ||
} |
215 changes: 215 additions & 0 deletions
215
src/Microsoft.ComponentDetection.Contracts/Mappers/CycloneDx.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using CycloneDX.Json; | ||
using CycloneDX.Models; | ||
using CycloneDX.Utils; | ||
using Microsoft.ComponentDetection.Contracts.BcdeModels; | ||
using Microsoft.ComponentDetection.Contracts.TypedComponent; | ||
|
||
namespace Microsoft.ComponentDetection.Contracts.Mappers | ||
{ | ||
public static class CycloneDx | ||
{ | ||
public static string ToCycloneDxString(this ScanResult scanResult) => Serializer.Serialize(scanResult.ToCycloneDx()); | ||
|
||
public static Bom ToCycloneDx(this ScanResult scanResult) => new Bom | ||
{ | ||
SerialNumber = CycloneDXUtils.GenerateSerialNumber(), | ||
Metadata = new Metadata | ||
{ | ||
Timestamp = DateTime.UtcNow, | ||
Tools = new List<Tool> | ||
{ | ||
new Tool | ||
{ | ||
Vendor = "Microsoft", | ||
Name = "Component Detection", | ||
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(), | ||
ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Vcs, | ||
Url = "https://github.com/microsoft/component-detection", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
Components = scanResult.ComponentsFound.ToComponents(), | ||
}; | ||
|
||
private static List<Component> ToComponents(this IEnumerable<ScannedComponent> scannedComponents) => | ||
scannedComponents.Select(sc => sc.ToComponent()).ToList(); | ||
|
||
private static Component ToComponent(this ScannedComponent scannedComponent) | ||
{ | ||
var component = new Component | ||
{ | ||
Type = Component.Classification.Library, | ||
Name = scannedComponent.Component.PackageUrl.Name, | ||
Version = scannedComponent.Component.PackageUrl.Version, | ||
Purl = scannedComponent.Component.PackageUrl.ToString(), | ||
Properties = scannedComponent.GenerateProperties(), | ||
}; | ||
|
||
switch (scannedComponent.Component.Type) | ||
{ | ||
case ComponentType.Cargo: | ||
var cargoComponent = (CargoComponent)scannedComponent.Component; | ||
break; | ||
case ComponentType.Conda: | ||
var condaComponent = (CondaComponent)scannedComponent.Component; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Other, | ||
Url = condaComponent.Url, | ||
}, | ||
}; | ||
break; | ||
case ComponentType.DockerImage: | ||
var dockerImageComponent = (DockerImageComponent)scannedComponent.Component; | ||
break; | ||
case ComponentType.Git: | ||
var gitComponent = (GitComponent)scannedComponent.Component; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Vcs, | ||
Url = gitComponent.RepositoryUrl.ToString(), | ||
}, | ||
}; | ||
break; | ||
case ComponentType.Go: | ||
var goComponent = (GoComponent)scannedComponent.Component; | ||
component.Hashes = new List<Hash> | ||
{ | ||
new Hash | ||
{ | ||
Alg = Hash.HashAlgorithm.SHA_256, | ||
Content = goComponent.Hash, | ||
}, | ||
}; | ||
break; | ||
case ComponentType.Linux: | ||
var linuxComponent = (LinuxComponent)scannedComponent.Component; | ||
component.Properties.AddRange( | ||
new List<Property> | ||
{ | ||
new Property | ||
{ | ||
Name = "distribution", Value = linuxComponent.Distribution, | ||
}, | ||
new Property | ||
{ | ||
Name = "release", Value = linuxComponent.Release, | ||
}, | ||
}); | ||
break; | ||
case ComponentType.Maven: | ||
var mavenComponent = (MavenComponent)scannedComponent.Component; | ||
break; | ||
case ComponentType.Npm: | ||
var npmComponent = (NpmComponent)scannedComponent.Component; | ||
if (npmComponent.Author?.Name != null || npmComponent.Author?.Email != null) | ||
{ | ||
component.Author = $"{npmComponent.Author?.Name} <{npmComponent.Author?.Email}>"; | ||
} | ||
|
||
if (npmComponent.Hash != null) | ||
{ | ||
component.Hashes = new List<Hash> | ||
{ | ||
new Hash | ||
{ | ||
Alg = Hash.HashAlgorithm.Null, // algorithm is included in hash | ||
Content = npmComponent.Hash, | ||
}, | ||
}; | ||
} | ||
|
||
break; | ||
case ComponentType.NuGet: | ||
component.Author = string.Join(",", ((NuGetComponent)scannedComponent.Component).Authors); | ||
break; | ||
case ComponentType.Other: | ||
var otherComponent = (OtherComponent)scannedComponent.Component; | ||
component.Hashes = new List<Hash> | ||
{ | ||
new Hash | ||
{ | ||
Alg = Hash.HashAlgorithm.Null, | ||
Content = otherComponent.Hash, | ||
}, | ||
}; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Distribution, | ||
Url = otherComponent.DownloadUrl.ToString(), | ||
}, | ||
}; | ||
break; | ||
case ComponentType.Pip: | ||
var pipComponent = (PipComponent)scannedComponent.Component; | ||
break; | ||
case ComponentType.Pod: | ||
var podComponent = (PodComponent)scannedComponent.Component; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Vcs, | ||
Url = podComponent.SpecRepo, | ||
}, | ||
}; | ||
break; | ||
case ComponentType.RubyGems: | ||
var rubyGemsComponent = (RubyGemsComponent)scannedComponent.Component; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Vcs, | ||
Url = rubyGemsComponent.Source, | ||
}, | ||
}; | ||
break; | ||
case ComponentType.Spdx: | ||
var spdxComponent = (SpdxComponent)scannedComponent.Component; | ||
break; | ||
case ComponentType.Vcpkg: | ||
var vcpkgComponent = (VcpkgComponent)scannedComponent.Component; | ||
component.Description = vcpkgComponent.Description; | ||
component.ExternalReferences = new List<ExternalReference> | ||
{ | ||
new ExternalReference | ||
{ | ||
Type = ExternalReference.ExternalReferenceType.Distribution, | ||
Url = vcpkgComponent.DownloadLocation, | ||
}, | ||
}; | ||
break; | ||
} | ||
|
||
return component; | ||
} | ||
|
||
private static List<Property> GenerateProperties(this ScannedComponent scannedComponent) | ||
{ | ||
var properties = new List<Property>(); | ||
properties.AddRange(scannedComponent.LocationsFoundAt.Select((locationFoundAt, i) => new Property | ||
{ | ||
Name = $"component-detection:location:{i}", | ||
Value = locationFoundAt, | ||
})); | ||
return properties; | ||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Microsoft.ComponentDetection.Contracts/Mappers/Spdx22.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Microsoft.ComponentDetection.Contracts.BcdeModels; | ||
|
||
namespace Microsoft.ComponentDetection.Contracts.Mappers | ||
{ | ||
using CycloneDX.Spdx.Interop; | ||
using CycloneDX.Spdx.Models.v2_2; | ||
using CycloneDX.Spdx.Serialization; | ||
|
||
public static class Spdx22 | ||
{ | ||
public static string ToSpdxString(this ScanResult scanResult) => JsonSerializer.Serialize(scanResult.ToSpdx()); | ||
|
||
public static SpdxDocument ToSpdx(this ScanResult scanResult) => scanResult.ToCycloneDx().ToSpdx(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
test/Microsoft.ComponentDetection.Contracts.Tests/Mappers/CycloneDx.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System.Collections.Generic; | ||
using FluentAssertions; | ||
using Microsoft.ComponentDetection.Contracts.BcdeModels; | ||
using Microsoft.ComponentDetection.Contracts.Mappers; | ||
using Microsoft.ComponentDetection.Contracts.TypedComponent; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
|
||
namespace Microsoft.ComponentDetection.Contracts.Tests.Mappers | ||
{ | ||
[TestClass] | ||
public class CycloneDx | ||
{ | ||
[TestMethod] | ||
public void ToCycloneDx_HappyPath() | ||
{ | ||
var scanResult = new ScanResult | ||
{ | ||
ComponentsFound = new List<ScannedComponent> | ||
{ | ||
new ScannedComponent | ||
{ | ||
Component = new NpmComponent("lodash", "1.2.3"), | ||
LocationsFoundAt = new[] | ||
{ | ||
"/src/lodash.js", | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
var result = scanResult.ToCycloneDxString(); | ||
|
||
result.Should().NotBeEmpty(); | ||
} | ||
} | ||
} |
Oops, something went wrong.