0

List devices

by
Published today

List access points, switches or gateways from the monitoring API, one page at a time, with next_offset for the following page.

Script aruba_central_onprem Verified

The script

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

3
/**
4
 * List devices
5
 * List access points, switches or gateways from the monitoring API, one page at a time. Returns the page plus next_offset (null on the last page).
6
 */
7
export async function main(
8
  auth: RT.ArubaCentralOnprem,
9
  device_type: "aps" | "switches" | "gateways",
10
  group: string | undefined,
11
  site: string | undefined,
12
  label: string | undefined,
13
  status: string | undefined,
14
  limit: number | undefined,
15
  offset: number | undefined,
16
  calculate_total: boolean | undefined
17
) {
18
  const token = await getAccessToken(auth, "read")
19
  const base = auth.base_url.replace(/\/+$/, "")
20
  const path = {
21
    aps: "/monitoring/v2/aps",
22
    switches: "/monitoring/v1/switches",
23
    gateways: "/monitoring/v1/gateways",
24
  }[device_type]
25
  const pageSize = limit || 100
26
  const start = offset || 0
27

28
  const url = new URL(`${base}${path}`)
29
  const params: { [key: string]: string | number | boolean | undefined } = {
30
    group,
31
    site,
32
    label,
33
    status,
34
    limit: pageSize,
35
    offset: start,
36
    calculate_total: calculate_total || undefined,
37
  }
38
  for (const [k, v] of Object.entries(params)) {
39
    if (v != null && v !== "") {
40
      url.searchParams.append(k, String(v))
41
    }
42
  }
43

44
  const response = await fetch(url, {
45
    headers: {
46
      Authorization: `Bearer ${token}`,
47
      Accept: "application/json",
48
    },
49
  })
50
  if (!response.ok) {
51
    throw new Error(`${response.status} ${await response.text()}`)
52
  }
53

54
  const page = (await response.json()) as { count: number; [key: string]: any }
55
  return {
56
    ...page,
57
    next_offset: page.count >= pageSize ? start + page.count : null,
58
  }
59
}
60

61
// OAuth grant mechanism documented for Central On-Premises (API Gateway > OAuth grant):
62
// login -> authorization code -> access token. Tokens last 2 hours, so a fresh one is minted per run.
63
async function getAccessToken(
64
  auth: RT.ArubaCentralOnprem,
65
  scope: "read" | "all"
66
): Promise<string> {
67
  const base = auth.base_url.replace(/\/+$/, "")
68

69
  const loginUrl = new URL(`${base}/oauth2/authorize/central/api/login`)
70
  loginUrl.searchParams.append("client_id", auth.client_id)
71
  const login = await fetch(loginUrl, {
72
    method: "POST",
73
    headers: { "Content-Type": "application/json", Accept: "application/json" },
74
    body: JSON.stringify({ username: auth.username, password: auth.password }),
75
  })
76
  if (!login.ok) {
77
    throw new Error(`login: ${login.status} ${await login.text()}`)
78
  }
79
  const cookies = login.headers.get("set-cookie") ?? ""
80
  const csrf = cookies.match(/csrftoken=([^;,\s]+)/)?.[1]
81
  const session = cookies.match(/session=([^;,\s]+)/)?.[1]
82
  if (!csrf || !session) {
83
    throw new Error(
84
      "login: response did not set the csrftoken and session cookies"
85
    )
86
  }
87

88
  const authorizeUrl = new URL(`${base}/oauth2/authorize/central/api`)
89
  authorizeUrl.searchParams.append("client_id", auth.client_id)
90
  authorizeUrl.searchParams.append("response_type", "code")
91
  authorizeUrl.searchParams.append("scope", scope)
92
  const authorize = await fetch(authorizeUrl, {
93
    method: "POST",
94
    headers: {
95
      "Content-Type": "application/json",
96
      Accept: "application/json",
97
      Cookie: `session=${session}`,
98
      "X-CSRF-Token": csrf,
99
    },
100
    body: JSON.stringify({ customer_id: auth.customer_id }),
101
  })
102
  if (!authorize.ok) {
103
    throw new Error(`authorize: ${authorize.status} ${await authorize.text()}`)
104
  }
105
  const { auth_code } = (await authorize.json()) as { auth_code: string }
106

107
  const tokenUrl = new URL(`${base}/oauth2/token`)
108
  tokenUrl.searchParams.append("client_id", auth.client_id)
109
  tokenUrl.searchParams.append("client_secret", auth.client_secret)
110
  tokenUrl.searchParams.append("grant_type", "authorization_code")
111
  tokenUrl.searchParams.append("code", auth_code)
112
  const token = await fetch(tokenUrl, {
113
    method: "POST",
114
    headers: { Accept: "application/json" },
115
  })
116
  if (!token.ok) {
117
    throw new Error(`token: ${token.status} ${await token.text()}`)
118
  }
119
  const { access_token } = (await token.json()) as { access_token: string }
120
  return access_token
121
}
122