From eab11d4a5b96e820f7ed5b6ad22e9c9a586c66f1 Mon Sep 17 00:00:00 2001
From: lilly
Date: Fri, 21 Feb 2025 21:15:20 +0100
Subject: [PATCH 1/2] add script to fetch netbox data and write to local files
---
data/zones/noc.eh22.intern.zone | 6 ++
flake.nix | 6 ++
packages/default.nix | 1 +
packages/fetch-netbox-data/default.nix | 23 ++++++++
.../fetch-netbox-data/fetch-netbox-data.py | 55 +++++++++++++++++++
secrets/passwords.yaml | 7 ++-
6 files changed, 96 insertions(+), 2 deletions(-)
create mode 100644 data/zones/noc.eh22.intern.zone
create mode 100644 packages/fetch-netbox-data/default.nix
create mode 100755 packages/fetch-netbox-data/fetch-netbox-data.py
diff --git a/data/zones/noc.eh22.intern.zone b/data/zones/noc.eh22.intern.zone
new file mode 100644
index 0000000..1f6a657
--- /dev/null
+++ b/data/zones/noc.eh22.intern.zone
@@ -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
diff --git a/flake.nix b/flake.nix
index 766d326..3caf6a3 100644
--- a/flake.nix
+++ b/flake.nix
@@ -84,6 +84,12 @@
ssh-to-age
pre-commit
sops
+ python312
+ python312Packages.pynetbox
+ python312Packages.dnspython
+ python312Packages.ipython
+ # custom packages
+ fetch-netbox-data
];
};
});
diff --git a/packages/default.nix b/packages/default.nix
index 5917dfe..0df9bed 100644
--- a/packages/default.nix
+++ b/packages/default.nix
@@ -2,5 +2,6 @@
{
# add new packages here as:
# name = pkgs.callPackage ./package-source.nix {};
+ fetch-netbox-data = pkgs.callPackage ./fetch-netbox-data { };
installer = flake.outputs.nixosConfigurations.installer.config.system.build.isoImage;
}
diff --git a/packages/fetch-netbox-data/default.nix b/packages/fetch-netbox-data/default.nix
new file mode 100644
index 0000000..7ac6b3a
--- /dev/null
+++ b/packages/fetch-netbox-data/default.nix
@@ -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;
+ };
+}
diff --git a/packages/fetch-netbox-data/fetch-netbox-data.py b/packages/fetch-netbox-data/fetch-netbox-data.py
new file mode 100755
index 0000000..3ff99e3
--- /dev/null
+++ b/packages/fetch-netbox-data/fetch-netbox-data.py
@@ -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()
diff --git a/secrets/passwords.yaml b/secrets/passwords.yaml
index baf6b24..8806649 100644
--- a/secrets/passwords.yaml
+++ b/secrets/passwords.yaml
@@ -1,4 +1,7 @@
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:
root: ENC[AES256_GCM,data:RVv1d/nB9pgcERkujSasoLY+cR3OO3NWxw==,iv:EHkUDxP6XB2JWeDtno2rcVvBQdJ/jmG5HjRjPppfS0A=,tag:obzij0BkGLJoXfUbqWLRjw==,type:str]
hardware:
@@ -24,8 +27,8 @@ sops:
Q0ZGUFBmUWpUYjR5OUwxOUplblZ0SmcKtMl1KoYwPb776zz8FfFnf0s7XlnOLnuU
nXkPxRaDel/3EsLnfhcONRAKTGdleRHAXQVIGHrs/jjnZ2OJgXIzYA==
-----END AGE ENCRYPTED FILE-----
- lastmodified: "2025-02-10T16:13:13Z"
- mac: ENC[AES256_GCM,data:k7lqf+JNpnmbKYjMuu82Q1DPtYsL7jAfwUh8QEjpyq9+Qael1dyV0e1yn/H1prLuZIbebT1rYX6s/MhT3t7Ts88bQHmf/EDyCeOPnRfRctzY1jQPPKbE3Pe7vtEnx5r/DEksi1Jh8vMoqHYcB987WPjAQn27P58UXYJROpqaSwg=,iv:fT9JnWYs8lEjXL3pXHtERRxccGd/ocb6KCc8gGbpBJg=,tag:rMvQoihg53GSNhYiNtypuQ==,type:str]
+ lastmodified: "2025-02-21T18:34:34Z"
+ mac: ENC[AES256_GCM,data:yeMXclT2ZdxHy2CqWQkXVay4EHHq2o8dXF2yXa7q1FKyteRzf0Gve/IQVxH3VXYsGQf3lSdL5EAe3BXmNesWnA5QfTELt2hzgd5nQ6+NTzLDXmi/AW3L4BhzpOoK7UIJ+mG42N4mkYlBe1dUyDBikxevWB3AAzGl7mAF/2io4TQ=,iv:d4g5dWUhFBauR8+4aPGU1hYkhyGsmdGBjgwBMs0HbtA=,tag:oOYKKCwOw/gjqeB/SCdkuQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.4
From d31677b549307770cc21231a44ab2125f85da79d Mon Sep 17 00:00:00 2001
From: lilly
Date: Fri, 21 Feb 2025 21:15:48 +0100
Subject: [PATCH 2/2] configure auth-dns to use netbox-fetched data
---
systems/auth-dns.noc.eh22.intern.nix | 35 ++++++++++------------
systems/sketchy-router.noc.eh22.intern.nix | 6 ++++
2 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/systems/auth-dns.noc.eh22.intern.nix b/systems/auth-dns.noc.eh22.intern.nix
index 1b83f39..1ccfcb2 100644
--- a/systems/auth-dns.noc.eh22.intern.nix
+++ b/systems/auth-dns.noc.eh22.intern.nix
@@ -1,26 +1,15 @@
{
pkgs,
+ lib,
...
}:
let
- noc_eh22_internZone = ''
- $ORIGIN noc.eh22.intern.
- $TTL 3600
-
- ; zone management
- noc.eh22.intern. IN SOA auth-dns.noc.eh22.intern. noc.eh22.esterhegg.eu. (
- 1 ; serial (automatically incremented by knot)
- 7200 ; refresh
- 3600 ; retry
- 3600000 ; expire
- 60 ; negative response caching ttl
- )
- @ IN NS auth-dns
-
- ; A/AAAA records
- proxmox IN A 10.31.210.248
- auth-dns IN A 10.31.210.253
- '';
+ zones = (
+ lib.attrsets.mapAttrs' (name: fileType: {
+ name = name;
+ value = ../data/zones/${name};
+ }) (builtins.readDir ../data/zones)
+ );
knotConf = pkgs.writeText "knot.conf" ''
server:
@@ -48,7 +37,15 @@ in
# enable knot authorative dns server
# ref: https://search.nüschtos.de/?query=services.knot
# https://www.knot-dns.cz/docs/3.4/html/configuration.html
- environment.etc."knot/zones/noc.eh22.intern.zone".text = noc_eh22_internZone;
+ environment.etc = (
+ lib.attrsets.mapAttrs' (name: value: {
+ name = "knot/zones/noc.eh22.intern.zone";
+ value = {
+ source = value;
+ };
+ }) zones
+ );
+
services.knot = {
enable = true;
settingsFile = knotConf;
diff --git a/systems/sketchy-router.noc.eh22.intern.nix b/systems/sketchy-router.noc.eh22.intern.nix
index 3617e67..feeba88 100644
--- a/systems/sketchy-router.noc.eh22.intern.nix
+++ b/systems/sketchy-router.noc.eh22.intern.nix
@@ -69,6 +69,12 @@
id = 300;
subnet = "10.20.25.0/24";
pools = [ { pool = "10.20.25.100 - 10.20.25.254"; } ];
+ reservations = [
+ {
+ hw-address = "bc:24:11:c1:8a:a4";
+ ip-address = "10.20.25.3";
+ }
+ ];
}
];
}