Skip to content

Commit 4c9616b

Browse files
authored
feat: Add sha256, sha384 and sha512 options (#60)
1 parent f0c4b78 commit 4c9616b

File tree

9 files changed

+78
-37
lines changed

9 files changed

+78
-37
lines changed

nodes/DependencyAnalytics/Actions.spec.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,11 @@ describe('Tests for actions/vulnerability.ts', () => {
409409
});
410410
});
411411

412-
describe('inputType: sbomSha256', () => {
413-
it('It should analyze vulnerabilities by SBOM SHA256', async () => {
414-
ctx.getNodeParameter.mockReturnValueOnce('sbomSha256').mockReturnValueOnce('abc123def456');
412+
describe('inputType: sbomSha', () => {
413+
it('It should analyze vulnerabilities by SBOM SHA (prefixed)', async () => {
414+
ctx.getNodeParameter
415+
.mockReturnValueOnce('sbomSha')
416+
.mockReturnValueOnce('sha256:abc123def456');
415417

416418
const sbomResponse = { id: 'sbom-123' };
417419
const advisoryResponse = [{ id: 'ADV-1' }];
@@ -426,8 +428,7 @@ describe('Tests for actions/vulnerability.ts', () => {
426428
fakeCredential,
427429
expect.objectContaining({
428430
method: 'GET',
429-
url: `${fakeBase}/sbom/sha256:abc123def456`,
430-
qs: { query: 'abc123def456' },
431+
url: `${fakeBase}/sbom/${encodeURIComponent('sha256:abc123def456')}`,
431432
}),
432433
);
433434
expect(authedRequest).toHaveBeenNthCalledWith(
@@ -450,22 +451,22 @@ describe('Tests for actions/vulnerability.ts', () => {
450451
});
451452

452453
it('It should throw error if SBOM SHA256 is empty', async () => {
453-
ctx.getNodeParameter.mockReturnValueOnce('sbomSha256').mockReturnValueOnce(' ');
454+
ctx.getNodeParameter.mockReturnValueOnce('sbomSha').mockReturnValueOnce(' ');
454455

455456
(throwError as unknown as jest.Mock).mockImplementation(() => {
456-
throw new Error('SHA256 required');
457+
throw new Error('SBOM SHA required');
457458
});
458459

459460
await expect(vulnerability.analyze({ ctx, itemIndex: 0 })).rejects.toThrow();
460461
expect(throwError).toHaveBeenCalledWith(
461462
expect.anything(),
462-
"The 'SBOM SHA-256' parameter is required.",
463+
"The 'SBOM SHA' parameter is required.",
463464
0,
464465
);
465466
});
466467

467468
it('It should throw error if SBOM not found', async () => {
468-
ctx.getNodeParameter.mockReturnValueOnce('sbomSha256').mockReturnValueOnce('nonexistent');
469+
ctx.getNodeParameter.mockReturnValueOnce('sbomSha').mockReturnValueOnce('sha256:abc123');
469470

470471
(authedRequest as jest.Mock).mockResolvedValueOnce({});
471472
(throwError as unknown as jest.Mock).mockImplementation(() => {
@@ -475,7 +476,7 @@ describe('Tests for actions/vulnerability.ts', () => {
475476
await expect(vulnerability.analyze({ ctx, itemIndex: 0 })).rejects.toThrow();
476477
expect(throwError).toHaveBeenCalledWith(
477478
expect.anything(),
478-
"No SBOM found for the provided value in 'SBOM SHA-256'.",
479+
"No SBOM found for the provided value in 'SBOM SHA'.",
479480
0,
480481
);
481482
});

nodes/DependencyAnalytics/DependencyAnalytics.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ test('It contains all expected displayNames in properties', () => {
3232
'Operation',
3333
'Input Type',
3434
'PURLs',
35-
'SBOM SHA-256',
35+
'SBOM SHA',
3636
'Sorting',
3737
'Selected Fields',
3838
'Operation',

nodes/DependencyAnalytics/actions/advisory.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ export async function get({ ctx, itemIndex }: { ctx: IExecuteFunctions; itemInde
1212
if (!identifierRaw)
1313
throwError(ctx.getNode(), "The 'Identifier' parameter is required.", itemIndex);
1414

15+
// If a bare SHA digest is provided without a sha* prefix, instruct the user to add it
16+
if (
17+
(/^[a-f0-9]{64}$/i.test(identifierRaw) ||
18+
/^[a-f0-9]{96}$/i.test(identifierRaw) ||
19+
/^[a-f0-9]{128}$/i.test(identifierRaw)) &&
20+
!/^sha(?:256|384|512):/i.test(identifierRaw)
21+
) {
22+
throwError(
23+
ctx.getNode(),
24+
"Provide 'SBOM SHA' with a prefix: sha256:, sha384:, or sha512:.",
25+
itemIndex,
26+
);
27+
}
28+
1529
const options: IHttpRequestOptions = {
1630
method: 'GET',
1731
url: `${base}/advisory/${encodeURIComponent(identifierRaw)}`,

nodes/DependencyAnalytics/actions/sbom.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@ export async function get({ ctx, itemIndex }: { ctx: IExecuteFunctions; itemInde
1212
if (!identifierRaw)
1313
throwError(ctx.getNode(), "The 'Identifier' parameter is required.", itemIndex);
1414

15-
const normalizedId = /^sha256:/i.test(identifierRaw)
16-
? identifierRaw
17-
: /^[a-f0-9]{64}$/i.test(identifierRaw)
18-
? `sha256:${identifierRaw}`
19-
: identifierRaw;
15+
// If a bare SHA digest is provided without a sha* prefix, instruct the user to add it
16+
if (
17+
(/^[a-f0-9]{64}$/i.test(identifierRaw) ||
18+
/^[a-f0-9]{96}$/i.test(identifierRaw) ||
19+
/^[a-f0-9]{128}$/i.test(identifierRaw)) &&
20+
!/^sha(?:256|384|512):/i.test(identifierRaw)
21+
) {
22+
throwError(
23+
ctx.getNode(),
24+
"Provide 'SBOM SHA' with a prefix: sha256:, sha384:, or sha512:.",
25+
itemIndex,
26+
);
27+
}
28+
29+
const normalizedId = identifierRaw;
2030

2131
const options: IHttpRequestOptions = {
2232
method: 'GET',

nodes/DependencyAnalytics/actions/vulnerability.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export async function getMany({ ctx, itemIndex }: { ctx: IExecuteFunctions; item
5353
export async function analyze({ ctx, itemIndex }: { ctx: IExecuteFunctions; itemIndex: number }) {
5454
const credentialName = chooseCredential(ctx, itemIndex);
5555
const base = getBase(ctx, itemIndex);
56-
const inputType = ctx.getNodeParameter('inputType', itemIndex) as 'sbomSha256' | 'purls';
56+
const inputType = ctx.getNodeParameter('inputType', itemIndex) as 'sbomSha' | 'purls';
5757

5858
if (inputType === 'purls') {
5959
const raw = ctx.getNodeParameter('purlsRaw', itemIndex) as unknown;
@@ -82,11 +82,7 @@ export async function analyze({ ctx, itemIndex }: { ctx: IExecuteFunctions; item
8282

8383
const isPlainObject = (v: any) => v && typeof v === 'object' && !Array.isArray(v);
8484
if (isPlainObject(res)) {
85-
// Prefer the map keyed by PURL shape: { [purl]: { details: [...] } }
8685
for (const [pkgPurl, data] of Object.entries(res as Record<string, any>)) {
87-
// Support both shapes:
88-
// 1) { details: [...] }
89-
// 2) [ { ...vulnerabilityDetail... }, ... ]
9086
const details = Array.isArray(data)
9187
? (data as any[])
9288
: Array.isArray((data as any)?.details)
@@ -219,22 +215,26 @@ export async function analyze({ ctx, itemIndex }: { ctx: IExecuteFunctions; item
219215
}
220216
}
221217

222-
// inputType === 'sbomSha256'
223-
const q = (ctx.getNodeParameter('sbomSha256', itemIndex) as string)?.trim();
224-
if (!q) throwError(ctx.getNode(), "The 'SBOM SHA-256' parameter is required.", itemIndex);
218+
const q = (ctx.getNodeParameter('sbomSha', itemIndex) as string)?.trim();
219+
if (!q) throwError(ctx.getNode(), "The 'SBOM SHA' parameter is required.", itemIndex);
220+
if (!/^sha(?:256|384|512):[a-f0-9]+$/i.test(q)) {
221+
throwError(
222+
ctx.getNode(),
223+
"Provide 'SBOM SHA' with a prefix: sha256:, sha384:, or sha512:.",
224+
itemIndex,
225+
);
226+
}
225227

226-
// SBOM by sha256
227228
const listOpts: IHttpRequestOptions = {
228229
method: 'GET',
229-
url: `${base}/sbom/sha256:${q}`,
230-
qs: { query: q },
230+
url: `${base}/sbom/${encodeURIComponent(q)}`,
231231
returnFullResponse: false,
232232
};
233233

234234
const listResp = (await authedRequest(ctx, credentialName, listOpts)) as any;
235235
const sbomId = listResp?.id;
236236
if (!sbomId)
237-
throwError(ctx.getNode(), "No SBOM found for the provided value in 'SBOM SHA-256'.", itemIndex);
237+
throwError(ctx.getNode(), "No SBOM found for the provided value in 'SBOM SHA'.", itemIndex);
238238

239239
// Advisories for SBOM
240240
const advOpts: IHttpRequestOptions = {

nodes/DependencyAnalytics/descriptions/advisory.properties.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const advisoryProperties: INodeProperties[] = [
66
name: 'advisorySelectedFields',
77
type: 'multiOptions',
88
default: [],
9+
description: "Fields to include when 'Selected Fields' output mode is selected",
910
options: [
1011
{ name: 'Average Score', value: 'average_score' },
1112
{ name: 'Average Severity', value: 'average_severity' },
@@ -48,6 +49,7 @@ export const advisoryProperties: INodeProperties[] = [
4849
name: 'sortingAdvisory',
4950
type: 'fixedCollection',
5051
placeholder: 'Add sort rule',
52+
description: 'Add one or more sorting rules to order the advisories',
5153
typeOptions: { multipleValues: true },
5254
displayOptions: { show: { operation: ['getMany'], resource: ['advisory'] } },
5355
default: {},
@@ -60,6 +62,7 @@ export const advisoryProperties: INodeProperties[] = [
6062
displayName: 'Field',
6163
name: 'field',
6264
type: 'options',
65+
description: 'Property to sort by',
6366
options: [
6467
{ name: 'Average Score', value: 'average_score' },
6568
{ name: 'Average Severity', value: 'average_severity' },
@@ -73,6 +76,7 @@ export const advisoryProperties: INodeProperties[] = [
7376
displayName: 'Direction',
7477
name: 'direction',
7578
type: 'options',
79+
description: 'Sort order',
7680
options: [
7781
{ name: 'Ascending', value: 'asc' },
7882
{ name: 'Descending', value: 'desc' },

nodes/DependencyAnalytics/descriptions/common.properties.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export const commonProperties: INodeProperties[] = [
3232
{ name: 'Advisory', value: 'advisory' },
3333
],
3434
default: 'vulnerability',
35+
description:
36+
'Choose which Trustify resource to work with. This affects available operations and fields.',
3537
},
3638

3739
// common “get” param
@@ -41,8 +43,8 @@ export const commonProperties: INodeProperties[] = [
4143
type: 'string',
4244
required: true,
4345
default: '',
44-
description: 'The SHA-256 ID or normalized identifier',
45-
placeholder: 'e.g. 3a7bd3e2360a3d...',
46+
description: 'SHA ID (sha256|sha384|sha512) or a normalized identifier',
47+
placeholder: 'e.g. sha256:3a7bd3e2360a3d…, CVE-2024-1234',
4648
displayOptions: {
4749
show: { operation: ['get'], resource: ['sbom', 'vulnerability', 'advisory'] },
4850
},

nodes/DependencyAnalytics/descriptions/sbom.properties.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const sbomProperties: INodeProperties[] = [
4747
name: 'sortingSbom',
4848
type: 'fixedCollection',
4949
placeholder: 'Add sort rule',
50+
description: 'Add one or more sorting rules to order the SBOMs',
5051
typeOptions: { multipleValues: true },
5152
displayOptions: { show: { operation: ['getMany'], resource: ['sbom'] } },
5253
default: {},
@@ -59,6 +60,7 @@ export const sbomProperties: INodeProperties[] = [
5960
displayName: 'Field',
6061
name: 'field',
6162
type: 'options',
63+
description: 'Property to sort by',
6264
options: [
6365
{ name: 'Name', value: 'name' },
6466
{ name: 'Packages (Count)', value: 'number_of_packages' },
@@ -70,6 +72,7 @@ export const sbomProperties: INodeProperties[] = [
7072
displayName: 'Direction',
7173
name: 'direction',
7274
type: 'options',
75+
description: 'Sort order',
7376
options: [
7477
{ name: 'Ascending', value: 'asc' },
7578
{ name: 'Descending', value: 'desc' },

nodes/DependencyAnalytics/descriptions/vulnerability.properties.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
66
name: 'vulnSelectedFields',
77
type: 'multiOptions',
88
default: [],
9+
description: "Fields to include when 'Selected Fields' output mode is selected",
910
options: [
1011
{ name: 'Advisories', value: 'advisories' },
1112
{ name: 'CWEs', value: 'cwes' },
@@ -33,6 +34,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
3334
name: 'advisorySelectedFields',
3435
type: 'multiOptions',
3536
default: [],
37+
description: "Advisory fields to include when 'Selected Fields' output mode is selected",
3638
options: [
3739
{ name: 'CWEs', value: 'cwes' },
3840
{ name: 'Description', value: 'description' },
@@ -59,7 +61,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
5961
show: {
6062
resource: ['vulnerability'],
6163
operation: ['analyze'],
62-
inputType: ['purls', 'sbomSha256'],
64+
inputType: ['purls', 'sbomSha'],
6365
outputMode: ['selected'],
6466
},
6567
},
@@ -97,9 +99,10 @@ export const vulnerabilityProperties: INodeProperties[] = [
9799
displayName: 'Input Type',
98100
name: 'inputType',
99101
type: 'options',
102+
description: 'Analyze by providing PURLs directly or by referencing an SBOM via SHA',
100103
options: [
101104
{ name: 'PURLs (Multiline)', value: 'purls' },
102-
{ name: 'SBOM Lookup (SHA-256)', value: 'sbomSha256' },
105+
{ name: 'SBOM Lookup (SHA)', value: 'sbomSha' },
103106
],
104107
default: 'purls',
105108
displayOptions: { show: { resource: ['vulnerability'], operation: ['analyze'] } },
@@ -118,14 +121,15 @@ export const vulnerabilityProperties: INodeProperties[] = [
118121
},
119122
},
120123
{
121-
displayName: 'SBOM SHA-256',
122-
name: 'sbomSha256',
124+
displayName: 'SBOM SHA',
125+
name: 'sbomSha',
123126
type: 'string',
124127
default: '',
125-
placeholder: 'e.g. 3a7bd3e2360a3d…',
126-
description: 'The SHA-256 checksum of the SBOM file to analyze',
128+
placeholder: 'e.g. sha256:3a7bd3…, sha384:…, or sha512:…',
129+
description:
130+
'SHA checksum of the SBOM to analyze. Format: sha256:[64-hex] | sha384:[96-hex] | sha512:[128-hex].',
127131
displayOptions: {
128-
show: { resource: ['vulnerability'], operation: ['analyze'], inputType: ['sbomSha256'] },
132+
show: { resource: ['vulnerability'], operation: ['analyze'], inputType: ['sbomSha'] },
129133
},
130134
},
131135

@@ -134,6 +138,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
134138
name: 'sortingVuln',
135139
type: 'fixedCollection',
136140
placeholder: 'Add sort rule',
141+
description: 'Add one or more sorting rules to order the vulnerabilities',
137142
typeOptions: { multipleValues: true },
138143
displayOptions: { show: { operation: ['getMany', 'analyze'], resource: ['vulnerability'] } },
139144
default: {},
@@ -146,6 +151,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
146151
displayName: 'Field',
147152
name: 'field',
148153
type: 'options',
154+
description: 'Property to sort by',
149155
options: [
150156
{ name: 'Identifier (e.g., CVE)', value: 'identifier' },
151157
{ name: 'Title', value: 'title' },
@@ -157,6 +163,7 @@ export const vulnerabilityProperties: INodeProperties[] = [
157163
displayName: 'Direction',
158164
name: 'direction',
159165
type: 'options',
166+
description: 'Sort order',
160167
options: [
161168
{ name: 'Ascending', value: 'asc' },
162169
{ name: 'Descending', value: 'desc' },

0 commit comments

Comments
 (0)