master
md 364 lines 13.5 KB
Rendered Raw
1 <!--startmeta
2 custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/crates/netflow-plugin/integrations/generic_json-over-http_ipam.md"
3 meta_yaml: "https://github.com/netdata/netdata/edit/master/src/crates/netflow-plugin/metadata.yaml"
4 sidebar_label: "Generic JSON-over-HTTP IPAM"
5 learn_status: "Published"
6 learn_rel_path: "Network Flows/Enrichment Methods"
7 keywords: ['ipam', 'cmdb', 'infoblox', 'bluecat', 'phpipam', 'servicenow', 'custom', 'prefix list', 'network identity']
8 message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE FLOWS' metadata.yaml FILE"
9 endmeta-->
10
11 <!-- markdownlint-disable-file -->
12
13 # Generic JSON-over-HTTP IPAM
14
15
16 <img src="https://netdata.cloud/img/network-wired.svg" width="150"/>
17
18
19 Plugin: netflow-plugin
20 Module: generic-ipam
21
22 <img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
23
24 ## Overview
25
26 Annotate network flows with network-identity labels from any JSON-over-HTTP IPAM
27 or CMDB endpoint. The plugin does not care WHO produces the JSON -- it cares
28 about the JSON shape after your `transform` (a jq expression) runs over it.
29 Examples: Infoblox WAPI, BlueCat REST API, phpIPAM, ServiceNow CMDB queries, an
30 internal aggregator, a Lambda function, a static file served from S3, a
31 hand-rolled CMDB.
32
33 This card is also the **reference description** of how all the other Network
34 Identity cards work under the hood. AWS IP Ranges, GCP IP Ranges, Azure IP Ranges
35 and NetBox are all special-cased instances of this same mechanism: each is just
36 a known URL plus a recommended jq `transform`. Read this card to understand the
37 generic shape, then read the per-source cards for the URL and transform that fit
38 that specific provider.
39
40 For the full network-identity concept (merge order vs GeoIP and static, what
41 fields you can populate, why TLS verification cannot be disabled), see
42 [Network Identity](https://learn.netdata.cloud/docs/network-flows/enrichment).
43
44
45 The plugin issues a periodic HTTP request (GET by default, POST optionally) to
46 your configured URL with the headers you specify, parses the response as JSON,
47 runs your `transform` jq expression (compiled by the
48 [jaq](https://github.com/01mf02/jaq) library) over the parsed body, and merges
49 the resulting per-prefix rows into the network-attributes trie.
50
51 The same flow applies to every JSON-over-HTTP source; the integration-specific
52 part is the URL and the `transform` expression.
53
54
55 This integration is only supported on the following platforms:
56
57 - Linux
58
59 This integration supports multiple instances configured side-by-side.
60
61
62 ### Default Behavior
63
64 #### Auto-Detection
65
66 Disabled by default. Add a named entry under `enrichment.network_sources` for each IPAM/CMDB/endpoint you want to import.
67
68 #### Limits
69
70 Resource use scales with response size, transform complexity, refresh interval, and the number of emitted prefixes. Empty transform output is treated as a fetch failure.
71
72 #### Performance Impact
73
74 One HTTP request per refresh interval plus a jq transform over the response. Runtime enrichment does prefix matching for source and destination IPs, and cost scales with the number of loaded network-source records.
75
76 ## Setup
77
78
79 ### Prerequisites
80
81 #### An HTTP/HTTPS endpoint returning JSON
82
83 The endpoint must respond with a parseable JSON document (the plugin sets
84 `Accept: application/json`). Only GET and POST are accepted as request
85 methods. There is no pagination, no
86 cursor following, no `Link: rel=next` handling -- the fetch is one-shot
87 per cycle. If your IPAM paginates, expose a bulk endpoint or wrap it in a
88 server-side aggregator that returns the full list at one URL.
89
90
91 #### Authentication via headers
92
93 The plugin has no built-in OAuth flow, basic-auth helper, or token
94 refresh. Whatever the API needs (bearer tokens, API keys, custom header
95 names, basic-auth realms) goes into the `headers:` map. The header map is
96 an arbitrary string-to-string mapping, so any single-shot scheme works.
97 For short-lived tokens, refresh them outside Netdata and reload the
98 plugin config.
99
100
101 #### A POST endpoint must accept an empty body
102
103 When `method: POST` is configured, the plugin sends the request with the
104 configured headers but **no request body**. If your CMDB requires a JSON query body to return prefixes,
105 wrap it server-side with an endpoint that accepts GET (or POST with no
106 body) and returns the full prefix set.
107
108
109
110 ### Configuration
111
112 #### Options
113
114 Add a named entry under `enrichment.network_sources`. Unknown keys cause a
115 config error.
116
117
118 <details open><summary>Config options</summary>
119
120
121
122 | Option | Description | Default | Required |
123 |:-----|:------------|:--------|:---------:|
124 | url | HTTP/HTTPS endpoint. Required (a non-empty URL is enforced by validation). | | yes |
125 | method | HTTP method. Only `GET` and `POST` are accepted; anything else fails validation. Note that `POST` is sent with no request body. | GET | no |
126 | headers | Map of additional HTTP request headers. Use this for any authentication scheme (`Authorization: Bearer ...`, `token: ...`, custom API-key headers, basic-auth realms encoded explicitly, etc.). Values are passed through verbatim. | {} | no |
127 | interval | Refresh cadence. Values below 60 seconds are accepted, but refreshes still run no faster than once per minute. Pick the value that matches how often your IPAM actually changes (5-15 minutes for a curated CMDB; daily for slow-moving prefix lists). | 60s | no |
128 | timeout | Per-request timeout. Must be greater than 0. | 60s | no |
129 | proxy | Whether to honor the system HTTP/HTTPS proxy environment variables. Set to `false` to bypass the proxy for this source (useful when the IPAM is on the internal network and the proxy is for outbound traffic only). | true | no |
130 | tls.enable | Enables custom TLS settings (custom CA bundle, mTLS client certificate). Must be `true` whenever any of `tls.ca_file`, `tls.cert_file`, `tls.key_file` is set. | false | no |
131 | tls.verify | Certificate verification toggle. **Setting this to `false` is rejected by validation** -- network-identity data flows directly into security-relevant enrichment, so MITM-able responses are not allowed. Use `tls.ca_file` to trust internal CAs instead. | true | no |
132 | tls.skip_verify | Legacy alias for the same intent as `tls.verify: false`. **Setting this to `true` is rejected by validation.** Use `tls.ca_file`. | false | no |
133 | tls.ca_file | PEM file with the CA bundle to trust for this endpoint (instead of, or in addition to, the system roots). The recommended way to talk to an internal IPAM behind your own PKI. | | no |
134 | tls.cert_file | PEM file with the client certificate, for mTLS-protected endpoints. | | no |
135 | tls.key_file | PEM file with the client private key. Required only when the key is in a separate file from the certificate; if omitted, the cert file is reused. `tls.cert_file` must also be set whenever `tls.key_file` is set. | | no |
136 | transform | jq expression compiled by [jaq](https://github.com/01mf02/jaq). Receives the entire parsed JSON body once and must produce a **stream of objects**, where each object has at minimum a `prefix` field (a CIDR string -- `IPv4/len` or `IPv6/len`) plus any of the optional attribute fields: `name`, `role`, `site`, `region`, `country`, `state`, `city`, `tenant`, `asn`, `asn_name`. Any field not produced is treated as empty. The transform compiles at startup -- a syntax error fails the config load. An empty stream at runtime is treated as a fetch failure and triggers backoff. | . | yes |
137
138
139 </details>
140
141
142
143 #### via File
144
145 The configuration file name for this integration is `netflow.yaml`.
146
147
148 You can edit the configuration file using the [`edit-config`](https://github.com/netdata/netdata/blob/master/docs/netdata-agent/configuration/README.md#edit-configuration-files) script from the
149 Netdata [config directory](https://github.com/netdata/netdata/blob/master/docs/netdata-agent/configuration/README.md#locate-your-config-directory).
150
151 ```bash
152 cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
153 sudo ./edit-config netflow.yaml
154 ```
155
156 ##### Examples
157
158 ###### Flat list with `{prefix, name, env}`
159
160 The simplest IPAM shape: a top-level array of subnets, each with a CIDR
161 string and a few labels. Maps `env` -> tenant and the `name` -> NET_NAME.
162
163
164 ```yaml
165 enrichment:
166 network_sources:
167 custom_ipam:
168 url: "https://ipam.corp.example/api/v1/prefixes"
169 headers:
170 Authorization: "Bearer abcdef0123456789"
171 interval: 5m
172 transform: |
173 .[] | {
174 prefix: .prefix,
175 name: .name,
176 tenant: .env
177 }
178
179 ```
180 ###### phpIPAM with API token
181
182 phpIPAM exposes `/api/<APP>/subnets/`. Replace `<APP>` with your phpIPAM
183 application name. phpIPAM splits the address into a base and a mask --
184 the transform reassembles them into a CIDR string.
185
186
187 <details open><summary>Config</summary>
188
189 ```yaml
190 enrichment:
191 network_sources:
192 phpipam:
193 url: "https://ipam.example/api/netdata/subnets/"
194 headers:
195 token: "abcdef..."
196 interval: 10m
197 transform: |
198 .data[] | {
199 prefix: (.subnet + "/" + (.mask|tostring)),
200 name: .description,
201 tenant: (.custom_tenant // ""),
202 site: (.location.name // "")
203 }
204
205 ```
206 </details>
207
208 ###### Hierarchical CMDB export
209
210 A CMDB that returns nested objects -- top-level sites, each with a list
211 of vlans, each with a list of prefixes. Flattens to one row per prefix,
212 inheriting site and role labels from the parent.
213
214
215 <details open><summary>Config</summary>
216
217 ```yaml
218 enrichment:
219 network_sources:
220 cmdb:
221 url: "https://cmdb.example/export/networks.json"
222 headers:
223 Authorization: "Bearer <CMDB_TOKEN>"
224 interval: 15m
225 transform: |
226 .sites[] as $site
227 | $site.vlans[] as $vlan
228 | $vlan.prefixes[]
229 | {
230 prefix: .cidr,
231 name: .label,
232 site: $site.name,
233 region: $site.region,
234 role: $vlan.role,
235 tenant: $vlan.tenant
236 }
237
238 ```
239 </details>
240
241 ###### Internal IPAM behind mTLS
242
243 When the IPAM is fronted by your internal PKI and requires a client
244 certificate. `tls.enable: true` activates the custom TLS path; `tls.verify`
245 must remain true (cannot be disabled).
246
247
248 <details open><summary>Config</summary>
249
250 ```yaml
251 enrichment:
252 network_sources:
253 corp_ipam:
254 url: "https://ipam.corp/api/networks"
255 tls:
256 enable: true
257 ca_file: /etc/netdata/ssl/corp-ca.pem
258 cert_file: /etc/netdata/ssl/netdata.crt
259 key_file: /etc/netdata/ssl/netdata.key
260 interval: 10m
261 transform: |
262 .[] | {
263 prefix: .cidr,
264 name: .label,
265 tenant: .tenant
266 }
267
268 ```
269 </details>
270
271 ###### Source with the system proxy bypassed
272
273 When the agent host has an outbound HTTP proxy configured but the IPAM
274 lives on the internal network and should be reached directly.
275
276
277 <details open><summary>Config</summary>
278
279 ```yaml
280 enrichment:
281 network_sources:
282 internal_ipam:
283 url: "https://ipam.internal/api/networks"
284 proxy: false
285 headers:
286 Authorization: "Bearer ..."
287 interval: 5m
288 transform: |
289 .[] | { prefix: .cidr, name: .label }
290
291 ```
292 </details>
293
294
295
296 ### Endpoint requires pagination
297
298 The plugin does not paginate. Either raise the page size in the URL to
299 cover your full inventory, or wrap the endpoint with a server-side
300 aggregator that returns all results at one URL. There is no built-in
301 `Link: rel=next` follower.
302
303
304 ### POST endpoint requires a request body
305
306 The plugin's POST request is sent with no body. If your CMDB requires a
307 JSON query body to return prefixes, wrap it server-side with an endpoint
308 that accepts GET (or accepts POST with no body) and returns the full prefix
309 set.
310
311
312 ### TLS verification cannot be disabled
313
314 `tls.verify: false` and `tls.skip_verify: true` are both rejected during
315 configuration validation. Use `tls.ca_file` to trust internal CAs. This is
316 deliberate -- network-identity rows feed enrichment used in security
317 investigations and capacity decisions, where silently accepting MITM-able
318 responses would corrupt every downstream analysis.
319
320
321 ### Empty result back-off
322
323 An empty stream from the jq transform is treated as a fetch failure.
324 The source then backs
325 off exponentially -- starting at `interval / 10` (floor 1s), doubling on
326 each consecutive failure, and capped at the regular `interval`. On the
327 next successful non-empty fetch the cadence resets to `interval`. If your
328 IPAM legitimately has no prefixes (a quiet state), have the upstream
329 return at least one synthetic prefix so the source does not back off.
330
331
332 ### Refresh appears slower than configured
333
334 The fetch loop floors the configured `interval` at 60 seconds. Configuring
335 `interval: 5s` does not produce a 5-second loop -- it produces a 60-second
336 loop. Pick a value at or above 60s that matches how often your IPAM
337 actually changes (5-15 minutes is typical for a curated CMDB).
338
339
340 ### Unknown config keys cause errors
341
342 The config struct uses `deny_unknown_fields`. Typos like `headres:` or a
343 non-existent option fail config load with a parse error rather than being
344 silently ignored. Check the `enrichment.network_sources.<name>` schema
345 listed under "Config options".
346
347
348 ### JSON parse errors are silent in the dashboard
349
350 Decode failures (HTTP error, JSON parse error, jq runtime error, schema
351 mismatch on `prefix`) are logged but do not surface in the dashboard.
352 Watch the Netdata journal for warnings:
353 `journalctl --namespace netdata | grep network_sources`.
354
355
356 ### Prefer explicit authorization headers over URL credentials
357
358 URLs with embedded credentials (`https://user:pass@host`) are converted to
359 HTTP Basic authentication by the HTTP client. Prefer `headers:` for clarity
360 and to avoid storing credentials in URLs -- e.g.
361 `headers: { Authorization: "Basic dXNlcjpwYXNz" }` for HTTP basic-auth.
362
363
364