Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support --normalize flag (sort+) for CycloneDX BOM on trim command output #81

Merged
merged 43 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
69c9067
Sort CycloneDX BOM top-level arrays before diff
mrutkows Apr 5, 2024
2e82781
Sort CycloneDX BOM top-level arrays before diff
mrutkows Apr 5, 2024
4138911
Add initial support for a sort flag on the Trim command
mrutkows Apr 8, 2024
b903e80
Add more sort tiebreaker fields for Component struct
mrutkows Apr 8, 2024
79ead2c
Add more sort tiebreaker fields for Services and Vulnerabilites structs
mrutkows Apr 8, 2024
d97f439
Add more sort tiebreaker fields for Services and Vulnerabilites structs
mrutkows Apr 8, 2024
9aca51f
clean up sort function comments
mrutkows Apr 8, 2024
0172560
break out sort functions and support recursive Components sort
mrutkows Apr 9, 2024
5bb773f
Continue to support more data schema for sort/comparison
mrutkows Apr 11, 2024
f16485f
Organize sort hierarchy to use top-down sort and comparator functions
mrutkows Apr 11, 2024
c317539
Refactor sort-named entites to normalize
mrutkows Apr 17, 2024
df69659
Add initial validation method to test normalized file output
mrutkows Apr 17, 2024
0f46061
Continue to improve use of the Normalizer interface
mrutkows Apr 17, 2024
ec76800
Add more normalize test cases using large application BOMs
mrutkows Apr 17, 2024
73e3ad4
Propagate the use of the Normalizer interface on more named Cdx types
mrutkows Apr 17, 2024
dcdf7f8
Support sort of DependsOn slice
mrutkows Apr 18, 2024
2e95661
Complete transition to uniformly using the Normalizer interface
mrutkows Apr 18, 2024
51b42f9
Support Normalizer interface for all Formulation data types
mrutkows Apr 18, 2024
34a1fa4
Support Normalizer interface for all Formulation data types
mrutkows Apr 18, 2024
4a1f7ce
Support Normalizer interface for LicenseChoice
mrutkows Apr 18, 2024
5f61da9
Support Normalizer interface for Vulnerability
mrutkows Apr 18, 2024
fcdfc85
Support Normalizer interface for Compositions slice and struct
mrutkows Apr 18, 2024
575dbdf
Support full normalization of the Vulnerability structure and all its…
mrutkows Apr 19, 2024
19017ba
Support full normalization of the Vulnerability structure and all its…
mrutkows Apr 19, 2024
352ccfd
Organize Formulation normalization into separate files
mrutkows Apr 19, 2024
9a70f8e
Support full normalization of the Vulnerability structure and all its…
mrutkows Apr 19, 2024
5b5bce9
Support full normalization of the Vulnerability structure and all its…
mrutkows Apr 19, 2024
9c51b85
Handle Diff command if normalized files still cause underyling panics
mrutkows Apr 22, 2024
3b6dd80
Add vulnerability Diff tests
mrutkows Apr 22, 2024
6efa4eb
remove temp test files
mrutkows Apr 22, 2024
237f3d9
remove temp test files
mrutkows Apr 22, 2024
2b6e844
Lower use of bom-ref as a normilaztion key as it can vary per-scan
mrutkows Apr 22, 2024
00a2ed3
Support temporary output files on all Diff command tests
mrutkows Apr 22, 2024
3ad5dad
Fix invalid delta file for panic test
mrutkows Apr 22, 2024
0b06a41
Fix linting errors for unref. functions
mrutkows Apr 24, 2024
375fa3a
Renamed HashXXX functions to HashmapXXX to reflect what is actually h…
mrutkows Apr 25, 2024
b3ca980
Abstract out BOMRef comparator
mrutkows Apr 26, 2024
68cfb58
Do not use bom-ref for normalization if it us a UUID
mrutkows Apr 26, 2024
59c969d
Fix some minor bugs in resource list command formatting
mrutkows Apr 26, 2024
2eaaf85
Add Trim --normalize flag example with new testcase to README
mrutkows Apr 26, 2024
de7d247
Add Trim --normalize flag example with new testcase to README
mrutkows Apr 26, 2024
9f79b10
Adjust normative order of fields for Component and Service based-upon…
mrutkows Apr 26, 2024
9e8b781
Add extra advice on diff panic to use trim and normalize
mrutkows Apr 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

{
"showGlobalVariables": true,
"name": "Debug: validate",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "main.go", // "program": "${file}",
"args": ["validate", "-i", "examples/cyclonedx/SBOM/protonmail-webclient-v4-0912dff/bom.json"],
"dlvFlags": ["--check-go-version=false"]
},
{
"showGlobalVariables": true,
"name": "Debug: query: SELECT * FROM metadata.component",
Expand Down
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"MLBOM",
"multimap",
"myservices",
"NATS",
"NOASSERTION",
"nolint",
"nosec",
Expand All @@ -99,6 +100,7 @@
"PROPKEY",
"protonmail",
"repackager",
"rvoi",
"rwxr",
"SAAS",
"SAASBOM",
Expand Down
182 changes: 182 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,14 @@ A comma-separated list of JSON map keys. Similar to the [query command's `--sele

A comma-separated list of JSON document paths using the same syntax as the [query command's `--from` flag](#query---from-flag).

##### Trim `--normalize` flag

A flag that normalizes the BOM data after trimming and prior to output.

This flag has custom code that sorts all components, services, licenses, vulnerabilities, properties, external references, hashes and *most* other BOM data using custom comparators.

Each comparator uses `required` fields and other identifying fields to create *"composite keys"* for each unique data structure.

#### Trim examples

The original BOM used for these examples can be found here:
Expand Down Expand Up @@ -1133,6 +1141,180 @@ Output BOM results with `properties` removed from all `components`:

---

##### Example: Trim `bom-ref` and normalize output

```bash
./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-components-normalize.sbom.json --keys="bom-ref" --normalize -q
```

**Note** If you do not want to remove any keys and simply normalize output, set keys to an empty string: `--keys=""`.

Use the trim command to remove all `bom-ref` fields and normalize output:

```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"components": [
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"purl": "pkg:npm/[email protected]",
"name": "sample",
"version": "2.0.0",
"licenses": [
{
"license": {
"id": "GPL-2.0-or-later"
}
},
{
"license": {
"id": "LGPL-2.0-or-later"
}
},
{
"license": {
"id": "GPL-2.0-only"
}
}
],
"properties": [
{
"name": "moo",
"value": "cow"
},
{
"name": "foo",
"value": "bar"
}
]
},
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"purl": "pkg:npm/[email protected]",
"name": "body-parser",
"version": "1.19.0",
"hashes": [
{
"alg": "SHA-256",
"content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
},
{
"alg": "SHA-1",
"content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
}
],
"licenses": [
{
"license": {
"id": "MIT"
}
},
{
"license": {
"id": "Apache-2.0"
}
}
],
"externalReferences": [
{
"type": "website",
"url": "https://example.com/website"
},
{
"type": "support",
"url": "https://example.com/support"
}
]
}
]
}
```

Trimmed, normalized output:

```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"components": [
{
"type": "library",
"name": "body-parser",
"version": "1.19.0",
"hashes": [
{
"alg": "SHA-1",
"content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
},
{
"alg": "SHA-256",
"content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
],
"licenses": [
{
"license": {
"id": "Apache-2.0"
}
},
{
"license": {
"id": "MIT"
}
}
],
"purl": "pkg:npm/[email protected]",
"externalReferences": [
{
"type": "support",
"url": "https://example.com/support"
},
{
"type": "website",
"url": "https://example.com/website"
}
]
},
{
"type": "library",
"name": "sample",
"version": "2.0.0",
"licenses": [
{
"license": {
"id": "GPL-2.0-only"
}
},
{
"license": {
"id": "GPL-2.0-or-later"
}
},
{
"license": {
"id": "LGPL-2.0-or-later"
}
}
],
"purl": "pkg:npm/[email protected]",
"properties": [
{
"name": "foo",
"value": "bar"
},
{
"name": "moo",
"value": "cow"
}
]
}
]
}
```

### Validate

This command will parse standardized SBOMs and validate it against its declared format and version (e.g., SPDX 2.2, CycloneDX 1.4). Custom variants of standard JSON schemas can be used for validation by supplying the `--variant` name as a flag. Explicit JSON schemas can be specified using the `--force` flag.
Expand Down
29 changes: 0 additions & 29 deletions acdx.json

This file was deleted.

15 changes: 10 additions & 5 deletions cmd/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,21 @@ func Diff(persistentFlags utils.PersistentCommandFlags, flags utils.DiffCommandF
// #nosec G304 (suppress warning)
bBaseData, errReadBase := os.ReadFile(inputFilename)
if errReadBase != nil {
getLogger().Debugf("%v", bBaseData[:255])
err = getLogger().Errorf("Failed to ReadFile '%s': %s", inputFilename, err.Error())
if len(bBaseData) > 255 {
getLogger().Debugf("%v", bBaseData[:255])
}
err = getLogger().Errorf("Failed to ReadFile '%s': %s", inputFilename, errReadBase.Error())
return
}

getLogger().Infof("Reading file (--input-revision): `%s` ...", revisedFilename)
// #nosec G304 (suppress warning)
bRevisedData, errReadDelta := os.ReadFile(revisedFilename)
if errReadDelta != nil {
getLogger().Debugf("%v", bRevisedData[:255])
err = getLogger().Errorf("Failed to ReadFile '%s': %s", inputFilename, err.Error())
if len(bRevisedData) > 255 {
getLogger().Debugf("%v", bRevisedData[:255])
}
err = getLogger().Errorf("Failed to ReadFile '%s': %s", revisedFilename, errReadDelta.Error())
return
}

Expand Down Expand Up @@ -201,6 +205,7 @@ func Diff(persistentFlags utils.PersistentCommandFlags, flags utils.DiffCommandF
getLogger().Warningf("Diff output format not supported for `%s` format.", format)
}

// Output complete diff in either supported format
fmt.Fprintf(output, "%s\n", diffString)

} else {
Expand All @@ -214,7 +219,7 @@ func Diff(persistentFlags utils.PersistentCommandFlags, flags utils.DiffCommandF
func compareBinaryData(bBaseData []byte, bRevisedData []byte) (diffResults diff.Diff, err error) {
defer func() {
if recoveredPanic := recover(); recoveredPanic != nil {
fmt.Println("panic occurred:", recoveredPanic)
getLogger().Infof("ADVICE: Use the Trim command before Diff to remove highly variable data, such as: \"bom-ref\", \"hashes\" and \"properties\".")
err = getLogger().Errorf("panic occurred: %v", recoveredPanic)
return
}
Expand Down
Loading
Loading