Add a phpIPAM import to the IP Addresses page

New "Sync from phpIPAM" action on IP Addresses, alongside the existing
"Sync from Tailscale" / "Sync from Proxmox" ones and built the same way:
a new integration type (config in-app, URL + API app ID + app token,
credentials encrypted at rest) that this page pulls from on demand.
Deliberately import-only, not a full integration -- no dedicated page,
dashboard widget, or nav entry, since that's all this was asked for.

Auth is phpIPAM's static "App token" method: create an API app under
Administration -> API with its security set to "SSL with App token", and
its one-time code goes straight in as the `token` header (also sent as
`phpipam-token`, in case a given version expects that name instead) --
no login call, no token to renew. The user/password "User token" method
isn't implemented.

Addresses are read the standard way: GET /subnets/, then GET
/subnets/{id}/addresses/ for each, rather than assuming a single
"all addresses" endpoint exists on every version. phpIPAM wraps every
response as {code, success, data} -- including an empty result: a subnet
with nothing in it answers success:false, message:"No addresses found"
rather than success:true, data:[]. That's read as "nothing here", not a
failure; anything else with success:false throws with phpIPAM's own
message. One subnet failing outright (e.g. the app lacks permission on
it) is skipped with a note rather than aborting the whole sync. Every
address field is read defensively -- optional, independently
type-checked -- so a field phpIPAM renames or drops in some version
leaves that value blank instead of breaking the import.

Imported entries: label from hostname or description, "phpIPAM" as
vendor, the subnet's own description (or its CIDR, if it has none) as
location, and description/note/MAC folded into notes. Existing sync
plumbing (upsertSyncedEntry) gained a location parameter so this and any
future sync can set it; the two existing syncs pass null, unchanged.

Endpoints, the token header, and the address/subnet field names are
cross-checked against phpIPAM's own published API documentation. Not
verified against a live instance -- there wasn't one available while
building this, so if a real sync comes back empty or with the wrong
fields, that's the next thing to check.

Verified with 23 backend checks against a fake phpIPAM server matching
that documented shape (the empty-subnet quirk, a subnet that fails
outright, malformed/missing fields, a non-JSON response) and the real
route (added/updated/skipped counts, a manually-entered IP never
overwritten, roles, no-enabled-integration, upstream failure surfaced
per-integration rather than as a 500, audit entries) plus a browser check
of the real IP Addresses page against the real routers: the sync button,
its result message, re-syncing (updates rather than duplicates), the
manual entry staying untouched, and the viewer view.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
bobbanandClaude Sonnet 5 committed 2026-09-29 19:49:10 +02:00
1 parent bf7f73f6b6
commit 70ba60c7da
14 files changed
+281 -13

No files matched your search

+20
View File
@@ -79,6 +79,26 @@ the dashboard views themselves load fine.
metrics endpoint only exposes current status, not a monitor's scheduled start/end time, so this reflects
what's in maintenance right now rather than mirroring Uptime Kuma's own schedule.
### phpIPAM
- **Config fields:** phpIPAM URL, API app ID, App token
- **Auth:** the `token` header (and `phpipam-token`, in case your version expects that name instead), set to a
static per-app code. In phpIPAM, go to **Administration → API**, create (or edit) an API app, and set its
**App security** to **"SSL with App token"** (or "App token" if the install isn't served over HTTPS). Saving
it shows the app's code once — that's what goes in this integration's "App token" field, and the app's own
short id (chosen when you created it) goes in "API app ID". phpIPAM's other auth method — logging in as a
real user to get a short-lived token — isn't supported; use an App-token app instead.
- **Required access:** the API app just needs read access to whichever sections/subnets you want imported.
- **What it does:** this is import-only, not a full integration page — on the **IP Addresses** page, "Sync
from phpIPAM" reads every subnet and the addresses in each, and adds or updates an IPAM entry per address
(label from its hostname or description, the subnet's own description as its location, description/note/MAC
folded into notes), the same way "Sync from Tailscale"/"Sync from Proxmox" already work: an address you
entered by hand, or that a different sync source owns, is never overwritten.
- **Not verified against a live instance** — built from phpIPAM's own published API documentation
(endpoints, the `token` header, and the address/subnet field names all cross-checked there), but nobody has
run it against a real phpIPAM yet. If a sync comes back empty or with the wrong fields, tell us what your
instance actually returned and we'll adjust.
## DNS providers
### Cloudflare