1 | |
2 |
|
3 | |
4 | * List Issues |
5 | * List Wiz issues (risks) ordered by severity, with optional filters by severity, status and project. Returns a cursor-paginated page. |
6 | */ |
7 | export async function main( |
8 | auth: RT.Wiz, |
9 | severity: |
10 | | ("INFORMATIONAL" | "LOW" | "MEDIUM" | "HIGH" | "CRITICAL")[] |
11 | | undefined, |
12 | status: ("OPEN" | "IN_PROGRESS" | "RESOLVED" | "REJECTED")[] | undefined, |
13 | first: number | undefined, |
14 | after: string | undefined |
15 | ) { |
16 | const tokenResponse = await fetch( |
17 | auth.auth_url || "https://auth.app.wiz.io/oauth/token", |
18 | { |
19 | method: "POST", |
20 | headers: { "Content-Type": "application/x-www-form-urlencoded" }, |
21 | body: new URLSearchParams({ |
22 | grant_type: "client_credentials", |
23 | audience: auth.audience || "wiz-api", |
24 | client_id: auth.client_id, |
25 | client_secret: auth.client_secret, |
26 | }), |
27 | } |
28 | ) |
29 | if (!tokenResponse.ok) { |
30 | throw new Error(`${tokenResponse.status} ${await tokenResponse.text()}`) |
31 | } |
32 | const { access_token } = (await tokenResponse.json()) as { |
33 | access_token: string |
34 | } |
35 |
|
36 | const filterBy: { [key: string]: any } = {} |
37 | if (severity && severity.length > 0) filterBy.severity = severity |
38 | if (status && status.length > 0) filterBy.status = status |
39 |
|
40 | const query = ` |
41 | query ListIssues($first: Int, $after: String, $filterBy: IssueFilters, $orderBy: IssueOrder) { |
42 | issues: issuesV2(first: $first, after: $after, filterBy: $filterBy, orderBy: $orderBy) { |
43 | totalCount |
44 | pageInfo { hasNextPage endCursor } |
45 | nodes { |
46 | id |
47 | type |
48 | severity |
49 | status |
50 | createdAt |
51 | updatedAt |
52 | dueAt |
53 | resolvedAt |
54 | statusChangedAt |
55 | resolutionReason |
56 | sourceRule { |
57 | __typename |
58 | ... on Control { id name description } |
59 | ... on CloudConfigurationRule { id name description serviceType } |
60 | ... on CloudEventRule { id name description } |
61 | } |
62 | entitySnapshot { |
63 | id |
64 | name |
65 | type |
66 | nativeType |
67 | status |
68 | cloudPlatform |
69 | region |
70 | subscriptionName |
71 | subscriptionExternalId |
72 | providerId |
73 | tags |
74 | } |
75 | projects { id name slug businessUnit } |
76 | notes { id text createdAt updatedAt user { name email } } |
77 | serviceTickets { externalId name url } |
78 | } |
79 | } |
80 | }` |
81 |
|
82 | const response = await fetch(auth.api_endpoint, { |
83 | method: "POST", |
84 | headers: { |
85 | Authorization: `Bearer ${access_token}`, |
86 | "Content-Type": "application/json", |
87 | Accept: "application/json", |
88 | }, |
89 | body: JSON.stringify({ |
90 | query, |
91 | variables: { |
92 | first: first ?? 50, |
93 | after: after || null, |
94 | filterBy, |
95 | orderBy: { field: "SEVERITY", direction: "DESC" }, |
96 | }, |
97 | }), |
98 | }) |
99 |
|
100 | if (!response.ok) { |
101 | throw new Error(`${response.status} ${await response.text()}`) |
102 | } |
103 |
|
104 | const result = (await response.json()) as { data?: any; errors?: any } |
105 | if (result.errors) { |
106 | throw new Error(JSON.stringify(result.errors)) |
107 | } |
108 | return result.data.issues |
109 | } |
110 |
|