0

List alerts

by
Published today

List alerts raised between start_time and end_time (ISO 8601; end_time defaults to now), one page at a time (limit, default 100, max 10000, and offset). Optional alert_type (e.g. DLP, malware, policy, uba, Compromised Credential), query (Netskope query language, e.g. severity eq "high"; combined with alert_type using AND) and fields (comma-separated columns). Returns the result page plus next_offset, null on the last page.

Script netskope Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 6 hours ago
1
//native
2

3
/**
4
 * List alerts
5
 * List alerts raised in a time window, one page at a time. Pass next_offset back as offset to fetch the next page.
6
 */
7
export async function main(
8
  auth: RT.Netskope,
9
  start_time: string,
10
  end_time: string | undefined,
11
  limit: number | undefined,
12
  offset: number | undefined,
13
  alert_type: string | undefined,
14
  query: string | undefined,
15
  fields: string | undefined
16
) {
17
  const toEpoch = (value: string) => {
18
    const ms = Date.parse(value)
19
    if (Number.isNaN(ms)) {
20
      throw new Error(`Invalid date: ${value}`)
21
    }
22
    return Math.floor(ms / 1000).toString()
23
  }
24
  const pageSize = limit || 100
25
  if (pageSize > 10000) {
26
    throw new Error("limit cannot exceed 10000 (datasearch page cap)")
27
  }
28
  const skip = offset || 0
29

30
  const filters: string[] = []
31
  if (query != null && query !== "") {
32
    filters.push(query)
33
  }
34
  if (alert_type != null && alert_type !== "") {
35
    if (!/^[a-zA-Z0-9_ -]+$/.test(alert_type)) {
36
      throw new Error(`Invalid alert_type: ${alert_type}`)
37
    }
38
    filters.push(`alert_type eq "${alert_type}"`)
39
  }
40

41
  const url = new URL(
42
    `${auth.tenant_url.replace(/\/+$/, "")}/api/v2/events/datasearch/alert`
43
  )
44
  url.searchParams.append("starttime", toEpoch(start_time))
45
  url.searchParams.append(
46
    "endtime",
47
    end_time ? toEpoch(end_time) : Math.floor(Date.now() / 1000).toString()
48
  )
49
  url.searchParams.append("limit", pageSize.toString())
50
  url.searchParams.append("offset", skip.toString())
51
  if (filters.length) {
52
    url.searchParams.append("query", filters.join(" AND "))
53
  }
54
  if (fields != null && fields !== "") {
55
    url.searchParams.append("fields", fields)
56
  }
57

58
  const response = await fetch(url, {
59
    method: "GET",
60
    headers: {
61
      "Netskope-Api-Token": auth.token,
62
      Accept: "application/json",
63
    },
64
  })
65

66
  if (!response.ok) {
67
    throw new Error(`${response.status} ${await response.text()}`)
68
  }
69

70
  const page = (await response.json()) as {
71
    result?: unknown[]
72
    status?: { execution?: string; total?: number }
73
  }
74
  if (page.status?.execution === "FAILED") {
75
    throw new Error(`Netskope query failed: ${JSON.stringify(page.status)}`)
76
  }
77
  const count = page.result?.length ?? 0
78
  const total = page.status?.total
79
  const hasMore = total != null ? skip + count < total : count === pageSize
80
  return {
81
    ...page,
82
    next_offset: hasMore && count > 0 ? skip + count : null,
83
  }
84
}
85