add script to fetch netbox data and write to local files

This commit is contained in:
lilly 2025-02-21 21:15:20 +01:00
parent 5a0cd84dd5
commit eab11d4a5b
Signed by: lilly
SSH key fingerprint: SHA256:y9T5GFw2A20WVklhetIxG1+kcg/Ce0shnQmbu1LQ37g
6 changed files with 96 additions and 2 deletions

View file

@ -0,0 +1,6 @@
$ORIGIN noc.eh22.intern.
@ 0 IN SOA auth-dns noc.eh22.easterhegg.eu. 1 7200 3600 3600000 60
@ 0 IN NS 10.20.25.3.
auth-dns 0 IN A 10.20.25.3
proxmox 0 IN A 10.20.25.1
sketchy-router 0 IN A 10.20.25.2

View file

@ -84,6 +84,12 @@
ssh-to-age ssh-to-age
pre-commit pre-commit
sops sops
python312
python312Packages.pynetbox
python312Packages.dnspython
python312Packages.ipython
# custom packages
fetch-netbox-data
]; ];
}; };
}); });

View file

@ -2,5 +2,6 @@
{ {
# add new packages here as: # add new packages here as:
# name = pkgs.callPackage ./package-source.nix {}; # name = pkgs.callPackage ./package-source.nix {};
fetch-netbox-data = pkgs.callPackage ./fetch-netbox-data { };
installer = flake.outputs.nixosConfigurations.installer.config.system.build.isoImage; installer = flake.outputs.nixosConfigurations.installer.config.system.build.isoImage;
} }

View file

@ -0,0 +1,23 @@
{ python3 }:
python3.pkgs.buildPythonApplication {
name = "fetch-netbox-data";
version = "1.0.0";
src = ./.;
pyproject = false;
propagatedBuildInputs = with python3.pkgs; [
pynetbox
dnspython
];
installPhase = ''
runHook preInstall
install -Dm755 ./fetch-netbox-data.py $out/bin/fetch-netbox-data
runHook postInstall
'';
meta = {
mainProgram = "fetch-netbox-data";
platforms = python3.meta.platforms;
};
}

View file

@ -0,0 +1,55 @@
#!/usr/bin/env python3
import pynetbox
import argparse
from dns import rdatatype
from dns import rdataclass
from dns.rdtypes.ANY.SOA import SOA
from dns.rdtypes.ANY.NS import NS
from dns.rdtypes.IN.A import A
from dns.zone import Zone
from pathlib import Path
def build_auth_dns_zones(nb: pynetbox.api, nox_dir: Path):
zones_dir = nox_dir / "data" / "zones"
zones_dir.mkdir(parents=True,exist_ok=True)
print(f"Fetching IPAM data to build authorative zonefiles in {zones_dir}")
print(f"Building zone noc.eh22.intern")
zonefile_path = zones_dir / "noc.eh22.intern.zone"
# build zone management stuff (SOA record, NS record)
zone = Zone(origin="noc.eh22.intern")
zone.get_rdataset("@", rdtype=rdatatype.SOA, create=True)\
.add(SOA(rdclass=rdataclass.IN, rdtype=rdatatype.SOA, mname="auth-dns.noc.eh22.intern.", rname="noc.eh22.easterhegg.eu.", serial=1, refresh=7200, retry=3600, expire=3600000, minimum=60))
zone.get_rdataset("@", rdtype=rdatatype.NS, create=True)\
.add(NS(rdclass=rdataclass.IN, rdtype=rdatatype.NS, target="10.20.25.3"))
# iterate over all ip addresses with dns names ending in noc.eh22.intern
for i_addr in nb.ipam.ip_addresses.filter("noc.eh22.intern"):
raw_addr = i_addr.address.rsplit("/", maxsplit=1)[0]
relative_name = i_addr.dns_name.removesuffix(".noc.eh22.intern")
if i_addr.family.value == 4:
zone.get_rdataset(relative_name, rdtype=rdatatype.A, create=True)\
.add(A(rdclass=rdataclass.IN, rdtype=rdatatype.A, address=raw_addr))
else:
raise RuntimeError(f"Got unknown IP family {i_addr.family} ({i_addr.family.value})")
with open(zonefile_path, mode="w") as f:
zone.to_file(f, want_comments=True, want_origin=True)
def main():
argp = argparse.ArgumentParser(prog="fetch-netbox-data", description="Fetch current IPAM data from netbox")
argp.add_argument("--base-url", default="https://netbox.eh22.easterhegg.eu", help="URL of the netbox installation")
argp.add_argument("--token", required=True, help="Netbox API Token")
argp.add_argument("--nox-dir", required=True, type=Path, help="Path to the nox repository")
args = argp.parse_args()
nb = pynetbox.api(args.base_url, token=args.token)
build_auth_dns_zones(nb, args.nox_dir)
if __name__ == "__main__":
main()

View file

@ -1,4 +1,7 @@
services: services:
netbox.eh22.easterhegg.eu:
noc: ENC[AES256_GCM,data:OX05HjLYVoMP4My97eijGjWDl+lyTBFa,iv:EDOWfkNZUrFFyrX63LhA4O8lqfmckOHcXRN0qzgn3u4=,tag:AwrwlwGoKih2qkbvmQIGFQ==,type:str]
noc_token: ENC[AES256_GCM,data:7WrIXDtjYKRVgA+r2iVcaT4zf+ftRTEQDEduu77j3RkvSX1e2UCNvg==,iv:B1r+wHg3AJKVj7PKS34G9FD/2Q1yngXdueqVJ0JIfY0=,tag:1w9FO2fPPK0gkInrtEZyBg==,type:str]
proxmox: proxmox:
root: ENC[AES256_GCM,data:RVv1d/nB9pgcERkujSasoLY+cR3OO3NWxw==,iv:EHkUDxP6XB2JWeDtno2rcVvBQdJ/jmG5HjRjPppfS0A=,tag:obzij0BkGLJoXfUbqWLRjw==,type:str] root: ENC[AES256_GCM,data:RVv1d/nB9pgcERkujSasoLY+cR3OO3NWxw==,iv:EHkUDxP6XB2JWeDtno2rcVvBQdJ/jmG5HjRjPppfS0A=,tag:obzij0BkGLJoXfUbqWLRjw==,type:str]
hardware: hardware:
@ -24,8 +27,8 @@ sops:
Q0ZGUFBmUWpUYjR5OUwxOUplblZ0SmcKtMl1KoYwPb776zz8FfFnf0s7XlnOLnuU Q0ZGUFBmUWpUYjR5OUwxOUplblZ0SmcKtMl1KoYwPb776zz8FfFnf0s7XlnOLnuU
nXkPxRaDel/3EsLnfhcONRAKTGdleRHAXQVIGHrs/jjnZ2OJgXIzYA== nXkPxRaDel/3EsLnfhcONRAKTGdleRHAXQVIGHrs/jjnZ2OJgXIzYA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-10T16:13:13Z" lastmodified: "2025-02-21T18:34:34Z"
mac: ENC[AES256_GCM,data:k7lqf+JNpnmbKYjMuu82Q1DPtYsL7jAfwUh8QEjpyq9+Qael1dyV0e1yn/H1prLuZIbebT1rYX6s/MhT3t7Ts88bQHmf/EDyCeOPnRfRctzY1jQPPKbE3Pe7vtEnx5r/DEksi1Jh8vMoqHYcB987WPjAQn27P58UXYJROpqaSwg=,iv:fT9JnWYs8lEjXL3pXHtERRxccGd/ocb6KCc8gGbpBJg=,tag:rMvQoihg53GSNhYiNtypuQ==,type:str] mac: ENC[AES256_GCM,data:yeMXclT2ZdxHy2CqWQkXVay4EHHq2o8dXF2yXa7q1FKyteRzf0Gve/IQVxH3VXYsGQf3lSdL5EAe3BXmNesWnA5QfTELt2hzgd5nQ6+NTzLDXmi/AW3L4BhzpOoK7UIJ+mG42N4mkYlBe1dUyDBikxevWB3AAzGl7mAF/2io4TQ=,iv:d4g5dWUhFBauR8+4aPGU1hYkhyGsmdGBjgwBMs0HbtA=,tag:oOYKKCwOw/gjqeB/SCdkuQ==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.4 version: 3.9.4