NetBox und Ansible

NetBox und Ansible

NetBox als Werkzeug zur Dokumentation von IT-Infrastrukturen kann ich nur wärmstens empfehlen.

Warum NetBox, was es alles kann und wie daraus irgendwann vielleicht sogar eine Source of Truth für weitere Automatisierung wird, überspringe ich an dieser Stelle bewusst. Dazu kommen wir noch.

Diesmal springen wir direkt ins kalte Wasser:

  • Grundinstallation von NetBox
  • etwas Hardening
  • Authentifizierung und Berechtigungen
  • Grundstruktur
  • Device Types
  • Geräte hinzufügen
  • ein paar Gedanken zu Variablen
  • Daily Business & Struktur

Spoiler: Fast alles technische davon wird bei mir mit Ansible erledigt. Und ich gehe darauf nicht genauer ein oder zeige Rollen oder Playbooks.

Grundinstallation

Meine NetBox (reines Lab) läuft als Docker-Container auf einem Debian-Server.

Nach einer sehr überschaubaren Debian-Grundinstallation übernehmen einige Ansible-Rollen den Rest:

  • Linux-Basiskonfiguration und Hardening
  • SSH-Konfiguration
  • Firewall
  • Docker
  • NGINX
  • anschließend NetBox selbst

NGINX dient dabei als zentrales Gateway für meine Container – aktuell unter anderem NetBox und Checkmk.

Ich kann den Labserver im Zweifelsfall planieren, neu installieren und den Großteil der Umgebung wieder aus Ansible herstellen.

Ein wenig Hardening

Das Betriebssystem selbst bekommt die üblichen Maßnahmen spendiert: Firewall, SSH-Keys, eingeschränkter SSH-Zugang und dergleichen.

Interessanter wird es beim API-Zugriff.

Für meine Automation gibt es einen zusätzlichen NGINX-Listener, der ausschließlich auf Loopback erreichbar ist. Der Zugriff erfolgt über einen Jump Host beziehungsweise SSH-Tunnel.

Vereinfacht:

Ansible
   │
   └── SSH / Jump Host
           │
           └── interner NGINX API Gateway
                    │
                    └── NetBox

NetBox selbst bleibt für Benutzer natürlich per HTTPS erreichbar.

Eine kleine Lektion gab es dabei auch: Die öffentliche NetBox-API einfach vollständig zu blockieren ist keine besonders gute Idee.

Die Weboberfläche von NetBox verwendet die API selbst, beispielsweise für dynamische Dropdowns bei Device Roles, Manufacturers und ähnlichen Feldern.

Das Ergebnis einer allzu ambitionierten NGINX-Regel war daher:

Manufacturer: No results found
Device Role: No results found

Security-Hardening kann also auch sehr effektiv gegen den Administrator selbst sein.

Für die Automation bleibt trotzdem der interne Weg bestehen. API-Tokens werden zusätzlich möglichst restriktiv behandelt.

Authentifizierung und Berechtigungen

Hier gibt es natürlich viele mögliche Varianten.

Ich habe mich für Microsoft Entra ID entschieden, schlicht weil es für meine Umgebung am besten passt.

Die Anmeldung erfolgt via OAuth2/OIDC. Auf Entra-Seite werden Gruppen gepflegt, die anschließend auf NetBox-Gruppen gemappt werden.

In NetBox gibt es beispielsweise Gruppen wie:

sec_entra_global_admin_rw
sec_entra_global_admin_ro

und dazu entsprechende Permissions:

perm_global_admin_rw
perm_global_admin_ro

Das Ganze bildet man am besten in einem eigenen Vars-File ab.

Ein Benutzer, der Mitglied der entsprechenden Entra-Gruppe ist, kann sich anmelden. Sein NetBox-Account wird automatisch erzeugt und über das Group Mapping mit den vorgesehenen Rechten ausgestattet.

Entfällt die entsprechende Gruppenzugehörigkeit, bekommt er keinen Zugang mehr.

MFA kommt dabei ganz normal aus der Microsoft-Welt.

Zusätzlich bleiben lokale NetBox-Accounts möglich – beispielsweise als Break-Glass-Zugang oder für technische Accounts.

Ein Punkt bleibt offen: Alte automatisch angelegte Benutzer bleiben zunächst in NetBox bestehen. Für eine produktive Umgebung würde ich dafür irgendwann einen Lifecycle-Task bauen, der Benutzer ohne gültige Zuordnung beispielsweise deaktiviert. Für mein Lab war meine Motivation dafür bisher überschaubar.

Auch diese Konfiguration steckt natürlich wieder in Ansible.

Ein relativ neues Konzept ist das Ownership https://netboxlabs.com/blog/netbox-object-owner-functionality/. Das sei hier mal nur erwähnt, die Administration würde analog funktionieren. Hier geht es aber nur begrenzt um inhaltiche Netbox Themen.

Zusammenfassung:

  • Authentifizierung via MS365
  • Authorisierung in der Netbox (group-mapping zu MS365 Gruppen)
  • Verwaltung via ansible

Die Grundstruktur von NetBox

Sites, Locations, Device Roles, Rack Roles, Tags, Custom Fields, Permissions und ähnliche Grundlagen möchte ich nicht jedes Mal von Hand anlegen.

Diese Struktur kommt bei mir aus Ansible.

Zum Beispiel:

Region
└── Site
    └── Location
        └── Rack
            └── Device

Dazu kommen Tenants, Rollen, Tags und Custom Fields.

Das ist am Anfang ein wenig Spielerei und durchaus Aufwand. Sobald das Gerüst aber steht, lässt es sich angenehm erweitern und – noch wichtiger – reproduzierbar wiederherstellen.

Device Types

Etwas spannender sind Device Types.

Ich möchte nicht selbst anfangen, sämtliche Maße, Interfaces, Power Ports und sonstigen Eigenschaften von Firewalls, Switches oder Servern abzutippen.

Dafür gibt es erfreulicherweise die NetBox Community Device Type Library:

netbox-community/devicetype-library

Auch deren Import habe ich in eine Ansible-Rolle gepackt.

Im Wesentlichen definiere ich nur noch, welche Hersteller mich interessieren:

netbox_devicetype_library_vendors:
  - HPE
  - APC
  - Fortinet

Okay.

Und ein paar andere Variablen.

Aber das Prinzip stimmt: Die Rolle holt die Library und importiert die gewünschten Hersteller nach NetBox.

Die große Lüge: man kommt damit aus und alles ist super. Nein, man wird noch genug an Device Types selbst pflegen müssen.

Stolpersteine:

Das war übrigens einer jener Punkte, an denen ich gelernt habe, dass man einen Importer durchaus so aggressiv konfigurieren kann, dass NetBox kurzzeitig die Lust am Leben verliert.

Seitdem: Hersteller nacheinander importieren, Healthchecks dazwischen und ein wenig Geduld.

Automatisierung bedeutet schließlich nicht zwingend, alles gleichzeitig zu tun.

Geräte hinzufügen

Damit kommen wir irgendwann zum eigentlichen Objekt der Begierde.

Das Device selbst wird ebenfalls durch eine Ansible-Rolle grundlegend angelegt.

Ein Teil der Informationen kommt aus Gruppenvariablen, ein kleiner Teil muss zwangsläufig am jeweiligen Gerät definiert werden.

Beispielsweise:

netbox_device_enabled: true

netbox_device_site: <site>
netbox_device_tenant: <tenant>
netbox_device_location: <locaction>

netbox_device_rack: <rackname>
netbox_device_position: <HE>
netbox_device_face: front

netbox_device_role: Firewall
netbox_device_type: fortinet-fg-60f

netbox_device_status: active

Der Gerätename kann direkt aus dem Ansible-Inventory übernommen werden. Die Variablen werden auf unterschiedliche groups_vars verteilt.

Damit weiß NetBox bereits:

welches Gerät
welcher Kunde
welcher Standort
welcher Raum
welches Rack
welche HE
welcher Device Type
welche Rolle

Für die Grundanlage reicht das schon erstaunlich weit.

Ein paar Worte zu Variablen

Ansible dokumentiert Inventory, group_vars und host_vars hervorragend. Eigentlich müsste ich dazu gar nichts schreiben.

Tue ich trotzdem.

Ein mögliches Inventory könnte beispielsweise Gruppen wie diese enthalten:

server_mgmt
server_docker
org_x
org_y
firewalls

In group_vars landen die allgemeinen Eigenschaften:

org_x
→ Kundendaten

firewalls
→ Firewall-spezifische Defaults

server_mgmt
→ NetBox-/Checkmk-Infrastruktur

In host_vars bleiben dann möglichst nur tatsächlich gerätespezifische Werte.

Das klingt einfach, bis ein Playbook plötzlich im Kontext einer Firewall läuft und man dort eine Variable benötigt, die eigentlich beim Management-Server definiert ist.

Genau dann merkt man, dass Ansible-Variablen zwar simpel aussehen, man sich über deren Scope aber trotzdem ein paar Gedanken machen sollte.

Ich habe mich beispielsweise entschieden, den verwendeten Management-Host im Playbook auszuwählen und dessen Variablen gezielt über hostvars zu verwenden.

So bleibt für mich nachvollziehbar, woher die Daten kommen. Keine Gewährleistung, dass das der schlauste Weg war.

Natürlich gehören Secrets in Ansible Vault – API-Tokens, Passwörter, SNMP-Communities und alles, was sonst nicht im Klartext in Git auftauchen sollte.

Bei größeren Umgebungen würde ich außerdem mehrere Vaults beziehungsweise vault-id verwenden.

Und auch bei normalen Variablen lohnt sich etwas Ordnung:

netbox_structure.yml
netbox_locations.yml
netbox_permissions.yml
netbox_vault.yml

Nicht weil Ansible das verlangt.

Sondern weil ich später noch verstehen möchte, was ich da eigentlich gebaut habe.

Daily Business & Datenhoheit

Bis hierher ist alles wunderbar.

Ansible baut Strukturen auf, NetBox wird befüllt und die Welt ist in Ordnung.

Leider ist Infrastruktur-Dokumentation kein Selbstzweck. Irgendwann arbeiten tatsächlich Menschen damit. Verdammt!

Und dann kommt die entscheidende Frage:

Wer besitzt welche Daten?

Wenn Ansible ein Feld verwaltet und ein Techniker dasselbe Feld manuell in NetBox ändert, gewinnt beim nächsten Lauf vermutlich Ansible.

Das kann gewollt sein. :-). Oder ausgesprochen lästig.

Selbstredend kann man viel mit Berechtigungen lösen, aber es wird immer Globale Admins geben, die das Recht haben was an der Struktur zu ändern. Empfehlung: So viel wie möglich an Struktur sollte automatisiert aus ansible kommen, Admins dazu zwingen ansible zu verwenden – man vermeidet zumindest ein wenig Saustall (Tags, Custom Fields, …). Aber auch inhaltliche Daten können aus der Automatisierung kommen und in der netbox abgebildet werden – wo aber sowohl User als auch Admins Zugriff haben.

Empfehlung: Erstelle eine Ownership Matrix und lebe mit einem hybriden Modell. Und erstelle ggf ein Tag für ansible-created.

BereichOwnership
Regions, Sites, LocationsAnsible
TenantsAnsible
Device RolesAnsible
Rack Roles / Rack TypesAnsible
Tags / Custom FieldsAnsible
Permissions / GruppenAnsible
Grundanlage eines DevicesAnsible
Patchungen / KabelNetBox
Fotos / operative DokumentationNetBox
Kommentare / Review-TagsNetBox
Laufende Änderungen durch TechnikerNetBox
uswusw

Das ist ausdrücklich keine allgemeingültige Wahrheit oder gar vollständig.

Gerade bei Dingen wie Rackposition, Seriennummer oder Standort muss jede Organisation selbst entscheiden, wer die Hoheit darüber hat. Möglicherweise werden diese auch gar nicht abgebildet oder kommen automatisiert aus anderen Systemen.

Bei mir kristallisiert sich aber immer mehr eben ein hybrides Modell heraus:

Ansible baut das Gerüst und setzt Standards. NetBox ist anschließend das operative Werkzeug für die tägliche Dokumentation. Überschneidungen müssen transparent kommuniziert oder markiert werden.

Fazit

NetBox und Ansible spielen sehr gut zusammen.

Ansible sorgt dafür, dass die Grundstruktur reproduzierbar, konsistent und reviewbar ist.

NetBox wiederum bleibt dort stark, wo es hingehört: als Werkzeug für Menschen, die Infrastruktur dokumentieren und täglich damit arbeiten.