Skip to content

Commit 7d3fb97

Browse files
authored
CSAF bugfixes, better reports and list diffing (#38)
* Fix sorting. Signed-off-by: Caroline Russell <[email protected]> * Extract io operations into functions. Signed-off-by: Caroline Russell <[email protected]> * Fix csaf status. Signed-off-by: Caroline Russell <[email protected]> * Refactoring. Signed-off-by: Caroline Russell <[email protected]> * Optionally include empty fields in results. Signed-off-by: Caroline Russell <[email protected]> * Correction. Signed-off-by: Caroline Russell <[email protected]> * Handle score comparisons. Signed-off-by: Caroline Russell <[email protected]> * Make sure the best search key is selected. Signed-off-by: Caroline Russell <[email protected]> * Correct filter_empty usage. Signed-off-by: Caroline Russell <[email protected]> * Update HTML reports. Signed-off-by: Caroline Russell <[email protected]> * Update tests. Signed-off-by: Caroline Russell <[email protected]> * Display additional data in report. Signed-off-by: Caroline Russell <[email protected]> * Fix CSAF display issue. Signed-off-by: Caroline Russell <[email protected]> * CSAF bugfixes. Signed-off-by: Caroline Russell <[email protected]> * Optional sorting before json dump. Signed-off-by: Caroline Russell <[email protected]> * Custom list class and class properties. Signed-off-by: Caroline Russell <[email protected]> * Updating and improving tests. Signed-off-by: Caroline Russell <[email protected]> * Typing. Signed-off-by: Caroline Russell <[email protected]> --------- Signed-off-by: Caroline Russell <[email protected]>
1 parent f7a8fe0 commit 7d3fb97

14 files changed

+1117
-623
lines changed

README.md

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ CJD offers advanced diffing for Cyclonedx BOM (v1.5 or v1.6) produced by
6464
The `preset-diff --type bom` command compares CycloneDx BOM components, services, and dependencies, as well as data
6565
outside of these parts.
6666

67-
Some fields are excluded from the component comparison by default but can be explicitly specified
68-
for inclusion using `preset-diff --include-extra` and whichever field(s) you wish to include (e.g.
67+
Some component fields are excluded from the component comparison by default but can be explicitly
68+
specified for inclusion using `preset-diff --include-extra` and whichever field(s) you wish to include (e.g.
6969
`--include-extra properties,evidence,licenses`:
7070
- properties
7171
- evidence
@@ -149,14 +149,14 @@ vulnerabilities
149149
- title
150150

151151

152-
## Allowing newer versions
152+
### Allowing newer versions
153153

154-
[Currently BOM only] The --allow-new-versions option attempts to parse component versions and ascertain if a discrepancy
155-
is attributable to an updated version. Dependency refs and dependents are compared with the version
156-
string removed rather than checking for a newer version.
154+
[Currently BOM only] The --allow-new-versions option attempts to parse component versions and
155+
ascertain if a discrepancy is attributable to an updated version. Dependency refs and dependents
156+
are compared with the version string removed rather than checking for a newer version.
157157

158158

159-
## Allowing new data
159+
### Allowing new data
160160

161161
The --allow-new-data option allows for empty fields in the original BOM not to be reported as a
162162
difference when the data is populated in the second specified BOM. It also addresses when a field
@@ -165,6 +165,53 @@ additional elements in the newer BOM.
165165

166166
The --components-only option only analyzes components, not services, dependencies, or other data.
167167

168+
### Report Template
169+
170+
You may use the builtin report templates or create one of your own. The variables available to you
171+
for each preset type are as follows.
172+
173+
**BOM**
174+
* common_lib
175+
* common_frameworks
176+
* common_services
177+
* common_deps
178+
* common_apps
179+
* common_other
180+
* common_vdrs
181+
* diff_lib_1
182+
* diff_lib_2
183+
* diff_frameworks_1
184+
* diff_frameworks_2
185+
* diff_apps_1
186+
* diff_apps_2
187+
* diff_other_1
188+
* diff_other_2
189+
* diff_services_1
190+
* diff_services_2
191+
* diff_deps_1
192+
* diff_deps_2
193+
* diff_vdrs_1
194+
* diff_vdrs_2
195+
* bom_1 (filename)
196+
* bom_2
197+
* stats (this is a statistic summary)
198+
* metadata (a bool to indicate if misc_data passed)
199+
* diff_status (integer representing the diff status)
200+
201+
**CSAF**
202+
* common_document
203+
* common_product_tree
204+
* common_vulnerabilities
205+
* diff_document_1
206+
* diff_document_2
207+
* diff_product_tree_1
208+
* diff_product_tree_2
209+
* diff_vulnerabilities_1
210+
* diff_vulnerabilities_2
211+
* diff_status (integer representing the diff status)
212+
* csaf_1 (filename)
213+
* csaf_2
214+
168215

169216
## Specifying fields to exclude
170217

@@ -203,7 +250,8 @@ be, check out json-flatten, which is the package used for this function.
203250

204251
custom-json-diff will sort the imported JSON alphabetically. If your JSON document contains arrays
205252
of objects, you will need to specify any keys you want to sort by in a toml file or use a preset.
206-
The first key located from the provided keys that is present in the object will be used for sorting.
253+
The first key located from the provided keys that is present in the object will be used, so order
254+
any keys provided accordingly.
207255

208256
## TOML config file example
209257

custom_json_diff/cli.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ def build_args() -> argparse.Namespace:
9090
help="BOM only - include properties/evidence/licenses/hashes/externalReferences (list which with comma, no space, inbetween).",
9191
dest="include",
9292
)
93+
parser_pc_diff.add_argument(
94+
"--include-empty",
95+
"-e",
96+
action="store_true",
97+
default=False,
98+
dest="include_empty",
99+
help="Include keys with empty values in summary.",
100+
)
93101
parser.add_argument(
94102
"-x",
95103
"--exclude",
@@ -127,6 +135,7 @@ def main():
127135
file_2=args.input[1],
128136
output=args.output,
129137
report_template=args.report_template,
138+
include_empty=args.include_empty
130139
)
131140
result, j1, j2 = compare_dicts(options)
132141
if preset_type == "bom":

custom_json_diff/lib/bom_diff_template.j2

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<div class="table_summary2">
2929
<div></div>
3030
<div>
31-
<table style="width: 100%;">
31+
<table style="width: 100%">
3232
<tr>
3333
<th colspan="2"
3434
style="text-align: center; background-color: #d7ddde; border: 1px solid black;">
@@ -43,14 +43,13 @@
4343
</tr>
4444
{% endfor %}
4545
<tr>
46-
<td>Metadata matched:</td>
47-
{% if metadata %}
46+
<td>Other matched:</td>
47+
{% if misc_data_1 or misc_data_2 %}
4848
<td style="text-align: right">✖</td>
4949
{% endif %}
50-
{% if not metadata %}
50+
{% if not (misc_data_1 or misc_data_2) %}
5151
<td style="text-align: right">✔</td>
5252
{% endif %}
53-
5453
</tr>
5554
</table>
5655
</div>
@@ -87,27 +86,28 @@
8786
<tr>
8887
<th colspan="3"
8988
style="text-align: center; background-color: #d7ddde; border: 1px solid black;">
90-
Component
91-
Diff
89+
Element Diff
9290
</th>
9391
</tr>
94-
<tr>
95-
<th style="width: 8%"></th>
96-
<th style="text-align: center; width: 46%">{{ bom_1 }}</th>
97-
<th style="text-align: center; width: 46%">{{ bom_2 }}</th>
98-
</tr>
99-
{% if diff_status <= 2 %}
92+
{% if diff_status > 0 %}
93+
<tr>
94+
<th style="width: 8%"></th>
95+
<th style="text-align: center; width: 46%">{{ bom_1 }}</th>
96+
<th style="text-align: center; width: 46%">{{ bom_2 }}</th>
97+
</tr>
98+
{% endif %}
99+
{% if diff_status == 0 %}
100100
<tr>
101101
<td colspan="3" style="text-align: center">No differences found.</td>
102102
</tr>
103103
{% endif %}
104104
{% if diff_apps_1 or diff_apps_2 %}
105105
<tr>
106-
<th>applications<br><br>{{ diff_apps_1 | length }}
107-
vs {{ diff_apps_2 | length }}</th>
106+
<th>applications<br><br>{{ diff_apps_1|length }} vs {{ diff_apps_2|length }}
107+
</th>
108108
<td>{% for item in diff_apps_1 %}
109109
<details>
110-
<summary>{{ item['name'] }}@{{ item['version'] }}</summary>
110+
<summary>{{ item["name"] }}@{{ item["version"] }}</summary>
111111
<ul>
112112
{% for key, value in item|items %}
113113
{% if value != "" and key not in ["properties","evidence","hashes","licenses","externalReferences"] %}
@@ -154,7 +154,8 @@
154154
{% endfor %}
155155
</ul>
156156
</details>
157-
{% endfor %}</td>
157+
{% endfor %}
158+
</td>
158159
<td>{% for item in diff_apps_2 %}
159160
<details>
160161
<summary>{{ item['name'] }}@{{ item['version'] }}</summary>
@@ -693,14 +694,9 @@
693694
<summary>{{ key }}:</summary>
694695
<ul>
695696
{% for affect in value %}
696-
<details>
697-
<summary>{{ affect['ref'] }}:</summary>
698-
<ul>
699-
{% for a in affect['versions'] %}
700-
<li>{{ a }}</li>
701-
{% endfor %}
702-
</ul>
703-
</details>
697+
{% for a, b in affect|items %}
698+
<li>{{ a }}: {{ b }}</li>
699+
{% endfor %}
704700
{% endfor %}
705701
</ul>
706702
</details>
@@ -813,14 +809,9 @@
813809
<summary>{{ key }}:</summary>
814810
<ul>
815811
{% for affect in value %}
816-
<details>
817-
<summary>{{ affect['ref'] }}:</summary>
818-
<ul>
819-
{% for a in affect['versions'] %}
820-
<li>{{ a }}</li>
821-
{% endfor %}
822-
</ul>
823-
</details>
812+
{% for a, b in affect|items %}
813+
<li>{{ a }}: {{ b }}</li>
814+
{% endfor %}
824815
{% endfor %}
825816
</ul>
826817
</details>
@@ -870,6 +861,23 @@
870861
{% endfor %}</td>
871862
</tr>
872863
{% endif %}
864+
{% if misc_data_1 or misc_data_2 %}
865+
<tr>
866+
<th>other</th>
867+
{% if misc_data_1 %}
868+
<td>{{ misc_data_1 }}</td>
869+
{% endif %}
870+
{% if not misc_data_1 %}
871+
<td></td>
872+
{% endif %}
873+
{% if misc_data_1 %}
874+
<td>{{ misc_data_2 }}</td>
875+
{% endif %}
876+
{% if not misc_data_2 %}
877+
<td></td>
878+
{% endif %}
879+
</tr>
880+
{% endif %}
873881
</table>
874882
</div>
875883
<div></div>
@@ -883,10 +891,10 @@
883891
<th colspan="2"
884892
style="text-align: center; background-color: #d7ddde; border: 1px solid black;">
885893
Common
886-
Components
894+
Elements
887895
</th>
888896
</tr>
889-
{% if not (common_apps or common_frameworks or common_lib or common_other or common_services or common_deps or common_vdrs) %}
897+
{% if not (common_apps or common_frameworks or common_lib or common_other or common_services or common_deps or common_vdrs or common_misc_data) %}
890898
<tr>
891899
<td colspan="2" style="text-align: center">No commonalities.</td>
892900
</tr>
@@ -1068,11 +1076,10 @@
10681076
{% endfor %}</td>
10691077
</tr>
10701078
{% endif %}
1071-
10721079
{% if common_other %}
10731080
<tr>
10741081
<th>other types</th>
1075-
<td>{% for item in common_other %}
1082+
<td style="width: 41%">{% for item in common_other %}
10761083
<details>
10771084
<summary>{{ item['name'] }}@{{ item['version'] }}</summary>
10781085
<ul>
@@ -1173,7 +1180,7 @@
11731180
{% if common_vdrs %}
11741181
<tr>
11751182
<th style="width: 8%">vulnerabilities</th>
1176-
<td>{% for item in common_vdrs %}
1183+
<td style="width: 41%">{% for item in common_vdrs %}
11771184
<details>
11781185
<summary>{{ item['bom-ref'] }}</summary>
11791186
<ul>
@@ -1238,14 +1245,9 @@
12381245
<summary>{{ key }}:</summary>
12391246
<ul>
12401247
{% for affect in value %}
1241-
<details>
1242-
<summary>{{ affect['ref'] }}:</summary>
1243-
<ul>
1244-
{% for a in affect['versions'] %}
1245-
<li>{{ a }}</li>
1246-
{% endfor %}
1247-
</ul>
1248-
</details>
1248+
{% for a, b in affect|items %}
1249+
<li>{{ a }}: {{ b }}</li>
1250+
{% endfor %}
12491251
{% endfor %}
12501252
</ul>
12511253
</details>
@@ -1295,6 +1297,12 @@
12951297
{% endfor %}</td>
12961298
</tr>
12971299
{% endif %}
1300+
{% if common_misc_data %}
1301+
<tr>
1302+
<th style="width: 8%">other</th>
1303+
<td style="width: 41%">{{ common_misc_data }}</td>
1304+
</tr>
1305+
{% endif %}
12981306
</table>
12991307
</div>
13001308
<div></div>

0 commit comments

Comments
 (0)