@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,69 @@
|
|
|
1
|
+
// The SDK's suppression-rules resource: list, create, get and delete.
|
|
2
|
+
import type { Requester } from '../client.js';
|
|
3
|
+
import type { Page, PageQuery } from '../pagination.js';
|
|
4
|
+
import { paginate } from '../pagination.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A pre-emptive suppression rule. `createdAt` is an ISO 8601 string, as the
|
|
8
|
+
* API sends it — parse it yourself if you need a `Date`.
|
|
9
|
+
*/
|
|
10
|
+
export interface SuppressionRule {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly orgId: string;
|
|
13
|
+
|
|
14
|
+
/** `null` means the rule covers every target in the organisation. */
|
|
15
|
+
readonly targetId: string | null;
|
|
16
|
+
|
|
17
|
+
/** Matched against an issue's vulnerability key; `*` is the only wildcard. */
|
|
18
|
+
readonly vulnKeyGlob: string;
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
|
|
21
|
+
/** The authenticated actor that created it — never supplied by the caller. */
|
|
22
|
+
readonly createdBy: string;
|
|
23
|
+
readonly createdAt: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type SuppressionRulePage = Page<SuppressionRule>;
|
|
27
|
+
|
|
28
|
+
export interface NewSuppressionRule {
|
|
29
|
+
/** Omit to cover the whole organisation. */
|
|
30
|
+
readonly targetId?: string;
|
|
31
|
+
|
|
32
|
+
/** Anchored at both ends, so `xss-*` does not match `not-xss-reflected`. */
|
|
33
|
+
readonly vulnKeyGlob: string;
|
|
34
|
+
readonly reason: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pre-emptive "never open an issue for this class" rules — the blunt
|
|
39
|
+
* instrument; per-issue ignore is the default. No update: delete and recreate.
|
|
40
|
+
*/
|
|
41
|
+
export class SuppressionRulesResource {
|
|
42
|
+
constructor(private readonly request: Requester) {}
|
|
43
|
+
|
|
44
|
+
list(query?: PageQuery): Promise<SuppressionRulePage> {
|
|
45
|
+
return this.request({ method: 'GET', path: '/suppression-rules', query: { ...query } });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Every rule, across every page, as an async iterator. */
|
|
49
|
+
listAll(): AsyncIterable<SuppressionRule> {
|
|
50
|
+
return paginate((page) => this.list({ page }));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @throws {SecureportError} `not_found` if `targetId` names no target of yours. */
|
|
54
|
+
create(input: NewSuppressionRule): Promise<SuppressionRule> {
|
|
55
|
+
return this.request({ method: 'POST', path: '/suppression-rules', body: input });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get(id: string): Promise<SuppressionRule> {
|
|
59
|
+
return this.request({ method: 'GET', path: `/suppression-rules/${encodeURIComponent(id)}` });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Issues the rule already caused to open as ignored stay ignored. */
|
|
63
|
+
delete(id: string): Promise<void> {
|
|
64
|
+
return this.request({
|
|
65
|
+
method: 'DELETE',
|
|
66
|
+
path: `/suppression-rules/${encodeURIComponent(id)}`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { Requester } from '../client.js';
|
|
2
|
+
import type { Page, PageQuery } from '../pagination.js';
|
|
3
|
+
import { paginate } from '../pagination.js';
|
|
4
|
+
|
|
5
|
+
/** A target: one thing runs are executed against. */
|
|
6
|
+
export interface Target {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly orgId: string;
|
|
9
|
+
|
|
10
|
+
/** As it appears on a report cover. */
|
|
11
|
+
readonly name: string;
|
|
12
|
+
|
|
13
|
+
/** A URL, host or repository. */
|
|
14
|
+
readonly url: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type TargetPage = Page<Target>;
|
|
18
|
+
|
|
19
|
+
export interface NewTarget {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly url: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* At least one of `name`/`url` is required — the API answers `{}` with a
|
|
26
|
+
* `422 validation`, not a no-op.
|
|
27
|
+
*/
|
|
28
|
+
export interface TargetPatch {
|
|
29
|
+
readonly name?: string;
|
|
30
|
+
readonly url?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type VerificationMethod = 'dns_txt' | 'http_file';
|
|
34
|
+
export type VerificationState = 'unverified' | 'verified';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The target's current verification state. Never carries the token — see
|
|
38
|
+
* {@link IssuedTargetVerification}, the one response that does.
|
|
39
|
+
*
|
|
40
|
+
* Date fields are ISO 8601 strings, as the API sends them — this type is
|
|
41
|
+
* SDK-local (no `@secureport/core` equivalent exists), so there is no
|
|
42
|
+
* shared revival logic to lean on; parse them yourself if you need `Date`.
|
|
43
|
+
*/
|
|
44
|
+
export interface TargetVerification {
|
|
45
|
+
readonly method: VerificationMethod | null;
|
|
46
|
+
readonly state: VerificationState;
|
|
47
|
+
readonly issuedAt: string | null;
|
|
48
|
+
|
|
49
|
+
/** Set only while a rotated token's grace period is still active. */
|
|
50
|
+
readonly previousExpiresAt: string | null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface NewTargetVerification {
|
|
54
|
+
readonly method: VerificationMethod;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The response to issuing (or rotating) a verification token.
|
|
59
|
+
*
|
|
60
|
+
* **The token appears here and nowhere else** — {@link TargetVerification}
|
|
61
|
+
* never carries it, and there is no recovery endpoint. Losing it means
|
|
62
|
+
* issuing a new one, which may reset `state` to `unverified` (see
|
|
63
|
+
* {@link TargetsResource.issueVerification}).
|
|
64
|
+
*
|
|
65
|
+
* `recordName`/`recordValue` are present for `method: 'dns_txt'`;
|
|
66
|
+
* `filePath`/`fileContents` for `method: 'http_file'` — a discriminated
|
|
67
|
+
* pair the wire schema does not enforce, so narrow on `method` yourself.
|
|
68
|
+
*/
|
|
69
|
+
export interface IssuedTargetVerification extends Omit<TargetVerification, 'method'> {
|
|
70
|
+
readonly method: VerificationMethod;
|
|
71
|
+
readonly token: string;
|
|
72
|
+
readonly summary: string;
|
|
73
|
+
readonly recordName?: string;
|
|
74
|
+
readonly recordValue?: string;
|
|
75
|
+
readonly filePath?: string;
|
|
76
|
+
readonly fileContents?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The result of one verification check — evidence, not a status flag. */
|
|
80
|
+
export interface TargetVerificationCheckResult {
|
|
81
|
+
/** This check's own evidence row id — a fresh one every call, whether it passed or failed. */
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly verified: boolean;
|
|
84
|
+
readonly state: VerificationState;
|
|
85
|
+
readonly method: VerificationMethod;
|
|
86
|
+
readonly checkedAt: string;
|
|
87
|
+
readonly expected: string;
|
|
88
|
+
readonly observed: string | null;
|
|
89
|
+
readonly message: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Targets, and the per-target verification flow a hosted scan (`kind:
|
|
94
|
+
* 'scan'`) requires before it can start — see `POST /runs`'s
|
|
95
|
+
* `verification_required` gate.
|
|
96
|
+
*/
|
|
97
|
+
export class TargetsResource {
|
|
98
|
+
constructor(private readonly request: Requester) {}
|
|
99
|
+
|
|
100
|
+
list(query?: PageQuery): Promise<TargetPage> {
|
|
101
|
+
return this.request({ method: 'GET', path: '/targets', query: { ...query } });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Every target, across every page, as an async iterator. */
|
|
105
|
+
listAll(): AsyncIterable<Target> {
|
|
106
|
+
return paginate((page) => this.list({ page }));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
create(input: NewTarget): Promise<Target> {
|
|
110
|
+
return this.request({ method: 'POST', path: '/targets', body: input });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get(id: string): Promise<Target> {
|
|
114
|
+
return this.request({ method: 'GET', path: `/targets/${encodeURIComponent(id)}` });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* **Changing `url` silently un-verifies the target** — the stored
|
|
119
|
+
* verification named the old host, and the API drops `state` to
|
|
120
|
+
* `unverified` as part of this same call. A caller relying on the target
|
|
121
|
+
* staying verified across a URL change needs to re-verify afterwards.
|
|
122
|
+
*/
|
|
123
|
+
update(id: string, patch: TargetPatch): Promise<Target> {
|
|
124
|
+
return this.request({
|
|
125
|
+
method: 'PATCH',
|
|
126
|
+
path: `/targets/${encodeURIComponent(id)}`,
|
|
127
|
+
body: patch,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** @throws {SecureportError} `conflict` if the target has run or issue history. */
|
|
132
|
+
delete(id: string): Promise<void> {
|
|
133
|
+
return this.request({ method: 'DELETE', path: `/targets/${encodeURIComponent(id)}` });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getVerification(id: string): Promise<TargetVerification> {
|
|
137
|
+
return this.request({ method: 'GET', path: `/targets/${encodeURIComponent(id)}/verification` });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Issues a fresh verification token, or rotates the current one — decided
|
|
142
|
+
* server-side, not by this method: calling with the **same `method`** as
|
|
143
|
+
* an already-verified target **rotates** (the target stays `verified`,
|
|
144
|
+
* and the old token keeps working for a 24-hour grace period). Calling
|
|
145
|
+
* with any other method, or while unverified, **re-issues** and resets
|
|
146
|
+
* `state` to `unverified` until the new token is checked.
|
|
147
|
+
*/
|
|
148
|
+
issueVerification(id: string, input: NewTargetVerification): Promise<IssuedTargetVerification> {
|
|
149
|
+
return this.request({
|
|
150
|
+
method: 'POST',
|
|
151
|
+
path: `/targets/${encodeURIComponent(id)}/verification`,
|
|
152
|
+
body: input,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Runs the verification check now, fresh — never trusts a stored flag.
|
|
158
|
+
* **Promote-only**: a match sets `state: 'verified'`; a mismatch or
|
|
159
|
+
* unreachable record is recorded as evidence but never demotes a target
|
|
160
|
+
* that is already verified. Writes a new evidence row every call, whether
|
|
161
|
+
* it passes or fails — not a no-op check.
|
|
162
|
+
*
|
|
163
|
+
* @throws {SecureportError} `conflict` if no token has been issued yet.
|
|
164
|
+
*/
|
|
165
|
+
verify(id: string): Promise<TargetVerificationCheckResult> {
|
|
166
|
+
return this.request({ method: 'POST', path: `/targets/${encodeURIComponent(id)}/verify` });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Revokes the current token outright — idempotent; revoking an
|
|
171
|
+
* already-unverified target is a clean no-op, not an error.
|
|
172
|
+
*/
|
|
173
|
+
revokeVerification(id: string): Promise<void> {
|
|
174
|
+
return this.request({
|
|
175
|
+
method: 'DELETE',
|
|
176
|
+
path: `/targets/${encodeURIComponent(id)}/verification`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|