PhpIPAM MAC-Adressen per arp ermitteln und hinzufügen: Unterschied zwischen den Versionen
Aus znilwiki
BLinz (Diskussion | Beiträge) |
BLinz (Diskussion | Beiträge) |
||
Zeile 197: | Zeile 197: | ||
---- | ---- | ||
==Konfiguration== | ==Konfiguration== | ||
URL='https://phpipam.znil.local/api' | URL='https://phpipam.znil.local/api' | ||
APP='ARP-CronJob' | APP='ARP-CronJob' | ||
TOKEN='dI4iAJlvuo9z78xlCUt5N4ubmy1FPyoL' | |||
SUBNET='192.168.0.0/22' | |||
TOKEN='dI4iAJlvuo9z78xlCUt5N4ubmy1FPyoL' | INTERFACE='ens33' | ||
INVALIDTAGS=("3" "4") | |||
SUBNET='192.168.0.0/22' | Bei der {{code|URL}} setzt Ihr den Aufruf zu eurer '''phpIPAM''' Installation ein.<br> | ||
INTERFACE='ens33' | |||
INVALIDTAGS=("3" "4") |
Version vom 19. Mai 2025, 10:57 Uhr
Changelog:
- 19.05.2025 erste Version
Vorwort
phpIPAM kann zu den IP-Adressen auch die MAC-Adressen zuordnen:
Dazu wird jedoch ausschließlich SNMP verwendet. Man muss ein Gerät vom Typ Switch einrichten und die Abfrage der MAC-Adress-Tabelle per SNMP einrichten.
Das macht ja durchaus sinn, jedoch sind meine Allnet-Switche zum Beispiel nicht kompatibel damit.
Im Internet fand ich dieses Skript hier:
https://github.com/lazynooblet/scripts/tree/main/bash/phpipam-update-mac-from-arp
welches die ARP-Tabelle auf dem Linux-System nutzt vom welches es aufgerufen wird.
Ich habe das Skript in 2 Punkten abgepasst:
- Im Original wird sich per Benutzername und Passwort angemeldet um sich den API-Key zu holen. Meine Variante nutzt einfach gleich den API Key (und versucht auch nicht diesen am Ende zu löschen)
- Ich lasse vorher einen fping über den Bereich laufen damit der ARP-Cache auch frisch gefüllt ist.
Das geänderte Skript
nano phpipam-update-mac-from-arp_V1.1.sh
#!/bin/bash
# V1.1
# Original by "lazynooblet" => https://github.com/lazynooblet/scripts/tree/main/bash/phpipam-update-mac-from-arp
# Modified 2025-05-19 by Bernhard Linz => https://znil.net/index.php?title=PhpIPAM_MAC-Adressen_per_arp_ermitteln_und_hinzuf%C3%BCgen
# Changes V1.1:
# - Remove USER and PASSWORD Authentification, use TOKEN instead
# - Add fping before checking MAC-Adresses to fill up ARP-Cache
URL='https://phpipam.znil.local/api'
APP='ARP-CronJob'
#USER='user'
#PASS='passwort'
TOKEN='dI4iAJlvuo9z78xlCUt5N4ubmy1FPyoL'
SUBNET='192.168.0.0/22'
INTERFACE='ens33'
INVALIDTAGS=("3" "4")
#echo "[INFO] Fetching token"
#TOKEN=$(curl -X POST --user ${USER}:${PASS} ${URL}/${APP}/user/ -s | jq --raw-output .data.token)
#if [ "$?" != "0" ]; then
# echo "[FAIL] Error fetching token from PHPIPAM" 1>&2
# exit 1
#fi
#if [ -z "${TOKEN}" ]; then
# echo "[FAIL] Didn't receive valid token from PHPIPAM" 1>&2
# exit 1
#fi
#echo "[INFO] Fetching token expiry (token test)"
#EXPIRES=$(curl -X GET --header "token: ${TOKEN}" ${URL}/${APP}/user/ -s | jq --raw-output .data.expires)
#if [ "$?" != "0" ]; then
# echo "[FAIL] Error fetching token expiry from PHPIPAM" 1>&2
# exit 1
#fi
#if [ -z "${EXPIRES}" ]; then
# echo "[FAIL] Didn't receive valid token expiry from PHPIPAM" 1>&2
# exit 1
#fi
echo "[INFO] fping subnet"
fping -4 -a -q -g ${SUBNET}
echo "[INFO] Fetching subnet id"
SUBNETID=$(curl -X GET --header "token: ${TOKEN}" ${URL}/${APP}/subnets/search/${SUBNET} -s | jq --raw-output .data[0].id)
if [ "$?" != "0" ]; then
echo "[FAIL] Error fetching subnet id from PHPIPAM" 1>&2
exit 1
fi
if [ -z "${SUBNETID}" ]; then
echo "[FAIL] Didn't receive valid subnet id from PHPIPAM" 1>&2
exit 1
fi
_update() {
ip=${1}
mac=${2}
IPID=$(curl -X GET --header "token: ${TOKEN}" ${URL}/${APP}/addresses/${ip}/${SUBNETID} -s | jq --raw-output .data.id)
if [ "$?" != "0" ]; then
echo "[FAIL] Error fetching ip id from PHPIPAM" 1>&2
exit 1
fi
if [ -z "${IPID}" ] || [ "${IPID}" = "null" ]; then
echo "[INFO] address not in phpipam database: ${ip}"
return
fi
NOUPDATE=0
JSON=$(curl -X GET --header "token: ${TOKEN}" ${URL}/${APP}/addresses/${IPID}/ -s)
if [ "$?" != "0" ]; then
echo "[FAIL] Error fetching ip data from PHPIPAM" 1>&2
exit 1
fi
IPTAG=$(echo ${JSON} | jq --raw-output .data.tag)
for tag in ${INVALIDTAGS[@]}; do
if [ "${IPTAG}" = "${tag}" ]; then
echo "[INFO] refusing to update ip with tag: ${IPTAG}"
NOUPDATE=1
fi
done
if [ ${NOUPDATE} -eq 1 ]; then return; fi
IPMAC=$(echo ${JSON} | jq --raw-output .data.mac)
if [ -z "${IPMAC}" ]; then
echo "[INFO] No mac set for ip"
fi
if [ "${IPMAC}" = "${mac}" ]; then
echo "[INFO] no update required for mac"
return
fi
JSON=$(curl -X PATCH --header "token: ${TOKEN}" ${URL}/${APP}/addresses/${IPID}/ -s --data "mac=${mac}")
if [ "$?" != "0" ]; then
echo "[FAIL] Error updating ip mac on PHPIPAM" 1>&2
exit 1
fi
RESULT=$(echo ${JSON} | jq --raw-output .success)
if [ "${RESULT}" != "true" ]; then
echo "[FAIL] API returned error updating ip on PHPIPAM: ${JSON}"
exit 1
fi
echo "[INFO] Updated id:${IPID} ip:${ip} mac:${mac}"
}
while read a b c d e; do
# ? (192.168.1.10) at a1:b2:c3:d4:e5:f6 [ether] on eth0
line="${a} ${b} ${c} ${d} ${e}"
ip=$(echo ${b} | sed 's/[^0-9\.]//g')
mac=${d}
if [ "${mac}" = "<incomplete>" ]; then
# we silently skip these
continue
fi
if ! [[ ${mac} =~ ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$ ]]; then
echo "[INFO] Invalid mac: ${mac}"
continue
fi
echo "[INFO] Found ip:${ip} mac:${mac}"
if [ -z "${ip}" ]; then
echo "[WARN] Unable to parse ip from '${b}': ${line}" 1>&2
fi
if [ -z "${mac}" ]; then
echo "[WARN] Unable to parse mac from '${d}': ${line}" 1>&2
fi
_update ${ip} ${mac}
done < <(arp -an -i ${INTERFACE})
if [ "$?" != "0" ]; then
echo "[FAIL] Error running arp" 1>&2
exit 1
fi
# get json output from ip for local interfaces
IPJSON=$(ip -j a show ${INTERFACE})
if [ "$?" != "0" ]; then
echo "[FAIL] Error running ip a show" 1>&2
exit 1
fi
localmac=$(echo ${IPJSON} | jq --raw-output '.[0].address')
if [[ ${localmac} =~ ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$ ]]; then
LENGTH=$(echo ${IPJSON} | jq --raw-output '.[0].addr_info | length')
for (( i=0; i<${LENGTH}; i++)); do
localip=$(echo ${IPJSON} | jq --raw-output .[0].addr_info[${i}].local)
if [ -z "${localip}" ]; then
echo "[WARN] Unable to parse ip [${i}] from '${IPJSON}'" 1>&2
continue
fi
echo "[INFO] Found interface:${INTERFACE} ip:${localip} mac:${localmac} index:$((${i} +1))/${LENGTH}"
_update ${localip} ${localmac}
done
else
echo "[INFO] Invalid mac from interface: ${localmac}"
fi
#JSON=$(curl -X DELETE --header "token: ${TOKEN}" ${URL}/${APP}/user/ -s)
#if [ "$?" != "0" ]; then
# echo "[FAIL] Error removing token" 1>&2
# exit 1
#fi
#RESULT=$(echo ${JSON} | jq --raw-output .success)
#if [ "${RESULT}" != "true" ]; then
# echo "[FAIL] API returned error when attempting to remove token: ${JSON}"
# exit 1
#fi
#echo "[INFO] Removed token"
Konfiguration
URL='https://phpipam.znil.local/api' APP='ARP-CronJob' TOKEN='dI4iAJlvuo9z78xlCUt5N4ubmy1FPyoL' SUBNET='192.168.0.0/22' INTERFACE='ens33' INVALIDTAGS=("3" "4")
Bei der URL setzt Ihr den Aufruf zu eurer phpIPAM Installation ein.