@backstage-community/plugin-mend-backend 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/api/index.cjs.js +68 -0
- package/dist/api/index.cjs.js.map +1 -0
- package/dist/index.cjs.js +11 -742
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/permission/conditions.cjs.js +33 -0
- package/dist/permission/conditions.cjs.js.map +1 -0
- package/dist/permission/permissions.cjs.js +17 -0
- package/dist/permission/permissions.cjs.js.map +1 -0
- package/dist/permission/rules.cjs.js +31 -0
- package/dist/permission/rules.cjs.js.map +1 -0
- package/dist/plugin.cjs.js +48 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/service/auth.service.cjs.js +93 -0
- package/dist/service/auth.service.cjs.js.map +1 -0
- package/dist/service/auth.service.helpers.cjs.js +14 -0
- package/dist/service/auth.service.helpers.cjs.js.map +1 -0
- package/dist/service/data.service.cjs.js +65 -0
- package/dist/service/data.service.cjs.js.map +1 -0
- package/dist/service/data.service.helpers.cjs.js +248 -0
- package/dist/service/data.service.helpers.cjs.js.map +1 -0
- package/dist/service/data.service.types.cjs.js +11 -0
- package/dist/service/data.service.types.cjs.js.map +1 -0
- package/dist/service/router.cjs.js +194 -0
- package/dist/service/router.cjs.js.map +1 -0
- package/package.json +20 -13
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var pathToRegexp = require('path-to-regexp');
|
|
4
|
+
var data_service_types = require('./data.service.types.cjs.js');
|
|
5
|
+
|
|
6
|
+
const dataProjectParser = (projectStatistics, organizationProjects) => {
|
|
7
|
+
const organizationData = organizationProjects.reduce((prev, next) => {
|
|
8
|
+
prev[next.uuid] = next;
|
|
9
|
+
return prev;
|
|
10
|
+
}, {});
|
|
11
|
+
const projectData = projectStatistics.reduce(
|
|
12
|
+
(prev, next) => {
|
|
13
|
+
const dependenciesCritical = next.statistics["ALERTS" /* DEPENDENCIES */].criticalSeverityVulnerabilities;
|
|
14
|
+
const dependenciesHigh = next.statistics["ALERTS" /* DEPENDENCIES */].highSeverityVulnerabilities;
|
|
15
|
+
const dependenciesMedium = next.statistics["ALERTS" /* DEPENDENCIES */].mediumSeverityVulnerabilities;
|
|
16
|
+
const dependenciesLow = next.statistics["ALERTS" /* DEPENDENCIES */].lowSeverityVulnerabilities;
|
|
17
|
+
const dependeciesTotal = dependenciesCritical + dependenciesHigh + dependenciesMedium + dependenciesLow;
|
|
18
|
+
const codeHigh = next.statistics["SAST_VULNERABILITIES_BY_SEVERITY" /* CODE */].sastHighVulnerabilities;
|
|
19
|
+
const codeMedium = next.statistics["SAST_VULNERABILITIES_BY_SEVERITY" /* CODE */].sastMediumVulnerabilities;
|
|
20
|
+
const codeLow = next.statistics["SAST_VULNERABILITIES_BY_SEVERITY" /* CODE */].sastLowVulnerabilities;
|
|
21
|
+
const codeTotal = codeHigh + codeMedium + codeLow;
|
|
22
|
+
const containersCritical = next.statistics["IMG_SECURITY" /* CONTAINERS */].imgCriticalVulnerabilities;
|
|
23
|
+
const containersHigh = next.statistics["IMG_SECURITY" /* CONTAINERS */].imgHighVulnerabilities;
|
|
24
|
+
const containersMedium = next.statistics["IMG_SECURITY" /* CONTAINERS */].imgMediumVulnerabilities;
|
|
25
|
+
const containersLow = next.statistics["IMG_SECURITY" /* CONTAINERS */].imgLowVulnerabilities;
|
|
26
|
+
const containersTotal = containersCritical + containersHigh + containersMedium + containersLow;
|
|
27
|
+
const criticalTotal = dependenciesCritical + containersCritical;
|
|
28
|
+
const highTotal = dependenciesHigh + codeHigh + containersHigh;
|
|
29
|
+
const mediumTotal = dependenciesMedium + codeMedium + containersMedium;
|
|
30
|
+
const lowTotal = dependenciesLow + codeLow + containersLow;
|
|
31
|
+
const total = dependeciesTotal + codeTotal + containersTotal;
|
|
32
|
+
const statistics = {
|
|
33
|
+
[data_service_types.StatisticsEngine.DEPENDENCIES]: {
|
|
34
|
+
critical: dependenciesCritical,
|
|
35
|
+
high: dependenciesHigh,
|
|
36
|
+
medium: dependenciesMedium,
|
|
37
|
+
low: dependenciesLow,
|
|
38
|
+
total: dependeciesTotal
|
|
39
|
+
},
|
|
40
|
+
[data_service_types.StatisticsEngine.CODE]: {
|
|
41
|
+
critical: null,
|
|
42
|
+
high: codeHigh,
|
|
43
|
+
medium: codeMedium,
|
|
44
|
+
low: codeLow,
|
|
45
|
+
total: codeTotal
|
|
46
|
+
},
|
|
47
|
+
[data_service_types.StatisticsEngine.CONTAINERS]: {
|
|
48
|
+
critical: containersCritical,
|
|
49
|
+
high: containersHigh,
|
|
50
|
+
medium: containersMedium,
|
|
51
|
+
low: containersLow,
|
|
52
|
+
total: containersTotal
|
|
53
|
+
},
|
|
54
|
+
critical: criticalTotal,
|
|
55
|
+
high: highTotal,
|
|
56
|
+
medium: mediumTotal,
|
|
57
|
+
low: lowTotal,
|
|
58
|
+
total
|
|
59
|
+
};
|
|
60
|
+
const project = {
|
|
61
|
+
statistics,
|
|
62
|
+
uuid: next.uuid,
|
|
63
|
+
name: next.name,
|
|
64
|
+
path: next.path,
|
|
65
|
+
entity: next.entity,
|
|
66
|
+
applicationName: organizationData[next.uuid].applicationName,
|
|
67
|
+
applicationUuid: next.applicationUuid,
|
|
68
|
+
lastScan: next.statistics["LAST_SCAN" /* LAST_SCAN */].lastScanTime,
|
|
69
|
+
languages: Object.entries(next.statistics.LIBRARY_TYPE_HISTOGRAM).sort(
|
|
70
|
+
(a, b) => b[1] - a[1]
|
|
71
|
+
)
|
|
72
|
+
};
|
|
73
|
+
prev.projectList.unshift(project);
|
|
74
|
+
return prev;
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
projectList: []
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
projectData.projectList.sort(
|
|
81
|
+
(a, b) => b.statistics.critical - a.statistics.critical
|
|
82
|
+
);
|
|
83
|
+
return projectData;
|
|
84
|
+
};
|
|
85
|
+
const parseEntityURL = (entityUrl) => {
|
|
86
|
+
try {
|
|
87
|
+
if (!entityUrl) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const matches = entityUrl.match(
|
|
91
|
+
/https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(:[0-9]{1,5})?(\/.*)?/g
|
|
92
|
+
);
|
|
93
|
+
if (!matches) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const url = new URL(matches[0]);
|
|
97
|
+
const fn = pathToRegexp.match("/:org/:repo", { end: false });
|
|
98
|
+
return fn(url.pathname);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const dataMatcher = (entities, projects) => {
|
|
104
|
+
return entities.reduce(
|
|
105
|
+
(prev, next) => {
|
|
106
|
+
const entityURL = parseEntityURL(
|
|
107
|
+
next?.metadata?.annotations?.["backstage.io/source-location"]
|
|
108
|
+
);
|
|
109
|
+
if (!entityURL) {
|
|
110
|
+
return prev;
|
|
111
|
+
}
|
|
112
|
+
const project = projects.find(
|
|
113
|
+
(item) => item.path.match(/^GH_(.*)/)?.[1] === entityURL?.params.repo
|
|
114
|
+
);
|
|
115
|
+
if (!project) {
|
|
116
|
+
return prev;
|
|
117
|
+
}
|
|
118
|
+
const entity = {
|
|
119
|
+
path: entityURL.path,
|
|
120
|
+
params: entityURL.params,
|
|
121
|
+
namespace: next.metadata.namespace,
|
|
122
|
+
kind: "component",
|
|
123
|
+
source: "catalog"
|
|
124
|
+
};
|
|
125
|
+
prev.push({ ...project, entity });
|
|
126
|
+
return prev;
|
|
127
|
+
},
|
|
128
|
+
[]
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
const getIssueStatus = (engine, finding) => {
|
|
132
|
+
if (engine === data_service_types.StatisticsEngine.CODE) {
|
|
133
|
+
if (finding?.suppressed)
|
|
134
|
+
return "suppressed";
|
|
135
|
+
if (finding?.almIssues?.jiraPlatform?.issueStatus)
|
|
136
|
+
return "created";
|
|
137
|
+
if (finding?.reviewed)
|
|
138
|
+
return "reviewed";
|
|
139
|
+
}
|
|
140
|
+
if (engine === data_service_types.StatisticsEngine.DEPENDENCIES) {
|
|
141
|
+
if (finding?.findingInfo?.status === "IGNORED")
|
|
142
|
+
return "suppressed";
|
|
143
|
+
}
|
|
144
|
+
return "unreviewed";
|
|
145
|
+
};
|
|
146
|
+
const dataFindingParser = (code = [], dependencies = [], containers = []) => {
|
|
147
|
+
let codeFindings = [];
|
|
148
|
+
let dependenciesFindings = [];
|
|
149
|
+
let containersFindings = [];
|
|
150
|
+
if (code.length) {
|
|
151
|
+
codeFindings = code.map((finding) => {
|
|
152
|
+
return {
|
|
153
|
+
kind: data_service_types.StatisticsEngine.CODE,
|
|
154
|
+
level: finding.severity.toLowerCase(),
|
|
155
|
+
name: finding.type.cwe.title,
|
|
156
|
+
origin: `${finding.sharedStep.file}:${finding.sharedStep.line}`,
|
|
157
|
+
time: finding?.createdTime,
|
|
158
|
+
issue: {
|
|
159
|
+
issueStatus: finding.almIssues.jiraPlatform.issueStatus,
|
|
160
|
+
reporter: finding.almIssues.jiraPlatform.createdByName,
|
|
161
|
+
creationDate: finding.almIssues.jiraPlatform.createdTime,
|
|
162
|
+
ticketName: finding.almIssues.jiraPlatform.issueKey,
|
|
163
|
+
link: `${finding.almIssues.jiraPlatform.publicLink}/browse/${finding.almIssues.jiraPlatform.issueKey}`,
|
|
164
|
+
status: getIssueStatus(data_service_types.StatisticsEngine.CODE, finding)
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (dependencies.length) {
|
|
170
|
+
dependenciesFindings = dependencies.map((finding) => {
|
|
171
|
+
return {
|
|
172
|
+
kind: data_service_types.StatisticsEngine.DEPENDENCIES,
|
|
173
|
+
level: finding.vulnerability.severity.toLowerCase(),
|
|
174
|
+
name: finding.vulnerability.name,
|
|
175
|
+
origin: finding.component.name,
|
|
176
|
+
time: finding.vulnerability.modifiedDate,
|
|
177
|
+
issue: {
|
|
178
|
+
issueStatus: "",
|
|
179
|
+
reporter: "",
|
|
180
|
+
creationDate: "",
|
|
181
|
+
ticketName: "",
|
|
182
|
+
link: "",
|
|
183
|
+
status: getIssueStatus(data_service_types.StatisticsEngine.DEPENDENCIES, finding)
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (containers.length) {
|
|
189
|
+
containersFindings = containers.map((finding) => {
|
|
190
|
+
return {
|
|
191
|
+
kind: data_service_types.StatisticsEngine.CONTAINERS,
|
|
192
|
+
level: finding.severity.toLowerCase(),
|
|
193
|
+
name: finding.vulnerabilityId,
|
|
194
|
+
origin: finding.packageName,
|
|
195
|
+
time: finding.detectionDate,
|
|
196
|
+
issue: {
|
|
197
|
+
issueStatus: "",
|
|
198
|
+
reporter: "",
|
|
199
|
+
creationDate: "",
|
|
200
|
+
ticketName: "",
|
|
201
|
+
link: "",
|
|
202
|
+
status: getIssueStatus(data_service_types.StatisticsEngine.CONTAINERS, finding)
|
|
203
|
+
// NOTE: Currently, issue for finding in containers no exist.
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
const order = {
|
|
209
|
+
critical: 1,
|
|
210
|
+
high: 2,
|
|
211
|
+
medium: 3,
|
|
212
|
+
low: 4
|
|
213
|
+
};
|
|
214
|
+
return [...codeFindings, ...dependenciesFindings, ...containersFindings].sort(
|
|
215
|
+
(a, b) => {
|
|
216
|
+
return order[a.level] - order[b.level];
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
};
|
|
220
|
+
const parseQueryString = (href = "?") => {
|
|
221
|
+
const [, queryString] = href.split("?");
|
|
222
|
+
const queryParams = {};
|
|
223
|
+
new URLSearchParams(queryString).forEach((val, key) => {
|
|
224
|
+
queryParams[key] = val;
|
|
225
|
+
});
|
|
226
|
+
return queryParams;
|
|
227
|
+
};
|
|
228
|
+
const fetchQueryPagination = async (cb) => {
|
|
229
|
+
const defaultQueryParams = { limit: "10000", cursor: "0" };
|
|
230
|
+
const collection = [];
|
|
231
|
+
const fetchLoop = async (queryParams) => {
|
|
232
|
+
const result = await cb({ queryParams });
|
|
233
|
+
collection.push(...result.response);
|
|
234
|
+
const nextQuery = result.additionalData?.paging?.next;
|
|
235
|
+
if (nextQuery) {
|
|
236
|
+
const newQueryParams = parseQueryString(nextQuery);
|
|
237
|
+
await fetchLoop(newQueryParams);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
await fetchLoop(defaultQueryParams);
|
|
241
|
+
return collection;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
exports.dataFindingParser = dataFindingParser;
|
|
245
|
+
exports.dataMatcher = dataMatcher;
|
|
246
|
+
exports.dataProjectParser = dataProjectParser;
|
|
247
|
+
exports.fetchQueryPagination = fetchQueryPagination;
|
|
248
|
+
//# sourceMappingURL=data.service.helpers.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.service.helpers.cjs.js","sources":["../../src/service/data.service.helpers.ts"],"sourcesContent":["import { Entity } from '@backstage/catalog-model';\nimport { match } from 'path-to-regexp';\nimport type { QueryParams } from '../api';\nimport {\n ProjectStatisticsSuccessResponseData,\n EntityURL,\n OrganizationProjectSuccessResponseData,\n PaginationQueryParams,\n Project,\n CodeFindingSuccessResponseData,\n DependenciesFindingSuccessResponseData,\n ContainersFindingSuccessResponseData,\n Finding,\n StatisticsEngine,\n StatisticsName,\n} from './data.service.types';\n\nenum FINDING_TYPE {\n DEPENDENCIES = 'ALERTS',\n CODE = 'SAST_VULNERABILITIES_BY_SEVERITY',\n CONTAINERS = 'IMG_SECURITY',\n LAST_SCAN = 'LAST_SCAN',\n}\n\ntype OverviewData = {\n projectList: Project[];\n};\n\nexport const dataProjectParser = (\n projectStatistics: Array<\n ProjectStatisticsSuccessResponseData & { entity: EntityURL }\n >,\n organizationProjects: OrganizationProjectSuccessResponseData[],\n) => {\n const organizationData = organizationProjects.reduce((prev, next) => {\n prev[next.uuid] = next;\n return prev;\n }, {} as { [key: string]: OrganizationProjectSuccessResponseData });\n\n const projectData = projectStatistics.reduce(\n (\n prev: OverviewData,\n next: ProjectStatisticsSuccessResponseData & { entity: EntityURL },\n ) => {\n const dependenciesCritical =\n next.statistics[FINDING_TYPE.DEPENDENCIES]\n .criticalSeverityVulnerabilities;\n const dependenciesHigh =\n next.statistics[FINDING_TYPE.DEPENDENCIES].highSeverityVulnerabilities;\n const dependenciesMedium =\n next.statistics[FINDING_TYPE.DEPENDENCIES]\n .mediumSeverityVulnerabilities;\n const dependenciesLow =\n next.statistics[FINDING_TYPE.DEPENDENCIES].lowSeverityVulnerabilities;\n const dependeciesTotal =\n dependenciesCritical +\n dependenciesHigh +\n dependenciesMedium +\n dependenciesLow;\n\n const codeHigh =\n next.statistics[FINDING_TYPE.CODE].sastHighVulnerabilities;\n const codeMedium =\n next.statistics[FINDING_TYPE.CODE].sastMediumVulnerabilities;\n const codeLow = next.statistics[FINDING_TYPE.CODE].sastLowVulnerabilities;\n const codeTotal = codeHigh + codeMedium + codeLow;\n\n const containersCritical =\n next.statistics[FINDING_TYPE.CONTAINERS].imgCriticalVulnerabilities;\n const containersHigh =\n next.statistics[FINDING_TYPE.CONTAINERS].imgHighVulnerabilities;\n const containersMedium =\n next.statistics[FINDING_TYPE.CONTAINERS].imgMediumVulnerabilities;\n const containersLow =\n next.statistics[FINDING_TYPE.CONTAINERS].imgLowVulnerabilities;\n const containersTotal =\n containersCritical + containersHigh + containersMedium + containersLow;\n\n const criticalTotal = dependenciesCritical + containersCritical;\n const highTotal = dependenciesHigh + codeHigh + containersHigh;\n const mediumTotal = dependenciesMedium + codeMedium + containersMedium;\n const lowTotal = dependenciesLow + codeLow + containersLow;\n const total = dependeciesTotal + codeTotal + containersTotal;\n\n const statistics = {\n [StatisticsEngine.DEPENDENCIES]: {\n critical: dependenciesCritical,\n high: dependenciesHigh,\n medium: dependenciesMedium,\n low: dependenciesLow,\n total: dependeciesTotal,\n },\n [StatisticsEngine.CODE]: {\n critical: null,\n high: codeHigh,\n medium: codeMedium,\n low: codeLow,\n total: codeTotal,\n },\n [StatisticsEngine.CONTAINERS]: {\n critical: containersCritical,\n high: containersHigh,\n medium: containersMedium,\n low: containersLow,\n total: containersTotal,\n },\n critical: criticalTotal,\n high: highTotal,\n medium: mediumTotal,\n low: lowTotal,\n total: total,\n };\n\n const project = {\n statistics,\n uuid: next.uuid,\n name: next.name,\n path: next.path,\n entity: next.entity,\n applicationName: organizationData[next.uuid].applicationName,\n applicationUuid: next.applicationUuid,\n lastScan: next.statistics[FINDING_TYPE.LAST_SCAN].lastScanTime,\n languages: Object.entries(next.statistics.LIBRARY_TYPE_HISTOGRAM).sort(\n (a, b) => b[1] - a[1],\n ),\n };\n\n prev.projectList.unshift(project);\n return prev;\n },\n {\n projectList: [],\n },\n );\n\n projectData.projectList.sort(\n (a, b) => b.statistics.critical - a.statistics.critical,\n );\n\n return projectData;\n};\n\nconst parseEntityURL = (entityUrl?: string) => {\n try {\n if (!entityUrl) {\n return null;\n }\n\n const matches = entityUrl.match(\n /https?:\\/\\/[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,}(:[0-9]{1,5})?(\\/.*)?/g,\n );\n\n if (!matches) {\n return null;\n }\n\n const url = new URL(matches[0]);\n const fn = match('/:org/:repo', { end: false });\n return fn(url.pathname);\n } catch (error) {\n return null;\n }\n};\n\nexport const dataMatcher = (\n entities: Entity[],\n projects: ProjectStatisticsSuccessResponseData[],\n) => {\n return entities.reduce(\n (\n prev: Array<\n ProjectStatisticsSuccessResponseData & {\n entity: EntityURL;\n }\n >,\n next: Entity,\n ) => {\n const entityURL = parseEntityURL(\n next?.metadata?.annotations?.['backstage.io/source-location'],\n );\n\n if (!entityURL) {\n return prev;\n }\n\n // NOTE: Find project based on GH_ prefix\n const project = projects.find(\n (item: { path: string }) =>\n item.path.match(/^GH_(.*)/)?.[1] === entityURL?.params.repo,\n );\n\n if (!project) {\n return prev;\n }\n\n const entity = {\n path: entityURL.path,\n params: entityURL.params,\n namespace: next.metadata.namespace,\n kind: 'component',\n source: 'catalog',\n };\n\n prev.push({ ...project, entity });\n\n return prev;\n },\n [],\n );\n};\n\nconst getIssueStatus = (\n engine: StatisticsEngine,\n finding:\n | CodeFindingSuccessResponseData\n | DependenciesFindingSuccessResponseData\n | ContainersFindingSuccessResponseData,\n): string => {\n if (engine === StatisticsEngine.CODE) {\n if ((finding as CodeFindingSuccessResponseData)?.suppressed)\n return 'suppressed';\n if (\n (finding as CodeFindingSuccessResponseData)?.almIssues?.jiraPlatform\n ?.issueStatus\n )\n return 'created';\n if ((finding as CodeFindingSuccessResponseData)?.reviewed)\n return 'reviewed';\n }\n\n if (engine === StatisticsEngine.DEPENDENCIES) {\n // NOTE: Available status: IGNORED and ACTIVE\n // ACTIVE means unreviewed\n // IGNORED means suppressed, comment fields are available to this status\n if (\n (finding as DependenciesFindingSuccessResponseData)?.findingInfo\n ?.status === 'IGNORED'\n )\n return 'suppressed';\n }\n\n return 'unreviewed';\n};\n\nexport const dataFindingParser = (\n code: CodeFindingSuccessResponseData[] = [],\n dependencies: DependenciesFindingSuccessResponseData[] = [],\n containers: ContainersFindingSuccessResponseData[] = [],\n) => {\n let codeFindings: Finding[] = [];\n let dependenciesFindings: Finding[] = [];\n let containersFindings: Finding[] = [];\n\n if (code.length) {\n codeFindings = code.map(finding => {\n return {\n kind: StatisticsEngine.CODE,\n level: finding.severity.toLowerCase() as StatisticsName,\n name: finding.type.cwe.title,\n origin: `${finding.sharedStep.file}:${finding.sharedStep.line}`,\n time: finding?.createdTime,\n issue: {\n issueStatus: finding.almIssues.jiraPlatform.issueStatus,\n reporter: finding.almIssues.jiraPlatform.createdByName,\n creationDate: finding.almIssues.jiraPlatform.createdTime,\n ticketName: finding.almIssues.jiraPlatform.issueKey,\n link: `${finding.almIssues.jiraPlatform.publicLink}/browse/${finding.almIssues.jiraPlatform.issueKey}`,\n status: getIssueStatus(StatisticsEngine.CODE, finding),\n },\n };\n });\n }\n\n if (dependencies.length) {\n dependenciesFindings = dependencies.map(finding => {\n return {\n kind: StatisticsEngine.DEPENDENCIES,\n level: finding.vulnerability.severity.toLowerCase() as StatisticsName,\n name: finding.vulnerability.name,\n origin: finding.component.name,\n time: finding.vulnerability.modifiedDate,\n issue: {\n issueStatus: '',\n reporter: '',\n creationDate: '',\n ticketName: '',\n link: '',\n status: getIssueStatus(StatisticsEngine.DEPENDENCIES, finding),\n },\n };\n });\n }\n\n if (containers.length) {\n containersFindings = containers.map(finding => {\n return {\n kind: StatisticsEngine.CONTAINERS,\n level: finding.severity.toLowerCase() as StatisticsName,\n name: finding.vulnerabilityId,\n origin: finding.packageName,\n time: finding.detectionDate,\n issue: {\n issueStatus: '',\n reporter: '',\n creationDate: '',\n ticketName: '',\n link: '',\n status: getIssueStatus(StatisticsEngine.CONTAINERS, finding), // NOTE: Currently, issue for finding in containers no exist.\n },\n };\n });\n }\n\n const order: { [k: string]: number } = {\n critical: 1,\n high: 2,\n medium: 3,\n low: 4,\n };\n\n return [...codeFindings, ...dependenciesFindings, ...containersFindings].sort(\n (a, b) => {\n return order[a.level] - order[b.level];\n },\n );\n};\n\nconst parseQueryString = (href = '?'): QueryParams => {\n const [, queryString] = href.split('?');\n\n const queryParams: QueryParams = {};\n new URLSearchParams(queryString).forEach((val, key) => {\n queryParams[key] = val;\n });\n\n return queryParams;\n};\n\nexport const fetchQueryPagination = async <T>(cb: Function) => {\n const defaultQueryParams = { limit: '10000', cursor: '0' };\n const collection: T[] = [];\n\n const fetchLoop = async (queryParams: PaginationQueryParams) => {\n const result = await cb({ queryParams });\n\n collection.push(...result.response);\n\n const nextQuery = result.additionalData?.paging?.next;\n\n if (nextQuery) {\n const newQueryParams = parseQueryString(nextQuery);\n await fetchLoop(newQueryParams);\n }\n };\n\n await fetchLoop(defaultQueryParams);\n\n return collection;\n};\n"],"names":["StatisticsEngine","match"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var StatisticsEngine = /* @__PURE__ */ ((StatisticsEngine2) => {
|
|
4
|
+
StatisticsEngine2["DEPENDENCIES"] = "dependencies";
|
|
5
|
+
StatisticsEngine2["CODE"] = "code";
|
|
6
|
+
StatisticsEngine2["CONTAINERS"] = "containers";
|
|
7
|
+
return StatisticsEngine2;
|
|
8
|
+
})(StatisticsEngine || {});
|
|
9
|
+
|
|
10
|
+
exports.StatisticsEngine = StatisticsEngine;
|
|
11
|
+
//# sourceMappingURL=data.service.types.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.service.types.cjs.js","sources":["../../src/service/data.service.types.ts"],"sourcesContent":["export type PaginationQueryParams = {\n cursor?: string;\n limit?: string;\n};\n\ntype PaginationSuccessResponseData = {\n additionalData: {\n totalItems: number;\n paging: {\n next?: string;\n };\n };\n};\n\ntype BodyParams = {\n projectUuids?: string[];\n applicationUuid?: string[];\n};\n\ntype PathParams = {\n uuid: string;\n};\n\nexport type GetOrganizationProjectRequestData = {\n queryParams?: PaginationQueryParams;\n};\n\nexport type OrganizationProjectSuccessResponseData = {\n uuid: string;\n name: string;\n path: string;\n applicationName: string;\n applicationUuid: string;\n};\n\nexport type GetOrganizationProjectSuccessResponseData = {\n supportToken: string;\n response: OrganizationProjectSuccessResponseData[];\n} & PaginationSuccessResponseData;\n\nexport type GetProjectStatisticsRequestData = {\n queryParams?: PaginationQueryParams;\n bodyParams?: BodyParams;\n};\n\nexport type ProjectStatisticsSuccessResponseData = {\n uuid: string;\n name: string;\n path: string;\n applicationUuid: string;\n creationDate: string;\n tags: [];\n labels: [];\n statistics: {\n UNIFIED_VULNERABILITIES: {\n unifiedCriticalVulnerabilities: number;\n unifiedHighVulnerabilities: number;\n unifiedMediumVulnerabilities: number;\n unifiedLowVulnerabilities: number;\n unifiedVulnerabilities: number;\n };\n VULNERABILITY_EFFECTIVENESS: {};\n LIBRARY_TYPE_HISTOGRAM: Record<string, number>;\n IMG_USAGE: {};\n POLICY_VIOLATION_LIBRARIES: {\n policyViolatingLibraries: number;\n };\n SAST_VULNERABILITIES_BY_TYPE: Record<string, number>;\n GENERAL: {\n totalLibraries: number;\n };\n LLM_SECURITY: {\n llmTotalLines: number;\n };\n IMG_SECURITY: {\n imgCriticalVulnerabilities: number;\n imgMaxRiskScore: number;\n imgMediumVulnerabilities: number;\n imgLowVulnerabilities: number;\n imgSecretMediumVulnerabilities: number;\n imgUnknownVulnerabilities: number;\n imgSecretHighVulnerabilities: number;\n imgTotalVulnerabilities: number;\n imgHighVulnerabilities: number;\n imgSecretCriticalVulnerabilities: number;\n imgSecretLowVulnerabilities: number;\n };\n ALERTS: {\n criticalSeverityVulnerabilities: number;\n highSeverityVulnerabilities: number;\n vulnerableLibraries: number;\n mediumSeverityVulnerabilities: number;\n lowSeverityVulnerabilities: number;\n };\n OUTDATED_LIBRARIES: {\n outdatedLibraries: number;\n };\n POLICY_VIOLATIONS: {};\n SAST_SCAN: {\n sastTotalLines: number;\n sastTestedFiles: number;\n sastTotalFiles: number;\n sastTestedLines: number;\n sastTotalMended: number;\n sastTotalRemediations: number;\n };\n VULNERABILITY_SEVERITY_LIBRARIES: {\n lowSeverityLibraries: number;\n highSeverityLibraries: number;\n mediumSeverityLibraries: number;\n criticalSeverityLibraries: number;\n };\n LICENSE_RISK: {\n highRiskLicenses: number;\n mediumRiskLicenses: number;\n lowRiskLicenses: number;\n };\n IAC_SECURITY: {\n iacCriticalMisconfigurations: number;\n iacHighMisconfigurations: number;\n iacTotalMisconfigurations: number;\n iacLowMisconfigurations: number;\n iacMediumMisconfigurations: number;\n };\n SCA_SECURITY: {};\n LICENSE_HISTOGRAM: Record<string, number>;\n SAST_VULNERABILITIES_BY_SEVERITY: {\n sastVulnerabilities: number;\n sastHighVulnerabilities: number;\n sastMediumVulnerabilities: number;\n sastLowVulnerabilities: number;\n };\n LAST_SCAN: {\n lastScanTime: number;\n lastScaScanTime: number;\n lastImgScanTime: number;\n lastSastScanTime: number;\n };\n };\n};\n\nexport type GetProjectStatisticsSuccessResponseData = {\n supportToken: string;\n response: ProjectStatisticsSuccessResponseData[];\n} & PaginationSuccessResponseData;\n\nexport type EntityURL = {\n path: string;\n params: {\n org?: string;\n repo?: string;\n };\n namespace?: string;\n kind: string;\n source: string;\n};\n\nexport enum StatisticsName {\n CRITICAL = 'critical',\n HIGH = 'high',\n MEDIUM = 'medium',\n LOW = 'low',\n TOTAL = 'total',\n}\n\nexport enum StatisticsEngine {\n DEPENDENCIES = 'dependencies',\n CODE = 'code',\n CONTAINERS = 'containers',\n}\n\ntype StatisticsBase = {\n [StatisticsName.CRITICAL]: number;\n [StatisticsName.HIGH]: number;\n [StatisticsName.MEDIUM]: number;\n [StatisticsName.LOW]: number;\n [StatisticsName.TOTAL]: number;\n};\n\nexport type Statistics = {\n [StatisticsEngine.DEPENDENCIES]: StatisticsBase;\n [StatisticsEngine.CODE]: Omit<StatisticsBase, StatisticsName.CRITICAL> & {\n [StatisticsName.CRITICAL]: null;\n };\n [StatisticsEngine.CONTAINERS]: StatisticsBase;\n} & StatisticsBase;\n\nexport type Project = {\n statistics: Statistics;\n uuid: string;\n name: string;\n path: string;\n applicationName: string;\n applicationUuid: string;\n lastScan: number;\n languages: Array<[string, number]>;\n entity: EntityURL;\n};\n\n// Code Finding API Data\ntype CodeFindingDataFlowSuccessResponseData = {\n id: string;\n sink: string;\n sinkKind: string;\n sinkFile: string;\n sinkSnippet: string;\n sinkLine: number;\n inputSource: string;\n inputKind: string;\n inputFlow: [\n {\n name: string;\n kind: string;\n file: string;\n snippet: string;\n line: number;\n startLine: number;\n endLine: number;\n },\n ];\n functionCalls: [\n {\n name: string;\n kind: string;\n file: string;\n snippet: string;\n line: number;\n startLine: number;\n endLine: number;\n },\n ];\n filter: {\n isFiltered: boolean;\n filterTypes: unknown[];\n };\n isNew: boolean;\n rating: number;\n confidenceRating: number;\n ageRating: number;\n};\n\nexport type CodeFindingSuccessResponseData = {\n id: string;\n scanId: string;\n snapshotId: string;\n projectId: string;\n appId: string;\n type: {\n id: number;\n name: string;\n engineId: number;\n language: string;\n sarif: string;\n sarifLevel: string;\n order: number;\n severity: StatisticsName;\n severityRating: number;\n description: string;\n recommendations: [string];\n references: [string];\n cwe: {\n id: string;\n title: string;\n url: string;\n };\n pcidss: {\n section: string;\n title: string;\n };\n nist: {\n control: string;\n priority: string;\n title: string;\n url: string;\n };\n hipaa: {\n control: string;\n title: string;\n };\n hitrust: {\n control: string;\n title: string;\n };\n owasp: {\n index: string;\n title: string;\n url: string;\n };\n owasp2021: {\n index: string;\n title: string;\n url: string;\n };\n capec: {\n id: string;\n title: string;\n url: string;\n };\n sansTop25: {\n rank: number;\n title: string;\n };\n };\n description: string;\n createdTime: string;\n isNew: boolean;\n severity: StatisticsName;\n baseline: boolean;\n hasRemediation: boolean;\n suppressed: boolean;\n suppressedBy: string;\n suppressionTime: string;\n suppressionMessage: string;\n reviewed: boolean;\n IssueStatus: number;\n sharedStep: {\n name: string;\n kind: string;\n file: string;\n snippet: string;\n line: number;\n startLine: number;\n endLine: number;\n lineBlame: {\n commitId: string;\n file: string;\n line: number;\n };\n };\n dataFlows: CodeFindingDataFlowSuccessResponseData[];\n severityRating: number;\n confidenceRating: number;\n ageRating: number;\n rating: number;\n almIssues: {\n jira: {\n issueId: string;\n project: string;\n };\n azure: {\n workItemId: number;\n project: string;\n };\n jiraPlatform: {\n internalStatus: string;\n issueStatus: string;\n issueKey: string;\n publicLink: string;\n createdTime: string;\n createdBy: string;\n createdByName: string;\n };\n };\n comments: unknown[];\n};\n\nexport type GetCodeFindingSuccessResponseData = {\n response: CodeFindingSuccessResponseData[];\n supportToken: string;\n} & PaginationSuccessResponseData;\n\nexport type GetCodeFindingsRequestData = {\n queryParams?: PaginationQueryParams;\n pathParams: PathParams;\n};\n\n// Dependencies Finding API Data\nexport type DependenciesFindingSuccessResponseData = {\n uuid: string;\n name: string;\n type: string;\n component: {\n uuid: string;\n name: string;\n description: string;\n componentType: string;\n libraryType: string;\n rootLibrary: boolean;\n references: {\n url: string;\n homePage: string;\n genericPackageIndex: string;\n };\n groupId: string;\n artifactId: string;\n version: string;\n path: string;\n };\n findingInfo: {\n status: string;\n comment: unknown;\n detectedAt: string;\n modifiedAt: string;\n };\n project: {\n uuid: string;\n name: string;\n path: string;\n applicationUuid: string;\n };\n application: {\n uuid: string;\n name: string;\n };\n vulnerability: {\n name: string;\n type: string;\n description: string;\n score: number;\n severity: StatisticsName;\n publishDate: string;\n modifiedDate: string;\n vulnerabilityScoring: {\n score: number;\n severity: string;\n type: string;\n }[];\n };\n topFix: {\n id: number;\n vulnerability: string;\n type: string;\n origin: string;\n url: string;\n fixResolution: string;\n date: string;\n message: string;\n };\n effective: string;\n threatAssessment: {\n exploitCodeMaturity: string;\n epssPercentage: number;\n };\n exploitable: boolean;\n scoreMetadataVector: string;\n};\n\nexport type GetDependenciesFindingSuccessResponseData = {\n supportToken: string;\n response: DependenciesFindingSuccessResponseData[];\n} & PaginationSuccessResponseData;\n\nexport type GetDependenciesFindingsRequestData = {\n queryParams?: PaginationQueryParams;\n pathParams: PathParams;\n};\n\n// Containers Finding API Data\nexport type ContainersFindingSuccessResponseData = {\n uuid: string;\n vulnerabilityId: string;\n description: string;\n projectUuid: string;\n imageName: string;\n packageName: string;\n packageVersion: string;\n severity: StatisticsName;\n cvss: number;\n epss: number;\n hasFix: false;\n fixVersion: string;\n publishedDate: string;\n detectionDate: string;\n};\n\nexport type GetContainersFindingSuccessResponseData = {\n supportToken: string;\n response: ContainersFindingSuccessResponseData[];\n} & PaginationSuccessResponseData;\n\nexport type GetContainersFindingsRequestData = {\n queryParams?: PaginationQueryParams;\n pathParams: PathParams;\n};\n\nexport type Finding = {\n kind: StatisticsEngine;\n level: StatisticsName;\n name: string;\n origin: string;\n time: string;\n issue: {\n issueStatus: string;\n reporter: string;\n creationDate: string;\n ticketName: string;\n link: string;\n status: string;\n };\n};\n"],"names":["StatisticsEngine"],"mappings":";;AAqKY,IAAA,gBAAA,qBAAAA,iBAAL,KAAA;AACL,EAAAA,kBAAA,cAAe,CAAA,GAAA,cAAA;AACf,EAAAA,kBAAA,MAAO,CAAA,GAAA,MAAA;AACP,EAAAA,kBAAA,YAAa,CAAA,GAAA,YAAA;AAHH,EAAAA,OAAAA,iBAAAA;AAAA,CAAA,EAAA,gBAAA,IAAA,EAAA;;;;"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var express = require('express');
|
|
4
|
+
var Router = require('express-promise-router');
|
|
5
|
+
var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
|
|
6
|
+
var catalogClient = require('@backstage/catalog-client');
|
|
7
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
8
|
+
var data_service_helpers = require('./data.service.helpers.cjs.js');
|
|
9
|
+
var data_service = require('./data.service.cjs.js');
|
|
10
|
+
var auth_service = require('./auth.service.cjs.js');
|
|
11
|
+
var permissions = require('../permission/permissions.cjs.js');
|
|
12
|
+
var conditions = require('../permission/conditions.cjs.js');
|
|
13
|
+
require('../permission/rules.cjs.js');
|
|
14
|
+
|
|
15
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
16
|
+
|
|
17
|
+
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
18
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
19
|
+
|
|
20
|
+
async function createRouter(options) {
|
|
21
|
+
const { logger, config, discovery, auth, httpAuth, permissions: permissions$1 } = options;
|
|
22
|
+
const router = Router__default.default();
|
|
23
|
+
router.use(express__default.default.json());
|
|
24
|
+
router.use(conditions.permissionIntegrationRouter);
|
|
25
|
+
const checkForAuth = (_request, response, next) => {
|
|
26
|
+
if (auth_service.MendAuthSevice.getAuthToken()) {
|
|
27
|
+
next();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
auth_service.MendAuthSevice.connect().then(next).catch(() => {
|
|
31
|
+
response.status(401).json({ error: "Oops! Unauthorized" });
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
const baseUrl = config.getString("mend.baseUrl");
|
|
35
|
+
const activationKey = config.getString("mend.activationKey");
|
|
36
|
+
const mendDataService = new data_service.MendDataService({
|
|
37
|
+
baseUrl,
|
|
38
|
+
activationKey
|
|
39
|
+
});
|
|
40
|
+
const catalogClient$1 = new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
41
|
+
router.get("/project" /* PROJECT */, checkForAuth, async (request, response) => {
|
|
42
|
+
try {
|
|
43
|
+
const credentials = await httpAuth.credentials(request);
|
|
44
|
+
const { token } = await auth.getPluginRequestToken({
|
|
45
|
+
onBehalfOf: credentials,
|
|
46
|
+
targetPluginId: "plugin.catalog.service"
|
|
47
|
+
});
|
|
48
|
+
const results = await Promise.all([
|
|
49
|
+
catalogClient$1.getEntities(
|
|
50
|
+
{ filter: [{ kind: ["Component"] }] },
|
|
51
|
+
{ token }
|
|
52
|
+
),
|
|
53
|
+
data_service_helpers.fetchQueryPagination(
|
|
54
|
+
mendDataService.getProjectStatistics
|
|
55
|
+
),
|
|
56
|
+
data_service_helpers.fetchQueryPagination(
|
|
57
|
+
mendDataService.getOrganizationProject
|
|
58
|
+
)
|
|
59
|
+
]);
|
|
60
|
+
const decision = (await permissions$1.authorizeConditional(
|
|
61
|
+
[{ permission: permissions.mendReadPermission }],
|
|
62
|
+
{
|
|
63
|
+
credentials
|
|
64
|
+
}
|
|
65
|
+
))[0];
|
|
66
|
+
let items;
|
|
67
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
68
|
+
const filter = conditions.transformConditions(decision.conditions);
|
|
69
|
+
items = results[1].filter(
|
|
70
|
+
(item) => filter?.exclude ? !filter.ids.includes(item.uuid) : filter.ids.includes(item.uuid)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const data = data_service_helpers.dataMatcher(results[0].items, items || results[1]);
|
|
74
|
+
const projects = data_service_helpers.dataProjectParser(data, results[2]);
|
|
75
|
+
response.json({
|
|
76
|
+
...projects,
|
|
77
|
+
clientUrl: auth_service.MendAuthSevice.getClientUrl(),
|
|
78
|
+
clientName: auth_service.MendAuthSevice.getClientName()
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
logger.error("/project", error);
|
|
82
|
+
response.status(500).json({ error: "Oops! Please try again later." });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
router.post("/finding" /* FINDING */, checkForAuth, async (request, response) => {
|
|
86
|
+
try {
|
|
87
|
+
const credentials = await httpAuth.credentials(request);
|
|
88
|
+
const { token } = await auth.getPluginRequestToken({
|
|
89
|
+
onBehalfOf: credentials,
|
|
90
|
+
targetPluginId: "plugin.catalog.service"
|
|
91
|
+
});
|
|
92
|
+
const uid = request.body.uid;
|
|
93
|
+
if (!uid) {
|
|
94
|
+
response.status(401).json({ error: "Oops! No UUID provided" });
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const projectResult = await Promise.all([
|
|
98
|
+
catalogClient$1.getEntities(
|
|
99
|
+
{ filter: [{ "metadata.uid": uid }] },
|
|
100
|
+
{ token }
|
|
101
|
+
),
|
|
102
|
+
data_service_helpers.fetchQueryPagination(
|
|
103
|
+
mendDataService.getProjectStatistics
|
|
104
|
+
),
|
|
105
|
+
data_service_helpers.fetchQueryPagination(
|
|
106
|
+
mendDataService.getOrganizationProject
|
|
107
|
+
)
|
|
108
|
+
]);
|
|
109
|
+
const decision = (await permissions$1.authorizeConditional(
|
|
110
|
+
[{ permission: permissions.mendReadPermission }],
|
|
111
|
+
{
|
|
112
|
+
credentials
|
|
113
|
+
}
|
|
114
|
+
))[0];
|
|
115
|
+
let items;
|
|
116
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
117
|
+
const filter = conditions.transformConditions(decision.conditions);
|
|
118
|
+
items = projectResult[1].filter(
|
|
119
|
+
(item) => filter?.exclude ? !filter.ids.includes(item.uuid) : filter.ids.includes(item.uuid)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const data = data_service_helpers.dataMatcher(
|
|
123
|
+
projectResult[0].items,
|
|
124
|
+
items || projectResult[1]
|
|
125
|
+
);
|
|
126
|
+
if (!data.length) {
|
|
127
|
+
response.json({
|
|
128
|
+
findingList: [],
|
|
129
|
+
projectName: "",
|
|
130
|
+
projectUuid: "",
|
|
131
|
+
clientUrl: auth_service.MendAuthSevice.getClientUrl(),
|
|
132
|
+
clientName: auth_service.MendAuthSevice.getClientName()
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const params = {
|
|
137
|
+
pathParams: {
|
|
138
|
+
uuid: data[0].uuid
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const findingResult = await Promise.all([
|
|
142
|
+
data_service_helpers.fetchQueryPagination(
|
|
143
|
+
(queryParam) => mendDataService.getCodeFinding({
|
|
144
|
+
...params,
|
|
145
|
+
...queryParam
|
|
146
|
+
})
|
|
147
|
+
),
|
|
148
|
+
data_service_helpers.fetchQueryPagination(
|
|
149
|
+
(queryParam) => mendDataService.getDependenciesFinding({
|
|
150
|
+
...params,
|
|
151
|
+
...queryParam
|
|
152
|
+
})
|
|
153
|
+
),
|
|
154
|
+
data_service_helpers.fetchQueryPagination(
|
|
155
|
+
(queryParam) => mendDataService.getContainersFinding({
|
|
156
|
+
...params,
|
|
157
|
+
...queryParam
|
|
158
|
+
})
|
|
159
|
+
)
|
|
160
|
+
]);
|
|
161
|
+
const project = data_service_helpers.dataProjectParser(data, projectResult[2]);
|
|
162
|
+
const findingList = data_service_helpers.dataFindingParser(
|
|
163
|
+
findingResult[0].filter((item) => !item.suppressed),
|
|
164
|
+
// NOTE: Do not show suppressed item
|
|
165
|
+
findingResult[1].filter(
|
|
166
|
+
(item) => !(item.findingInfo.status === "IGNORED")
|
|
167
|
+
),
|
|
168
|
+
// NOTE: Do not show ignored item
|
|
169
|
+
findingResult[2]
|
|
170
|
+
// ESC-51: Follow Jira activity
|
|
171
|
+
);
|
|
172
|
+
response.json({
|
|
173
|
+
findingList,
|
|
174
|
+
projectName: project.projectList[0].entity.params.repo,
|
|
175
|
+
projectUuid: project.projectList[0].uuid,
|
|
176
|
+
clientUrl: auth_service.MendAuthSevice.getClientUrl(),
|
|
177
|
+
clientName: auth_service.MendAuthSevice.getClientName()
|
|
178
|
+
});
|
|
179
|
+
} catch (error) {
|
|
180
|
+
logger.error("/finding", error);
|
|
181
|
+
response.status(500).json({ error: "Oops! Please try again later." });
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
router.get("/health", (_, response) => {
|
|
185
|
+
logger.info("PONG!");
|
|
186
|
+
response.json({ status: "ok" });
|
|
187
|
+
});
|
|
188
|
+
const middleware = rootHttpRouter.MiddlewareFactory.create({ logger, config });
|
|
189
|
+
router.use(middleware.error());
|
|
190
|
+
return router;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
exports.createRouter = createRouter;
|
|
194
|
+
//# sourceMappingURL=router.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport {\n LoggerService,\n DiscoveryService,\n AuthService,\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\nimport {\n dataFindingParser,\n dataMatcher,\n dataProjectParser,\n fetchQueryPagination,\n} from './data.service.helpers';\nimport { MendDataService } from './data.service';\nimport { MendAuthSevice } from './auth.service';\nimport {\n PaginationQueryParams,\n ProjectStatisticsSuccessResponseData,\n OrganizationProjectSuccessResponseData,\n CodeFindingSuccessResponseData,\n DependenciesFindingSuccessResponseData,\n ContainersFindingSuccessResponseData,\n} from './data.service.types';\nimport {\n mendReadPermission,\n transformConditions,\n permissionIntegrationRouter,\n type FilterProps,\n} from '../permission';\n\n/** @internal */\nexport type RouterOptions = {\n logger: LoggerService;\n config: Config;\n discovery: DiscoveryService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n};\n\nenum ROUTE {\n PROJECT = '/project',\n FINDING = '/finding',\n}\n\n/** @internal */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, discovery, auth, httpAuth, permissions } = options;\n\n const router = Router();\n router.use(express.json());\n\n router.use(permissionIntegrationRouter);\n\n const checkForAuth = (\n _request: express.Request,\n response: express.Response,\n next: express.NextFunction,\n ) => {\n if (MendAuthSevice.getAuthToken()) {\n next();\n return;\n }\n\n MendAuthSevice.connect()\n .then(next)\n .catch(() => {\n response.status(401).json({ error: 'Oops! Unauthorized' });\n });\n };\n\n const baseUrl = config.getString('mend.baseUrl');\n const activationKey = config.getString('mend.activationKey');\n\n // Init api service\n const mendDataService = new MendDataService({\n baseUrl,\n activationKey,\n });\n\n // Init catalog client\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n // Routes\n router.get(ROUTE.PROJECT, checkForAuth, async (request, response) => {\n try {\n // service to service auth\n const credentials = await httpAuth.credentials(request);\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'plugin.catalog.service',\n });\n\n // entity to project match\n const results = await Promise.all([\n catalogClient.getEntities(\n { filter: [{ kind: ['Component'] }] },\n { token },\n ),\n fetchQueryPagination<ProjectStatisticsSuccessResponseData>(\n mendDataService.getProjectStatistics,\n ),\n fetchQueryPagination<OrganizationProjectSuccessResponseData>(\n mendDataService.getOrganizationProject,\n ),\n ]);\n\n // permission - filter to exclude or include project\n const decision = (\n await permissions.authorizeConditional(\n [{ permission: mendReadPermission }],\n {\n credentials,\n },\n )\n )[0];\n\n let items;\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n const filter = transformConditions(decision.conditions) as FilterProps;\n items = results[1].filter(item =>\n filter?.exclude\n ? !filter.ids.includes(item.uuid)\n : filter.ids.includes(item.uuid),\n );\n }\n\n const data = dataMatcher(results[0].items, items || results[1]);\n\n // parse data\n const projects = dataProjectParser(data, results[2]);\n\n response.json({\n ...projects,\n clientUrl: MendAuthSevice.getClientUrl(),\n clientName: MendAuthSevice.getClientName(),\n });\n // Allow any object structure here\n } catch (error: any) {\n logger.error('/project', error);\n response.status(500).json({ error: 'Oops! Please try again later.' });\n }\n });\n\n router.post(ROUTE.FINDING, checkForAuth, async (request, response) => {\n try {\n // service to service auth\n const credentials = await httpAuth.credentials(request);\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'plugin.catalog.service',\n });\n\n // entity to project match\n const uid = request.body.uid;\n\n if (!uid) {\n response.status(401).json({ error: 'Oops! No UUID provided' });\n return;\n }\n\n const projectResult = await Promise.all([\n catalogClient.getEntities(\n { filter: [{ 'metadata.uid': uid }] },\n { token },\n ),\n fetchQueryPagination<ProjectStatisticsSuccessResponseData>(\n mendDataService.getProjectStatistics,\n ),\n fetchQueryPagination<OrganizationProjectSuccessResponseData>(\n mendDataService.getOrganizationProject,\n ),\n ]);\n\n // permission - filter to exclude or include project\n const decision = (\n await permissions.authorizeConditional(\n [{ permission: mendReadPermission }],\n {\n credentials,\n },\n )\n )[0];\n\n let items;\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n const filter = transformConditions(decision.conditions) as FilterProps;\n items = projectResult[1].filter(item =>\n filter?.exclude\n ? !filter.ids.includes(item.uuid)\n : filter.ids.includes(item.uuid),\n );\n }\n\n const data = dataMatcher(\n projectResult[0].items,\n items || projectResult[1],\n );\n\n if (!data.length) {\n response.json({\n findingList: [],\n projectName: '',\n projectUuid: '',\n clientUrl: MendAuthSevice.getClientUrl(),\n clientName: MendAuthSevice.getClientName(),\n });\n return;\n }\n\n const params = {\n pathParams: {\n uuid: data[0].uuid,\n },\n };\n\n // get project findings\n const findingResult = await Promise.all([\n fetchQueryPagination<CodeFindingSuccessResponseData>(\n (queryParam: PaginationQueryParams) =>\n mendDataService.getCodeFinding({\n ...params,\n ...queryParam,\n }),\n ),\n fetchQueryPagination<DependenciesFindingSuccessResponseData>(\n (queryParam: PaginationQueryParams) =>\n mendDataService.getDependenciesFinding({\n ...params,\n ...queryParam,\n }),\n ),\n fetchQueryPagination<ContainersFindingSuccessResponseData>(\n (queryParam: PaginationQueryParams) =>\n mendDataService.getContainersFinding({\n ...params,\n ...queryParam,\n }),\n ),\n ]);\n\n const project = dataProjectParser(data, projectResult[2]);\n const findingList = dataFindingParser(\n findingResult[0].filter(item => !item.suppressed), // NOTE: Do not show suppressed item\n findingResult[1].filter(\n item => !(item.findingInfo.status === 'IGNORED'),\n ), // NOTE: Do not show ignored item\n findingResult[2], // ESC-51: Follow Jira activity\n );\n\n response.json({\n findingList,\n projectName: project.projectList[0].entity.params.repo,\n projectUuid: project.projectList[0].uuid,\n clientUrl: MendAuthSevice.getClientUrl(),\n clientName: MendAuthSevice.getClientName(),\n });\n // Allow any object structure here\n } catch (error: any) {\n logger.error('/finding', error);\n response.status(500).json({ error: 'Oops! Please try again later.' });\n }\n });\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["permissions","Router","express","permissionIntegrationRouter","MendAuthSevice","MendDataService","catalogClient","CatalogClient","fetchQueryPagination","mendReadPermission","AuthorizeResult","transformConditions","dataMatcher","dataProjectParser","dataFindingParser","MiddlewareFactory"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-mend-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"postpack": "backstage-cli package postpack"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@backstage/backend-defaults": "^0.
|
|
38
|
-
"@backstage/backend-plugin-api": "^
|
|
39
|
-
"@backstage/catalog-client": "^1.
|
|
40
|
-
"@backstage/catalog-model": "^1.
|
|
41
|
-
"@backstage/config": "^1.2
|
|
42
|
-
"@backstage/plugin-permission-common": "^0.8.
|
|
43
|
-
"@backstage/plugin-permission-node": "^0.8.
|
|
37
|
+
"@backstage/backend-defaults": "^0.7.0",
|
|
38
|
+
"@backstage/backend-plugin-api": "^1.1.1",
|
|
39
|
+
"@backstage/catalog-client": "^1.9.1",
|
|
40
|
+
"@backstage/catalog-model": "^1.7.3",
|
|
41
|
+
"@backstage/config": "^1.3.2",
|
|
42
|
+
"@backstage/plugin-permission-common": "^0.8.4",
|
|
43
|
+
"@backstage/plugin-permission-node": "^0.8.7",
|
|
44
44
|
"@types/express": "*",
|
|
45
45
|
"express": "^4.17.1",
|
|
46
46
|
"express-promise-router": "^4.1.0",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"zod": "^3.23.8"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@backstage/backend-test-utils": "^
|
|
56
|
-
"@backstage/cli": "^0.
|
|
57
|
-
"@backstage/plugin-auth-backend": "^0.
|
|
58
|
-
"@backstage/plugin-auth-backend-module-guest-provider": "^0.
|
|
55
|
+
"@backstage/backend-test-utils": "^1.2.1",
|
|
56
|
+
"@backstage/cli": "^0.29.6",
|
|
57
|
+
"@backstage/plugin-auth-backend": "^0.24.2",
|
|
58
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.4",
|
|
59
59
|
"@types/supertest": "^2.0.12",
|
|
60
60
|
"msw": "^1.0.0",
|
|
61
61
|
"supertest": "^6.2.4"
|
|
@@ -63,5 +63,12 @@
|
|
|
63
63
|
"files": [
|
|
64
64
|
"dist",
|
|
65
65
|
"config.d.ts"
|
|
66
|
-
]
|
|
66
|
+
],
|
|
67
|
+
"typesVersions": {
|
|
68
|
+
"*": {
|
|
69
|
+
"index": [
|
|
70
|
+
"dist/index.d.ts"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
67
74
|
}
|