0

Search fixed addresses

Published today

Search static DHCP reservations (fixedaddress) by MAC address (any of aa:bb:cc:dd:ee:ff, AA-BB-CC-DD-EE-FF or aabb.ccdd.eeff), IPv4 address, network CIDR, network view or extensible attribute values (extattr_filters {"Site": "Paris"}), one page at a time. Pass the returned next_page_id as page_id to get the next page; it is null on the last page.

Script infoblox_nios Verified

The script

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

3
function wapiUrl(auth: RT.InfobloxNios, path: string) {
4
  const host = auth.host
5
    .trim()
6
    .replace(/^https?:\/\//, "")
7
    .replace(/\/+$/, "")
8
  const version = auth.wapi_version.trim().replace(/^v/, "")
9
  return new URL(`https://${host}/wapi/v${version}/${path}`)
10
}
11

12
function basicAuth(auth: RT.InfobloxNios) {
13
  const bytes = new TextEncoder().encode(`${auth.username}:${auth.password}`)
14
  return `Basic ${btoa(String.fromCharCode(...bytes))}`
15
}
16

17
async function wapiError(response: Response) {
18
  const text = await response.text()
19
  if (response.status === 401) {
20
    return new Error(
21
      "401 Unauthorized: wrong username or password, or the user's admin group has no API access"
22
    )
23
  }
24
  try {
25
    // WAPI errors are JSON: {"Error": "AdmConDataNotFoundError: ...", "code": "Client.Ibap.Data.NotFound", "text": "..."}
26
    const { Error: error, code, text: detail } = JSON.parse(text)
27
    if (error) {
28
      const message =
29
        detail && !error.includes(detail) ? `${error}: ${detail}` : error
30
      return new Error(
31
        `${response.status} ${message}${code ? ` (${code})` : ""}`
32
      )
33
    }
34
  } catch {}
35
  return new Error(`${response.status} ${text}`)
36
}
37

38
/**
39
 * Search fixed addresses
40
 * Search static DHCP reservations (fixedaddress) by MAC address (any of aa:bb:cc:dd:ee:ff, AA-BB-CC-DD-EE-FF or aabb.ccdd.eeff), IPv4 address, network CIDR, network view or extensible attribute values (extattr_filters {"Site": "Paris"}), one page at a time. Pass the returned next_page_id as page_id to get the next page; it is null on the last page.
41
 */
42
export async function main(
43
  auth: RT.InfobloxNios,
44
  mac: string | undefined,
45
  ipv4addr: string | undefined,
46
  network: string | undefined,
47
  network_view: string | undefined,
48
  extattr_filters: { [key: string]: string } | undefined,
49
  max_results: number | undefined,
50
  page_id: string | undefined,
51
  return_fields: string[] | undefined
52
) {
53
  const url = wapiUrl(auth, "fixedaddress")
54
  if (mac) {
55
    // NIOS stores MACs as aa:bb:cc:dd:ee:ff; accept AA-BB-..., aabb.ccdd.eeff and bare hex.
56
    const hex = mac
57
      .trim()
58
      .toLowerCase()
59
      .replace(/[^0-9a-f]/g, "")
60
    url.searchParams.append(
61
      "mac",
62
      hex.length === 12 ? hex.match(/../g)!.join(":") : mac.trim().toLowerCase()
63
    )
64
  }
65
  if (ipv4addr) url.searchParams.append("ipv4addr", ipv4addr)
66
  if (network) url.searchParams.append("network", network)
67
  if (network_view) url.searchParams.append("network_view", network_view)
68
  for (const [name, value] of Object.entries(extattr_filters ?? {})) {
69
    if (value != null && value !== "")
70
      url.searchParams.append(`*${name}`, String(value))
71
  }
72
  const fields = [
73
    "mac",
74
    "name",
75
    "network",
76
    "comment",
77
    "extattrs",
78
    ...(return_fields ?? []),
79
  ]
80
  url.searchParams.append("_return_fields+", fields.join(","))
81
  url.searchParams.append("_paging", "1")
82
  url.searchParams.append("_return_as_object", "1")
83
  url.searchParams.append("_max_results", String(max_results || 100))
84
  if (page_id) url.searchParams.append("_page_id", page_id)
85

86
  const response = await fetch(url, {
87
    headers: {
88
      Authorization: basicAuth(auth),
89
      Accept: "application/json",
90
    },
91
  })
92

93
  if (!response.ok) {
94
    throw await wapiError(response)
95
  }
96

97
  const data = await response.json()
98
  return { result: data.result, next_page_id: data.next_page_id ?? null }
99
}
100