Skip to content

Commit

Permalink
Merge pull request #318 from andreas-hilti/cdx1.6
Browse files Browse the repository at this point in the history
Cdx1.6
  • Loading branch information
mtsfoni authored Aug 24, 2024
2 parents 751d58b + 0cb39b2 commit 4a70618
Show file tree
Hide file tree
Showing 128 changed files with 1,864 additions and 399 deletions.
15 changes: 14 additions & 1 deletion .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: .NET Core CI

on: [pull_request, workflow_dispatch]

env:
SNAPSHOOTER_STRICT_MODE: true

jobs:
# Fail if there are build warnings
#
Expand Down Expand Up @@ -30,11 +33,21 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
# os: [ubuntu-latest, windows-latest, macos-latest]
# macos currently disabled. see issue #285 for more info.
os: [ubuntu-latest, windows-latest]
timeout-minutes: 30

steps:
- uses: actions/checkout@v3
- name: SnapshooterHotfixSymlinkLinux
if: matrix.os == 'ubuntu-latest'
run: sudo ln -s "$GITHUB_WORKSPACE" /_
shell: bash
- name: SnapshooterHotfixSymlinkWindows
if: matrix.os == 'windows-latest'
run: New-Item -ItemType SymbolicLink -Path "/_" -Target "$env:GITHUB_WORKSPACE"
shell: pwsh
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ jobs:
export PATH="$PATH:$HOME/.local/bin"
# The tests should have already been run during the PR workflow, so this is really just a sanity check
# See issue #285 for info why the symlink is necessary.
- name: SnapshooterHotfixSymlinkLinux
run: sudo ln -s "$GITHUB_WORKSPACE" /_
shell: bash

- name: Tests
run: dotnet test

Expand Down
2 changes: 1 addition & 1 deletion semver.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.0
7.1.0
4 changes: 2 additions & 2 deletions src/CycloneDX.Core/CycloneDX.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="JsonSchema.Net" Version="3.3.2" />
<PackageReference Include="JsonSchema.Net" Version="5.3.1" />
<PackageReference Include="protobuf-net" Version="3.2.26" />
<PackageReference Include="protobuf-net.BuildTools" Version="3.2.12" PrivateAssets="all" IncludeAssets="runtime;build;native;contentfiles;analyzers;buildtransitive" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 3 additions & 2 deletions src/CycloneDX.Core/Json/Converters/DateTimeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -40,7 +41,7 @@ public class DateTimeConverter : JsonConverter<DateTime?>
}

var valueString = reader.GetString();
var value = DateTime.Parse(valueString);
var value = DateTime.Parse(valueString, CultureInfo.InvariantCulture);
return value;
}

Expand All @@ -51,7 +52,7 @@ public override void Write(
{
Contract.Requires(writer != null);

writer.WriteStringValue(value?.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"));
writer.WriteStringValue(value?.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture));
}
}
}
4 changes: 0 additions & 4 deletions src/CycloneDX.Core/Json/Converters/ScoreMethodConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ public override void Write(
{
writer.WriteStringValue("other");
}
else if (value == ScoreMethod.CVSSV31)
{
writer.WriteStringValue("CVSSv3.1");
}
else if (value.ToString().StartsWith("CVSSV"))
{
writer.WriteStringValue("CVSSv" + value.ToString().Substring(5));
Expand Down
15 changes: 7 additions & 8 deletions src/CycloneDX.Core/Json/Converters/ToolChoicesConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,19 @@ public override void Write(
Contract.Requires(writer != null);
Contract.Requires(value != null);

if (value.Tools != null)
if (value.Tools != null || value.SpecVersion < SpecificationVersion.v1_5)
{
writer.WriteStartArray();
foreach (var tool in value.Tools)
if (value.Tools != null)
{
JsonSerializer.Serialize(writer, tool, options);
foreach (var tool in value.Tools)
{
JsonSerializer.Serialize(writer, tool, options);
}
}
writer.WriteEndArray();
}
else if (value.Components != null || value.Services != null)
else
{
writer.WriteStartObject();
if (value.Components != null)
Expand All @@ -97,10 +100,6 @@ public override void Write(
}
writer.WriteEndObject();
}
else
{
writer.WriteNullValue();
}
}
}
}
13 changes: 13 additions & 0 deletions src/CycloneDX.Core/Json/Serializer.Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,18 @@ internal static string Serialize(Models.Vulnerabilities.Vulnerability vulnerabil
Contract.Requires(vulnerability != null);
return JsonSerializer.Serialize(vulnerability, _options);
}

internal static string Serialize(Models.Composition composition)
{
Contract.Requires(composition != null);
return JsonSerializer.Serialize(composition, _options);
}

internal static string Serialize(Models.ExternalReference externalReference)
{
Contract.Requires(externalReference != null);
return JsonSerializer.Serialize(externalReference, _options);
}

}
}
6 changes: 4 additions & 2 deletions src/CycloneDX.Core/Json/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,18 @@ public static JsonSerializerOptions GetJsonSerializerOptions()

options.Converters.Add(new EnvironmentVarChoiceConverter());
options.Converters.Add(new ToolChoicesConverter());


options.Converters.Add(new HyphenEnumConverter<EvidenceIdentity.EvidenceFieldType>());
options.Converters.Add(new HyphenEnumConverter<EvidenceMethods.EvidenceTechnique>());
options.Converters.Add(new ScoreMethodConverter());
options.Converters.Add(new HyphenEnumConverter<Severity>());
options.Converters.Add(new HyphenEnumConverter<Trigger.TriggerType>());
options.Converters.Add(new HyphenEnumConverter<WorkflowTask.TaskType>());
options.Converters.Add(new HyphenEnumConverter<WorkflowTaskType>());
options.Converters.Add(new HyphenEnumConverter<Output.OutputType>());
options.Converters.Add(new HyphenEnumConverter<ModelCard.ModelParameterApproachType>());
options.Converters.Add(new UnderscoreEnumConverter<Status>());
options.Converters.Add(new HyphenEnumConverter<Volume.VolumeMode>());
options.Converters.Add(new HyphenEnumConverter<Data.DataType>());

options.Converters.Add(new JsonStringEnumConverter());

Expand Down
40 changes: 13 additions & 27 deletions src/CycloneDX.Core/Json/Validator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ public static ValidationResult Validate(string jsonString, SpecificationVersion
private static ValidationResult Validate(JsonSchema schema, JsonDocument jsonDocument, string schemaVersionString)
{
var validationMessages = new List<string>();
var validationOptions = new ValidationOptions
var validationOptions = new EvaluationOptions
{
OutputFormat = OutputFormat.Detailed,
OutputFormat = OutputFormat.List,
RequireFormatValidation = true
};

var result = schema.Validate(jsonDocument.RootElement, validationOptions);
var result = schema.Evaluate(jsonDocument.RootElement, validationOptions);

if (result.IsValid)
{
Expand All @@ -197,34 +197,20 @@ private static ValidationResult Validate(JsonSchema schema, JsonDocument jsonDoc
}
else
{
validationMessages.Add($"Validation failed: {result.Message}");
validationMessages.Add(result.SchemaLocation.ToString());
validationMessages.Add($"On instance: {result.InstanceLocation}:");
validationMessages.Add(result.InstanceLocation.Evaluate(jsonDocument.RootElement).ToString());

if (result.NestedResults != null)
validationMessages.Add("Validation failed:");
// because we requested the results as a flat list
// there will be no nested results
foreach (var detail in result.Details)
{
var nestedResults = new Queue<ValidationResults>(result.NestedResults);

while (nestedResults.Count > 0)
if (detail.HasErrors)
{
var nestedResult = nestedResults.Dequeue();

if (
!string.IsNullOrEmpty(nestedResult.Message)
&& nestedResult.NestedResults != null
&& nestedResult.NestedResults.Count > 0)
{
validationMessages.Add($"{nestedResult.InstanceLocation}: {nestedResult.Message}");
}

if (nestedResult.NestedResults != null)
foreach (var error in detail.Errors)
{
foreach (var newNestedResult in nestedResult.NestedResults)
{
nestedResults.Enqueue(newNestedResult);
}
validationMessages.Add(error.Value);
}
validationMessages.Add(detail.SchemaLocation.ToString());
validationMessages.Add($"On instance: {detail.InstanceLocation}:");
validationMessages.Add(detail.InstanceLocation.Evaluate(jsonDocument.RootElement).ToString());
}
}
}
Expand Down
37 changes: 33 additions & 4 deletions src/CycloneDX.Core/Models/Component.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using CycloneDX.Core.Models;
Expand Down Expand Up @@ -141,10 +143,23 @@ public ComponentScope NonNullableScope
public List<Hash> Hashes { get; set; }
public bool ShouldSerializeHashes() { return Hashes?.Count > 0; }

[XmlElement("licenses")]
[XmlIgnore]
[ProtoMember(13)]
public List<LicenseChoice> Licenses { get; set; }


[XmlElement("licenses")]
[JsonIgnore, ProtoIgnore]
[EditorBrowsable(EditorBrowsableState.Never)]
// This is a serialization workaround
public LicenseChoiceList LicensesSerialized
{
get { return Licenses != null ? new LicenseChoiceList(Licenses) : null; }
set { Licenses = value.Licenses; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeLicensesSerialized() { return Licenses?.Count > 0; }

[XmlElement("copyright")]
[ProtoMember(14)]
public string Copyright { get; set; }
Expand Down Expand Up @@ -190,16 +205,19 @@ public bool NonNullableModified
public List<ExternalReference> ExternalReferences { get; set; }
public bool ShouldSerializeExternalReferences() { return ExternalReferences?.Count > 0; }

[XmlArray("components")]
[ProtoMember(21)]
public List<Component> Components { get; set; }
//In the xml format, Properties is in front of Components.
//XML serialization uses the member order unless explicitly specified differently.
public bool ShouldSerializeComponents() { return Components?.Count > 0; }

[XmlArray("properties")]
[XmlArrayItem("property")]
[ProtoMember(22)]
public List<Property> Properties { get; set; }
public bool ShouldSerializeProperties() { return Properties?.Count > 0; }

[XmlArray("components")]
[ProtoMember(21)]
public List<Component> Components { get; set; }

[XmlElement("evidence")]
[ProtoMember(23)]
Expand All @@ -223,6 +241,17 @@ public bool NonNullableModified
public CryptoProperties CryptoProperties { get; set; }


public override bool Equals(object obj)
{
var other = obj as Component;
if (other == null)
{
return false;
}

return Json.Serializer.Serialize(this) == Json.Serializer.Serialize(other);
}

public bool Equals(Component obj)
{
return Json.Serializer.Serialize(this) == Json.Serializer.Serialize(obj);
Expand Down
23 changes: 22 additions & 1 deletion src/CycloneDX.Core/Models/Composition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
namespace CycloneDX.Models
{
[ProtoContract]
public class Composition : IXmlSerializable
public class Composition : IXmlSerializable, IEquatable<Composition>
{
[ProtoContract]
public enum AggregateType
Expand Down Expand Up @@ -194,5 +194,26 @@ public void WriteXml(System.Xml.XmlWriter writer) {
writer.WriteEndElement();
}
}

public override bool Equals(object obj)
{
var other = obj as Composition;
if (other == null)
{
return false;
}

return Json.Serializer.Serialize(this) == Json.Serializer.Serialize(other);
}

public bool Equals(Composition obj)
{
return CycloneDX.Json.Serializer.Serialize(this) == CycloneDX.Json.Serializer.Serialize(obj);
}

public override int GetHashCode()
{
return CycloneDX.Json.Serializer.Serialize(this).GetHashCode();
}
}
}
11 changes: 11 additions & 0 deletions src/CycloneDX.Core/Models/Dependency.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public class Dependency: IEquatable<Dependency>
[ProtoMember(3)]
public List<Provides> Provides { get; set; }

public override bool Equals(object obj)
{
var other = obj as Dependency;
if (other == null)
{
return false;
}

return Json.Serializer.Serialize(this) == Json.Serializer.Serialize(other);
}

public bool Equals(Dependency obj)
{
return CycloneDX.Json.Serializer.Serialize(this) == CycloneDX.Json.Serializer.Serialize(obj);
Expand Down
14 changes: 13 additions & 1 deletion src/CycloneDX.Core/Models/Evidence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Text.Json.Serialization;
Expand All @@ -30,9 +31,20 @@ namespace CycloneDX.Models
[ProtoContract]
public class Evidence
{
[XmlElement("licenses", Order = 3)]
[XmlIgnore]
[ProtoMember(1)]
public List<LicenseChoice> Licenses { get; set; }

[XmlElement("licenses", Order = 3)]
[JsonIgnore, ProtoIgnore]
[EditorBrowsable(EditorBrowsableState.Never)]
public LicenseChoiceList LicensesSerialized
{
get { return Licenses != null ? new LicenseChoiceList(Licenses) : null; }
set { Licenses = value.Licenses; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeLicensesSerialized() { return Licenses?.Count > 0; }

[XmlArray("copyright", Order = 4)]
[XmlArrayItem("text")]
Expand Down
Loading

0 comments on commit 4a70618

Please sign in to comment.