@secureport/sdk 0.5.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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/client.d.ts +135 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +191 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +80 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +118 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pagination.d.ts +27 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +19 -0
- package/dist/pagination.js.map +1 -0
- package/dist/resources/branding.d.ts +49 -0
- package/dist/resources/branding.d.ts.map +1 -0
- package/dist/resources/branding.js +38 -0
- package/dist/resources/branding.js.map +1 -0
- package/dist/resources/issues.d.ts +248 -0
- package/dist/resources/issues.d.ts.map +1 -0
- package/dist/resources/issues.js +100 -0
- package/dist/resources/issues.js.map +1 -0
- package/dist/resources/reports.d.ts +83 -0
- package/dist/resources/reports.d.ts.map +1 -0
- package/dist/resources/reports.js +50 -0
- package/dist/resources/reports.js.map +1 -0
- package/dist/resources/runs.d.ts +474 -0
- package/dist/resources/runs.d.ts.map +1 -0
- package/dist/resources/runs.js +281 -0
- package/dist/resources/runs.js.map +1 -0
- package/dist/resources/suppression-rules.d.ts +43 -0
- package/dist/resources/suppression-rules.d.ts.map +1 -0
- package/dist/resources/suppression-rules.js +33 -0
- package/dist/resources/suppression-rules.js.map +1 -0
- package/dist/resources/targets.d.ts +126 -0
- package/dist/resources/targets.d.ts.map +1 -0
- package/dist/resources/targets.js +83 -0
- package/dist/resources/targets.js.map +1 -0
- package/package.json +55 -0
- package/src/client.ts +328 -0
- package/src/errors.ts +120 -0
- package/src/index.ts +100 -0
- package/src/pagination.ts +41 -0
- package/src/resources/branding.ts +59 -0
- package/src/resources/issues.ts +344 -0
- package/src/resources/reports.ts +104 -0
- package/src/resources/runs.ts +635 -0
- package/src/resources/suppression-rules.ts +69 -0
- package/src/resources/targets.ts +179 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/resources/reports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEtE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAEnC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;IAElC;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAEnC,8BAA8B;IAC9B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CAChD;AAID;;;;;;;GAOG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,YAAY;IAErD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;CAahE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const MACHINE_FORMATS = new Set(['json', 'markdown', 'csv', 'sarif']);
|
|
2
|
+
/**
|
|
3
|
+
* Reports — the one resource whose response is never JSON. Every format
|
|
4
|
+
* `request` accepts is a raw, streamed body (`text/csv`,
|
|
5
|
+
* `application/sarif+json`, plain `application/json` text, …), so this
|
|
6
|
+
* resource is built on {@link SecureportClient.requestRaw} rather than the
|
|
7
|
+
* usual `request<T>()`, and hands the `Response` itself back to the caller
|
|
8
|
+
* to read as text, parse, or stream to a file.
|
|
9
|
+
*/
|
|
10
|
+
export class ReportsResource {
|
|
11
|
+
requestRaw;
|
|
12
|
+
constructor(requestRaw) {
|
|
13
|
+
this.requestRaw = requestRaw;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders a run into a report and streams it back. **Nothing is stored on
|
|
17
|
+
* the API side** — the bytes are produced from the run's snapshot on
|
|
18
|
+
* demand and exist only in this response; call this again for the same
|
|
19
|
+
* run and it renders again from whatever the run's snapshot is by then.
|
|
20
|
+
*
|
|
21
|
+
* **A failure partway through the stream cannot become an HTTP status.**
|
|
22
|
+
* The status and headers this method's `Response` carries are whatever was
|
|
23
|
+
* sent before the first byte of the body; nothing that goes wrong later in
|
|
24
|
+
* the stream can change them, so a truncated document looks identical to a
|
|
25
|
+
* complete one at this layer. Verify the body's own shape — that a JSON or
|
|
26
|
+
* SARIF document parses, that a CSV has the trailer row it expects — if a
|
|
27
|
+
* caller needs to be sure nothing was cut short.
|
|
28
|
+
*
|
|
29
|
+
* @throws {Error} synchronously, before any request is made, if
|
|
30
|
+
* `input.format` is `'pdf'` or `'html'` — this method exists only for
|
|
31
|
+
* `'json' | 'csv' | 'sarif' | 'markdown'`; a caller bypassing the type
|
|
32
|
+
* (plain JS, no type checker) is told so without spending a round trip.
|
|
33
|
+
* @throws {SecureportError} `conflict` if the run has not been reconciled
|
|
34
|
+
* — still running, or ended `failed`; `forbidden` should be unreachable
|
|
35
|
+
* given the format check above, but is still what the API itself would
|
|
36
|
+
* answer for `pdf`/`html`.
|
|
37
|
+
*/
|
|
38
|
+
request(runId, input) {
|
|
39
|
+
if (!MACHINE_FORMATS.has(input.format)) {
|
|
40
|
+
throw new Error(`'${input.format}' reports are requested from the dashboard by a signed-in user — an ` +
|
|
41
|
+
'API key can export json, csv, sarif or markdown.');
|
|
42
|
+
}
|
|
43
|
+
return this.requestRaw({
|
|
44
|
+
method: 'POST',
|
|
45
|
+
path: `/runs/${encodeURIComponent(runId)}/reports`,
|
|
46
|
+
body: input,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reports.js","sourceRoot":"","sources":["../../src/resources/reports.ts"],"names":[],"mappings":"AAsDA,MAAM,eAAe,GAAG,IAAI,GAAG,CAAe,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpF;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,UAAwB;QAAxB,eAAU,GAAV,UAAU,CAAc;IAAG,CAAC;IAEzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,KAAa,EAAE,KAAoB;QACzC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,IAAI,KAAK,CAAC,MAAM,sEAAsE;gBACpF,kDAAkD,CACrD,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;YACrB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS,kBAAkB,CAAC,KAAK,CAAC,UAAU;YAClD,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import type { Snapshot } from '@secureport/core';
|
|
2
|
+
import type { FetchBody, Requester } from '../client.js';
|
|
3
|
+
import type { Severity } from './issues.js';
|
|
4
|
+
import type { Page, PageQuery } from '../pagination.js';
|
|
5
|
+
/**
|
|
6
|
+
* What kind of run this was — `scan` (Secureport originated the traffic,
|
|
7
|
+
* subject to `POST /runs`'s terms/verification gate), `upload` (results
|
|
8
|
+
* brought from elsewhere) or `manual` (a human recorded a finding directly).
|
|
9
|
+
* Mirrors `@secureport/core`'s `RunKind`; SDK-local for the same reason as
|
|
10
|
+
* `Issue`/`Finding` — see the module doc in `issues.ts`.
|
|
11
|
+
*/
|
|
12
|
+
export type RunKind = 'scan' | 'upload' | 'manual';
|
|
13
|
+
/** What set the run going. Never defaulted — see {@link NewRun.trigger}. */
|
|
14
|
+
export type RunTrigger = 'github_action' | 'cli' | 'api' | 'scheduled' | 'web';
|
|
15
|
+
/**
|
|
16
|
+
* Where a run is in its lifecycle. `failed` and `cancelled` are both terminal
|
|
17
|
+
* and neither reconciles — see {@link RunsResource.cancel} for the difference.
|
|
18
|
+
*/
|
|
19
|
+
export type RunStatus = 'running' | 'finished' | 'failed' | 'cancelled';
|
|
20
|
+
/**
|
|
21
|
+
* How much a scan does — the S/M/L/XL catalogue, smallest to largest, each
|
|
22
|
+
* size a strict superset of the one below. Mirrors `@secureport/core`.
|
|
23
|
+
*/
|
|
24
|
+
export type ScanSize = 's' | 'm' | 'l' | 'xl';
|
|
25
|
+
/** What a run actually exercised. */
|
|
26
|
+
export interface Coverage {
|
|
27
|
+
/** Location patterns the run covered, as globs, e.g. `https://app.example.com/**`. */
|
|
28
|
+
readonly paths: readonly string[];
|
|
29
|
+
/** Ports exercised, where the run was port-aware. */
|
|
30
|
+
readonly ports?: readonly number[];
|
|
31
|
+
/**
|
|
32
|
+
* Severity classes whose checks the run exercised; absent means not
|
|
33
|
+
* severity-scoped. A scoped run cannot resolve issues outside its classes.
|
|
34
|
+
*/
|
|
35
|
+
readonly severities?: readonly Severity[];
|
|
36
|
+
/** Engines that took part. */
|
|
37
|
+
readonly engines: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One execution against a target.
|
|
41
|
+
*
|
|
42
|
+
* Date fields are ISO 8601 strings, as the API sends them — see
|
|
43
|
+
* {@link RunsResource.snapshot} for the one method in this resource that
|
|
44
|
+
* returns real `Date`s instead.
|
|
45
|
+
*/
|
|
46
|
+
export interface Run {
|
|
47
|
+
readonly id: string;
|
|
48
|
+
readonly orgId: string;
|
|
49
|
+
readonly targetId: string;
|
|
50
|
+
readonly kind: RunKind;
|
|
51
|
+
readonly trigger: RunTrigger;
|
|
52
|
+
readonly status: RunStatus;
|
|
53
|
+
/** How much this run does. Present exactly when `kind` is `'scan'`. */
|
|
54
|
+
readonly size?: ScanSize;
|
|
55
|
+
readonly coverage: Coverage;
|
|
56
|
+
/** The verification evidence a `kind: 'scan'` run was authorised against. */
|
|
57
|
+
readonly verificationId?: string;
|
|
58
|
+
readonly startedAt: string;
|
|
59
|
+
readonly finishedAt?: string;
|
|
60
|
+
}
|
|
61
|
+
export type RunPage = Page<Run>;
|
|
62
|
+
/** The filters `list`/`listAll` take, beside the page. Both optional and combinable. */
|
|
63
|
+
export interface RunFilters {
|
|
64
|
+
readonly targetId?: string;
|
|
65
|
+
readonly status?: RunStatus;
|
|
66
|
+
}
|
|
67
|
+
export interface NewRun {
|
|
68
|
+
readonly targetId: string;
|
|
69
|
+
readonly kind: RunKind;
|
|
70
|
+
/**
|
|
71
|
+
* Required, never defaulted — `00-DOMAIN.md` says trigger is set on every
|
|
72
|
+
* run from the first line of code, and a default would be a way of not
|
|
73
|
+
* saying.
|
|
74
|
+
*/
|
|
75
|
+
readonly trigger: RunTrigger;
|
|
76
|
+
/**
|
|
77
|
+
* Scans only, defaulting to `'m'`; refused on kinds that originate no
|
|
78
|
+
* traffic. Sizes the service cannot run yet are refused, never downgraded.
|
|
79
|
+
*/
|
|
80
|
+
readonly size?: ScanSize;
|
|
81
|
+
/**
|
|
82
|
+
* Absent means the whole target. Engines arrive with the results. Uploads
|
|
83
|
+
* only: a scan's coverage is derived server-side, and a claim is refused.
|
|
84
|
+
*/
|
|
85
|
+
readonly coverage?: Coverage;
|
|
86
|
+
}
|
|
87
|
+
export interface FinishRunInput {
|
|
88
|
+
/**
|
|
89
|
+
* **`'failed'` reconciles nothing** — a failed run is not a complete
|
|
90
|
+
* observation, so {@link RunsResource.summary} and
|
|
91
|
+
* {@link RunsResource.snapshot} will 409 forever after. Only `'finished'`
|
|
92
|
+
* triggers reconciliation.
|
|
93
|
+
*/
|
|
94
|
+
readonly status: 'finished' | 'failed';
|
|
95
|
+
}
|
|
96
|
+
/** A scan's phase, as {@link ScanProgress.phase} reports it. */
|
|
97
|
+
export type ScanPhase = 'queued' | 'launching' | 'scanning' | 'ended';
|
|
98
|
+
/**
|
|
99
|
+
* Where a scan is — {@link RunsResource.progress}'s answer.
|
|
100
|
+
*
|
|
101
|
+
* @remarks Deliberately no percentage: the engine reports nothing until it finishes, so the honest estimate is the time bound, not an invented fraction.
|
|
102
|
+
*/
|
|
103
|
+
export interface ScanProgress {
|
|
104
|
+
readonly runId: string;
|
|
105
|
+
readonly status: RunStatus;
|
|
106
|
+
/**
|
|
107
|
+
* How far the scan has got: `'queued'` (accepted, not yet launched),
|
|
108
|
+
* `'launching'`, `'scanning'`, or `'ended'` — `status` says how.
|
|
109
|
+
*/
|
|
110
|
+
readonly phase: ScanPhase;
|
|
111
|
+
/** Seconds since the run started — up to now, or to when it ended. */
|
|
112
|
+
readonly elapsedSeconds: number;
|
|
113
|
+
/** The size's time budget. The engine is stopped when it runs out. */
|
|
114
|
+
readonly budgetSeconds: number;
|
|
115
|
+
/**
|
|
116
|
+
* When the run will have ended by, one way or the other: the budget plus
|
|
117
|
+
* launch and upload grace. An ISO 8601 string, like every date here.
|
|
118
|
+
*/
|
|
119
|
+
readonly expectedBy: string;
|
|
120
|
+
}
|
|
121
|
+
/** Every field in a {@link RunSummary} that counts issues by severity. */
|
|
122
|
+
export interface SeverityCounts {
|
|
123
|
+
readonly critical: number;
|
|
124
|
+
readonly high: number;
|
|
125
|
+
readonly medium: number;
|
|
126
|
+
readonly low: number;
|
|
127
|
+
readonly advisory: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* What a run did, in the terms a report opens with. Written by
|
|
131
|
+
* reconciliation — see {@link RunsResource.summary}.
|
|
132
|
+
*/
|
|
133
|
+
export interface RunSummary {
|
|
134
|
+
readonly runId: string;
|
|
135
|
+
readonly orgId: string;
|
|
136
|
+
readonly targetId: string;
|
|
137
|
+
readonly kind: RunKind;
|
|
138
|
+
readonly trigger: RunTrigger;
|
|
139
|
+
readonly engines: readonly string[];
|
|
140
|
+
readonly coverage: Coverage;
|
|
141
|
+
readonly durationMs: number;
|
|
142
|
+
readonly new: SeverityCounts;
|
|
143
|
+
readonly stillOpen: SeverityCounts;
|
|
144
|
+
readonly resolved: SeverityCounts;
|
|
145
|
+
readonly regressed: SeverityCounts;
|
|
146
|
+
readonly ignored: SeverityCounts;
|
|
147
|
+
readonly exposureScore: number;
|
|
148
|
+
readonly createdAt: string;
|
|
149
|
+
}
|
|
150
|
+
/** Where one upload's parse stands. */
|
|
151
|
+
export type ArtifactProcessingStatus = 'queued' | 'processing' | 'done' | 'failed';
|
|
152
|
+
/**
|
|
153
|
+
* A raw scanner artifact archived against a run — what {@link RunsResource.import}
|
|
154
|
+
* and {@link RunsResource.listArtifacts} both return.
|
|
155
|
+
*
|
|
156
|
+
* `findingCount`/`skippedLines` are present once `processingStatus` is
|
|
157
|
+
* `'done'`; absent while `'queued'` or `'processing'`, since the parse simply
|
|
158
|
+
* has not happened yet.
|
|
159
|
+
*/
|
|
160
|
+
export interface RunArtifact {
|
|
161
|
+
readonly id: string;
|
|
162
|
+
readonly orgId: string;
|
|
163
|
+
readonly runId: string;
|
|
164
|
+
readonly objectName: string;
|
|
165
|
+
readonly filename: string;
|
|
166
|
+
readonly contentType: string;
|
|
167
|
+
readonly byteSize: number;
|
|
168
|
+
readonly sha256: string;
|
|
169
|
+
readonly sourceEngine?: string;
|
|
170
|
+
readonly expiresAt: string;
|
|
171
|
+
readonly processingStatus: ArtifactProcessingStatus;
|
|
172
|
+
/** Findings parsed from this upload. Present once `processingStatus` is `'done'`. */
|
|
173
|
+
readonly findingCount?: number;
|
|
174
|
+
/** Unreadable lines dropped from a line-delimited upload. Present with `'done'`. */
|
|
175
|
+
readonly skippedLines?: number;
|
|
176
|
+
readonly createdAt: string;
|
|
177
|
+
}
|
|
178
|
+
/** `GET /runs/{id}/artifacts`'s body — not a {@link Page}, since a run holds only a handful of files. */
|
|
179
|
+
export interface RunArtifactList {
|
|
180
|
+
readonly data: readonly RunArtifact[];
|
|
181
|
+
}
|
|
182
|
+
export interface NewRunImport {
|
|
183
|
+
/**
|
|
184
|
+
* The scanner's raw output, sent exactly as given — never JSON-encoded,
|
|
185
|
+
* whatever type it is. A `Buffer`, `Uint8Array`, `Blob` or `string` all work.
|
|
186
|
+
*/
|
|
187
|
+
readonly body: FetchBody;
|
|
188
|
+
/**
|
|
189
|
+
* Sent verbatim as the request's `content-type` — chosen by the caller,
|
|
190
|
+
* never inferred from `body`. Must be one the API accepts (JSON, NDJSON,
|
|
191
|
+
* JSONL, XML or plain text/CSV); anything else is a `415`.
|
|
192
|
+
*/
|
|
193
|
+
readonly contentType: string;
|
|
194
|
+
/** Which importer parses this file, e.g. `'nuclei'`, `'zap'`, `'burp'`, `'nessus'` or `'generic'`. */
|
|
195
|
+
readonly engine: string;
|
|
196
|
+
/** Recorded for the report; trusted for nothing. */
|
|
197
|
+
readonly filename?: string;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* What {@link RunsResource.createUploadUrl} needs to mint a signed URL — the
|
|
201
|
+
* digest and size the caller already knows, having the whole file in hand to
|
|
202
|
+
* upload it. Computed client-side and not re-verified byte-for-byte by the
|
|
203
|
+
* API (see {@link RunsResource.createUploadUrl}'s own `@throws` and TSDoc):
|
|
204
|
+
* that is the entire point of a signed URL over {@link RunsResource.import} —
|
|
205
|
+
* the bytes never transit the API for it to check.
|
|
206
|
+
*/
|
|
207
|
+
export interface NewRunImportUrl {
|
|
208
|
+
/** Lowercase hex SHA-256 of the file about to be uploaded. */
|
|
209
|
+
readonly sha256: string;
|
|
210
|
+
/** The file's exact size. Refused above the API's signed-upload ceiling. */
|
|
211
|
+
readonly byteSize: number;
|
|
212
|
+
/** Sent verbatim as the signed URL's bound content-type — must match the `PUT`'s own header exactly. */
|
|
213
|
+
readonly contentType: string;
|
|
214
|
+
/** Recorded for the report; trusted for nothing. */
|
|
215
|
+
readonly filename?: string;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* A signed URL to `PUT` a large scanner artifact to, straight to the
|
|
219
|
+
* artifacts bucket — what {@link RunsResource.createUploadUrl} returns for a
|
|
220
|
+
* file not already archived on this run.
|
|
221
|
+
*/
|
|
222
|
+
export interface RunUploadUrl {
|
|
223
|
+
/** `PUT` the file here — nothing else, no query string of your own. */
|
|
224
|
+
readonly uploadUrl: string;
|
|
225
|
+
/** Hand this back to {@link RunsResource.completeUpload} once the `PUT` succeeds. */
|
|
226
|
+
readonly objectName: string;
|
|
227
|
+
/**
|
|
228
|
+
* Every one of these must be sent verbatim as headers on the `PUT`, or the
|
|
229
|
+
* bucket refuses the upload — this is what carries the file's retention
|
|
230
|
+
* period through a path that never calls the API's own archiving code.
|
|
231
|
+
*/
|
|
232
|
+
readonly requiredHeaders: Readonly<Record<string, string>>;
|
|
233
|
+
/** The URL itself stops accepting a `PUT` after this — independent of the artifact's own retention. */
|
|
234
|
+
readonly urlExpiresAt: string;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* What {@link RunsResource.completeUpload} needs once a signed-URL `PUT`
|
|
238
|
+
* succeeded: the object it wrote to, and what to parse it as.
|
|
239
|
+
*/
|
|
240
|
+
export interface CompleteRunImport {
|
|
241
|
+
/** From {@link RunUploadUrl.objectName} — the exact value {@link RunsResource.createUploadUrl} returned. */
|
|
242
|
+
readonly objectName: string;
|
|
243
|
+
/** Which importer parses this file, e.g. `'nuclei'`, `'zap'`, `'burp'`, `'nessus'` or `'generic'`. */
|
|
244
|
+
readonly engine: string;
|
|
245
|
+
/** Recorded for the report; trusted for nothing. */
|
|
246
|
+
readonly filename?: string;
|
|
247
|
+
}
|
|
248
|
+
/** {@link RunsResource.waitUntilFinished}'s options. */
|
|
249
|
+
export interface WaitUntilFinishedOptions {
|
|
250
|
+
/**
|
|
251
|
+
* How often to poll {@link RunsResource.get} while the run is still `running`.
|
|
252
|
+
*
|
|
253
|
+
* @defaultValue 5000
|
|
254
|
+
*/
|
|
255
|
+
readonly pollIntervalMs?: number;
|
|
256
|
+
/**
|
|
257
|
+
* How long to poll before giving up and rejecting.
|
|
258
|
+
*
|
|
259
|
+
* Sized for a hosted scan, not an upload: a run behind a busy queue can take
|
|
260
|
+
* minutes, not seconds.
|
|
261
|
+
*
|
|
262
|
+
* @defaultValue 900000 (15 minutes)
|
|
263
|
+
*/
|
|
264
|
+
readonly timeoutMs?: number;
|
|
265
|
+
}
|
|
266
|
+
/** {@link RunsResource.waitForArtifact}'s options — same shape as {@link WaitUntilFinishedOptions}. */
|
|
267
|
+
export interface WaitForArtifactOptions {
|
|
268
|
+
/**
|
|
269
|
+
* How often to poll {@link RunsResource.listArtifacts} while the artifact is
|
|
270
|
+
* still `queued` or `processing`.
|
|
271
|
+
*
|
|
272
|
+
* @defaultValue 5000
|
|
273
|
+
*/
|
|
274
|
+
readonly pollIntervalMs?: number;
|
|
275
|
+
/**
|
|
276
|
+
* How long to poll before giving up and rejecting.
|
|
277
|
+
*
|
|
278
|
+
* @defaultValue 900000 (15 minutes)
|
|
279
|
+
*/
|
|
280
|
+
readonly timeoutMs?: number;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Runs — one execution against a target, and the scan lifecycle around it
|
|
284
|
+
* (`00-DOMAIN.md` §3): started, evidence attached, finished, then
|
|
285
|
+
* reconciled into a summary and a snapshot.
|
|
286
|
+
*/
|
|
287
|
+
export declare class RunsResource {
|
|
288
|
+
private readonly request;
|
|
289
|
+
constructor(request: Requester);
|
|
290
|
+
list(query?: PageQuery & RunFilters): Promise<RunPage>;
|
|
291
|
+
/** Every run matching `filters`, across every page, as an async iterator. */
|
|
292
|
+
listAll(filters?: RunFilters): AsyncIterable<Run>;
|
|
293
|
+
/**
|
|
294
|
+
* Starts a run against a target. It is created `running` and stays that way
|
|
295
|
+
* until {@link RunsResource.finish}: upload scanner output in between with
|
|
296
|
+
* {@link RunsResource.import}.
|
|
297
|
+
*
|
|
298
|
+
* @throws {SecureportError} `terms_required` for every kind if the
|
|
299
|
+
* organisation has not accepted the current terms — a human accepts them at
|
|
300
|
+
* `POST /orgs/{orgId}/terms`; an API key cannot. `verification_required` for
|
|
301
|
+
* `kind: 'scan'` if the target has no currently-passing verification,
|
|
302
|
+
* re-checked fresh as part of this same request rather than trusted from a
|
|
303
|
+
* stored flag. Neither is retried by the transport: both are settled
|
|
304
|
+
* refusals, not transient ones.
|
|
305
|
+
*/
|
|
306
|
+
create(input: NewRun): Promise<Run>;
|
|
307
|
+
/**
|
|
308
|
+
* One run by id. What it found is {@link RunsResource.summary}, once it has finished —
|
|
309
|
+
* this method never carries a summary or findings itself.
|
|
310
|
+
*/
|
|
311
|
+
get(id: string): Promise<Run>;
|
|
312
|
+
/**
|
|
313
|
+
* Ends a run and, for `status: 'finished'`, reconciles it: the findings
|
|
314
|
+
* uploaded against it become new, still-open, resolved or regressed
|
|
315
|
+
* issues, and the run gets a summary. **`status: 'failed'` reconciles
|
|
316
|
+
* nothing** — see {@link FinishRunInput.status}.
|
|
317
|
+
*
|
|
318
|
+
* @remarks Uploads and manual runs only: a `kind: 'scan'` run is refused here — its engine reports its own end, with evidence this route cannot supply. Stop a scan early with {@link RunsResource.cancel} instead.
|
|
319
|
+
* @throws {SecureportError} `conflict` if any upload is still being
|
|
320
|
+
* parsed — poll {@link RunsResource.listArtifacts} and finish once every
|
|
321
|
+
* one is `done` or `failed` — or if the run had already ended;
|
|
322
|
+
* `validation` for a `kind: 'scan'` run.
|
|
323
|
+
*/
|
|
324
|
+
finish(id: string, input: FinishRunInput): Promise<Run>;
|
|
325
|
+
/**
|
|
326
|
+
* Stops a running scan: the run ends as `'cancelled'` immediately, and the
|
|
327
|
+
* scan job behind it is cancelled best-effort.
|
|
328
|
+
*
|
|
329
|
+
* @remarks If the job cancel fails, the engine simply runs out its time budget and its late reports are discarded, so `'cancelled'` is final either way. Nothing is reconciled — a cancelled run resolves no issues, and findings already ingested stay recorded as partial evidence. That intent is what distinguishes it from `'failed'`, which means the scan itself went wrong.
|
|
330
|
+
* @throws {SecureportError} `conflict` if the run had already ended;
|
|
331
|
+
* `validation` for a run that is not a `kind: 'scan'` — an upload is ended
|
|
332
|
+
* by its own caller via {@link RunsResource.finish}.
|
|
333
|
+
*/
|
|
334
|
+
cancel(id: string): Promise<Run>;
|
|
335
|
+
/**
|
|
336
|
+
* Where a scan is: its phase, how long it has run, its time budget, and
|
|
337
|
+
* when it will have ended by — see {@link ScanProgress} for why no percentage.
|
|
338
|
+
*
|
|
339
|
+
* @remarks Combine with {@link RunsResource.waitUntilFinished} for a poll that also knows when to give up: `expectedBy` is the honest bound.
|
|
340
|
+
* @throws {SecureportError} `validation` for a run that is not a
|
|
341
|
+
* `kind: 'scan'` — an upload's progress is whatever its caller is doing.
|
|
342
|
+
*/
|
|
343
|
+
progress(id: string): Promise<ScanProgress>;
|
|
344
|
+
/**
|
|
345
|
+
* Archives a raw scanner artifact against a run. Nothing is parsed on the
|
|
346
|
+
* client side — the whole file is handed to the API as `input.body`, with
|
|
347
|
+
* `input.contentType` sent verbatim, and the API decides how (and when) to
|
|
348
|
+
* parse it.
|
|
349
|
+
*
|
|
350
|
+
* **The response shape depends on size, not just success or failure.** A
|
|
351
|
+
* file under 5 MiB is parsed inline and answers `201` with
|
|
352
|
+
* `processingStatus: 'done'` and `findingCount`/`skippedLines` filled in. At
|
|
353
|
+
* or over 5 MiB the parse is queued and the API answers `202` with
|
|
354
|
+
* `processingStatus: 'queued'` instead — poll {@link RunsResource.listArtifacts}
|
|
355
|
+
* for the outcome. Both are success: check `processingStatus` on the result rather
|
|
356
|
+
* than assuming the synchronous shape. **25 MiB is a hard cap**, refused
|
|
357
|
+
* with `payload_too_large` rather than accepted and truncated.
|
|
358
|
+
*
|
|
359
|
+
* **Idempotent by content, not by request.** Re-uploading the exact same
|
|
360
|
+
* bytes against the same run answers `200` with the original row, verbatim
|
|
361
|
+
* — no re-parse — so a retried upload after a flaky network is never
|
|
362
|
+
* double-counted.
|
|
363
|
+
*
|
|
364
|
+
* @throws {SecureportError} `conflict` if the run has already ended;
|
|
365
|
+
* `payload_too_large` over 25 MiB; `unsupported_media_type` for a
|
|
366
|
+
* `contentType` the API does not accept, or a compressed body.
|
|
367
|
+
*/
|
|
368
|
+
import(id: string, input: NewRunImport): Promise<RunArtifact>;
|
|
369
|
+
/**
|
|
370
|
+
* The first half of the signed-URL upload path for a file too large for
|
|
371
|
+
* {@link RunsResource.import} — Cloud Run caps that route's request body at
|
|
372
|
+
* 32 MiB whatever the API wants, so a genuinely large scan (a big Nessus or
|
|
373
|
+
* Burp export) goes here instead: mint a URL, `PUT` the file straight to
|
|
374
|
+
* the bucket yourself, then {@link RunsResource.completeUpload}.
|
|
375
|
+
*
|
|
376
|
+
* **Returns one of two shapes, told apart structurally.** If the same
|
|
377
|
+
* `sha256` is already archived on this run, this resolves with the
|
|
378
|
+
* existing {@link RunArtifact} directly — nothing minted, nothing to
|
|
379
|
+
* upload. Otherwise it resolves with a {@link RunUploadUrl}. Check for
|
|
380
|
+
* `'uploadUrl' in result` (or any field {@link RunUploadUrl} has and
|
|
381
|
+
* {@link RunArtifact} does not) to tell them apart.
|
|
382
|
+
*
|
|
383
|
+
* **You must `PUT` the bytes yourself, with a plain `fetch` — not through
|
|
384
|
+
* this SDK's own transport.** `uploadUrl` is a signed Cloud Storage URL:
|
|
385
|
+
* this client's `request`/`requestRaw` always attach your API key as a
|
|
386
|
+
* bearer token and always resolve paths against the API's own base URL,
|
|
387
|
+
* neither of which belongs on a request to Cloud Storage. Send every
|
|
388
|
+
* header in `result.requiredHeaders` verbatim — the bucket's signature
|
|
389
|
+
* check refuses the upload otherwise, silently from this SDK's point of
|
|
390
|
+
* view (it never sees that request).
|
|
391
|
+
*
|
|
392
|
+
* @throws {SecureportError} `conflict` if the run has already ended;
|
|
393
|
+
* `unsupported_media_type` for a `contentType` the API does not accept.
|
|
394
|
+
*/
|
|
395
|
+
createUploadUrl(id: string, input: NewRunImportUrl): Promise<RunArtifact | RunUploadUrl>;
|
|
396
|
+
/**
|
|
397
|
+
* The second half of the signed-URL upload path — call once your own
|
|
398
|
+
* `PUT` to {@link RunUploadUrl.uploadUrl} has succeeded. Archives the
|
|
399
|
+
* object as a run artifact and queues it for parsing; unlike
|
|
400
|
+
* {@link RunsResource.import}, the result is never parsed synchronously
|
|
401
|
+
* here — anything that needed a signed URL is already well past the size
|
|
402
|
+
* the API parses inline. Poll {@link RunsResource.listArtifacts} (or use
|
|
403
|
+
* {@link RunsResource.waitForArtifact}) the same way a `202` from
|
|
404
|
+
* {@link RunsResource.import} is polled.
|
|
405
|
+
*
|
|
406
|
+
* **Idempotent by content, same as {@link RunsResource.import}.** Calling
|
|
407
|
+
* this twice for the same object answers `200` with the original row the
|
|
408
|
+
* second time.
|
|
409
|
+
*
|
|
410
|
+
* @throws {SecureportError} `conflict` if the run has already ended, or if
|
|
411
|
+
* nothing was actually uploaded to the signed URL (it may have expired).
|
|
412
|
+
*/
|
|
413
|
+
completeUpload(id: string, input: CompleteRunImport): Promise<RunArtifact>;
|
|
414
|
+
/**
|
|
415
|
+
* The uploads archived against a run, with where each parse stands — what
|
|
416
|
+
* a client polls after a `202` from {@link RunsResource.import}. Not
|
|
417
|
+
* paginated: a run holds the handful of files one scan produced.
|
|
418
|
+
*/
|
|
419
|
+
listArtifacts(id: string): Promise<RunArtifactList>;
|
|
420
|
+
/**
|
|
421
|
+
* What the run did, in the terms a report opens with.
|
|
422
|
+
*
|
|
423
|
+
* @throws {SecureportError} `conflict` if the run has not been reconciled
|
|
424
|
+
* — still running, or ended `failed` — rather than a zeroed summary that
|
|
425
|
+
* would read as "nothing found".
|
|
426
|
+
*/
|
|
427
|
+
summary(id: string): Promise<RunSummary>;
|
|
428
|
+
/**
|
|
429
|
+
* The snapshot a report is rendered from: the run summary, the target,
|
|
430
|
+
* every issue with what this run changed about it, and the suppressed
|
|
431
|
+
* appendix.
|
|
432
|
+
*
|
|
433
|
+
* **Returns `@secureport/core`'s own `Snapshot` type, with real `Date`s —
|
|
434
|
+
* the one method in this resource that does.** Every other method here
|
|
435
|
+
* returns ISO 8601 strings, mirroring the wire exactly; this one instead
|
|
436
|
+
* runs the response text through core's own `parseSnapshot`, since that
|
|
437
|
+
* is the exact function a `Snapshot` written to disk is read back
|
|
438
|
+
* with, and the API's wire shape is asserted `Exact<>` against core's type
|
|
439
|
+
* server-side. That is what makes `@secureport/core` this package's first
|
|
440
|
+
* real dependency, rather than a structural mirror.
|
|
441
|
+
*
|
|
442
|
+
* @throws {SecureportError} `conflict` if the run has not been reconciled
|
|
443
|
+
* — still running, or ended `failed`.
|
|
444
|
+
*/
|
|
445
|
+
snapshot(id: string): Promise<Snapshot>;
|
|
446
|
+
/**
|
|
447
|
+
* Polls {@link RunsResource.get} until the run leaves `'running'`,
|
|
448
|
+
* resolving with whatever it finished as. **Does not itself call
|
|
449
|
+
* {@link RunsResource.summary} or {@link RunsResource.snapshot}** — those
|
|
450
|
+
* still 409 until reconciliation completes, which is why this only
|
|
451
|
+
* watches `status`.
|
|
452
|
+
*
|
|
453
|
+
* Shaped for a long-running hosted scan from the start: today an upload
|
|
454
|
+
* run is finished by the caller directly, so this helper's payoff is
|
|
455
|
+
* mostly forward-looking until scans actually execute.
|
|
456
|
+
*
|
|
457
|
+
* @throws {Error} if `status` is still `'running'` once `timeoutMs` elapses.
|
|
458
|
+
*/
|
|
459
|
+
waitUntilFinished(id: string, options?: WaitUntilFinishedOptions): Promise<Run>;
|
|
460
|
+
/**
|
|
461
|
+
* Polls {@link RunsResource.listArtifacts} until one artifact's
|
|
462
|
+
* `processingStatus` leaves `'queued'`/`'processing'`, resolving with it —
|
|
463
|
+
* the artifact-level completion {@link RunsResource.finish} itself waits
|
|
464
|
+
* on (its own TSDoc: "poll listArtifacts and finish once every one is done
|
|
465
|
+
* or failed"). A large upload answers {@link RunsResource.import} with
|
|
466
|
+
* `202 queued` before the parse has even started; this is what a caller
|
|
467
|
+
* that started one polls instead of hand-rolling the same loop.
|
|
468
|
+
*
|
|
469
|
+
* @throws {Error} if the artifact never appears on the run (id mismatch),
|
|
470
|
+
* or if it is still `queued`/`processing` once `timeoutMs` elapses.
|
|
471
|
+
*/
|
|
472
|
+
waitForArtifact(runId: string, artifactId: string, options?: WaitForArtifactOptions): Promise<RunArtifact>;
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/resources/runs.ts"],"names":[],"mappings":"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"}
|