Netbox Docker mit SAML2-Plugin
Aus verschiedenen Gründen will ich das Netbox Plugin for SSO using SAML2 in einer Docker-Umgebung ausprobieren. Die Installation ist nicht ganz trivial, darum schreibe ich meine Erlebnisse hier auf.
Die Beschreibung im Netbox Docker Wiki weist den Weg, wie man am schnellsten zum Ziel kommt.. Zunächst heißt es, das Repository zu klonen und in das Verzeichnis zu wechseln:
git clone -b release https://github.com/netbox-community/netbox-docker.git
cd netbox-docker
Anschließend sind einige Dateien anzupassen beziehungsweise neu anzulegen.
Bei Netbox Docker wird sehr viel über Umgebungsvariablen konfiguriert, die ich in der Datei env/netbox.env anpassen kann. Wichtig für das Plugin sind die folgenden Variablen:
REMOTE_AUTH_ENABLED=True
REMOTE_AUTH_BACKEND=netbox.authentication.RemoteUserBackend
REMOTE_AUTH_AUTO_CREATE_USER=True
In der Beschreibung des Plugins steht
bei REMOTE_AUTH_BACKEND noch utilities.auth_backends.RemoteUserBackend
.
Seit Netbox-Version 2.9 lautet der richtige Wert jedoch
netbox.authentication.RemoteUserBackend
.
In der Datei configuration/configuration.py wird das Plugin aktiviert und konfiguriert. Am Ende der Datei habe ich erstmal nur die Änderungen eingetragen, die im README zum Plugin vorgeschlagen werden.
PLUGINS = ['django3_saml2_nbplugin']
PLUGINS_CONFIG = {
'django3_saml2_nbplugin': {
# Use the Netbox default remote backend
'AUTHENTICATION_BACKEND': REMOTE_AUTH_BACKEND,
# Custom URL to validate incoming SAML requests against
'ASSERTION_URL': 'https://netbox.company.com',
# Populates the Issuer element in authn reques e.g defined as "Audience URI (SP Entity ID)" in SSO
'ENTITY_ID': 'https://netbox.conpany.com/',
# Metadata is required, choose either remote url or local file path
'METADATA_AUTO_CONF_URL': "https://mycorp.okta.com/app/sadjfalkdsflkads/sso/saml/metadata"
# or local file path
#'METADATA_LOCAL_FILE_PATH': '/opt/netbox/saml2.xml',
}
}
Bei AUTHENTICATION_BACKEND
wird
auf die Variable REMOTE_AUTH_BACKEND
Bezug genommen,
darum ist es wichtig,
dass die Plugin-Konfiguration nach dieser Variablen
in der Datei configurations.py steht.
Die Variablen ASSERTION_URL
, ENTITY_ID
und METADATA_AUTO_CONF_URL
bestimmen die Kommunikation mit dem SAML2-Identity-Provider
und müssen daher in Abstimmung mit diesem konfiguriert werden.
Dabei ist METADATA_AUTO_CONF_URL
eine URL,
mit der das Plugin sich beim Start von Netbox
die Metadaten für die Authentisierung als XML-Datei abholt.
Alternativ dazu ist es möglich,
diese XML-Datei selbst abzuholen,
im Container zu platzieren
und dann in der Variable METADATA_LOCAL_FILE_PATH
darauf zu verweisen.
METADATA_LOCAL_FILE_PATH
und METADATA_AUTO_CONF_URL
schließen einander aus,
es sollte nur eine der beiden Varianten verwendet werden.
In die Datei plugin_requirements.txt werden die benötigten Python-Module eingetragen:
netbox-plugin-auth-saml2
django3-auth-saml2
Die Datei docker-compose.override.yml wird auch ohne Plugins benötigt.
Da ich die Images für netbox
und netbox-worker
neu bauen muss,
sieht die Datei hier wie folgt aus:
version: '3.4'
services:
nginx:
ports:
- 8000:8080
volumes:
- ./netbox-nginx.conf:/etc/netbox-nginx/nginx.conf:ro
netbox:
build:
context: .
dockerfile: Dockerfile-Plugins
image: netbox:v2.9-plugins
netbox-worker:
image: netbox:v2.9-plugins
Zusätzlich zur einfachen docker-compose.override.yml,
werden hier die Container netbox
und netbox-worker
neu gebaut,
um die benötigten Python-Module zu installieren.
Außerdem bekommt nginx
eine angepasste Konfigurationsdatei,
weil beim SAML2-Plugin ein paar Pfade
beim Zugriff auf netbox
umgelenkt werden müssen.
Die Datei Dockerfile-Plugins ist als dockerfile
für den Bau der Container angegeben.
Diese sieht so aus:
FROM netboxcommunity/netbox:v2.9
RUN apk add --no-cache xmlsec
copy ./plugin_requirements.txt /
RUN pip install --no-warn-script-location -r /plugin_requirements.txt
# see https://github.com/sabnzbd/sabnzbd/issues/1451
# python3.9 gives "AttributeError: module 'base64' has no attribute 'decodestring'"
#
# fixed in pysaml2=5.1.0
#
#RUN sed -i 's/base64.decodestring/base64.decodebytes/g' /usr/local/lib/python3.9/site-packages/saml2/saml.py
#RUN sed -i 's/base64.encodestring/base64.encodebytes/g' /usr/local/lib/python3.9/site-packages/saml2/saml.py
Das SAML2-Plugin benötigt zusätzlich das Binärprogramm xmlsec1
,
dass ich durch Installieren des Software-Pakets xmlsec
mit apk
bekomme.
Danach werden die zusätzlichen Python-Module installiert.
Die auskommentierten Zeilen können
je nach verwendeter Version von Netbox (hier v2.9)
nötig sein oder nicht.
In Version 3.9 von Python
sind die Methoden decodestring
und encodestring
aus dem Modul base64
entfernt worden.
Das Modul pysaml2,
welches automatisch geladen wird,
verwendet in Version 5.0.0 noch die alten Methoden
und ab Version 5.1.0 nicht mehr.
Sollten sich kurz nach dem Start von Netbox Docker
die Container netbox
und/oder netbox-worker
mit der Fehlermeldung
AttributeError: module 'base64' has no attribute 'decodestring'
beenden,
aktiviert man am einfachsten die beiden sed
Befehle.
Mit den folgenden Befehlen werden die Images gebaut und anschließend gestartet:
sudo docker-compose build --no-cache
sudo docker-compose up -d
Laut docker-compose.override.yml sollte die Netbox nun an Port 8000 des Testrechners erreichbar sein.
Unmittelbar nach dem Start einer frischen Netbox wird zunächst die Datenbank initialisiert. In dieser Zeit werden keine Anfragen beantwortet und im Browser bekommt man die Meldung Bad GAteway.
Dauert dieser Zustand länger an, kann man mit folgendem Befehl nachschauen, ob alle Container laufen:
sudo docker-compose ps
Hat sich ein Container vorzeitig beendet, sieht die Ausgabe etwa so aus:
Name Command State Ports
--------------------------------------------------------------------------------------------------------------------------------
netbox-docker_netbox-worker_1 python3 /opt/netbox/netbox ... Exit 1
netbox-docker_netbox_1 /opt/netbox/docker-entrypo ... Up
netbox-docker_nginx_1 /docker-entrypoint.sh ngin ... Up 80/tcp, 0.0.0.0:8000->8080/tcp,0.0.0.0:32773->8080/tcp
netbox-docker_postgres_1 docker-entrypoint.sh postgres Up 5432/tcp
netbox-docker_redis-cache_1 docker-entrypoint.sh sh -c ... Up 6379/tcp
netbox-docker_redis_1 docker-entrypoint.sh sh -c ... Up 6379/tcp
In diesem Fall hilft oft, die Logs anzuschauen, um zu sehen, wie man das Problem beheben kann:
sudo docker-compose logs netbox-worker|less -r
Die Ausgabe hier zeigt,
dass manage.py
sich mit einer Fehlermeldung beendet hatte:
Attaching to netbox-docker_netbox-worker_1
netbox-worker_1 | 🧬 loaded config '/etc/netbox/config/configuration.py'
netbox-worker_1 | 🧬 loaded config '/etc/netbox/config/configuration.py'
netbox-worker_1 | 🧬 loaded config '/etc/netbox/config/extra.py'
netbox-worker_1 | Traceback (most recent call last):
netbox-worker_1 | File "/opt/netbox/netbox/manage.py", line 10, in <module>
netbox-worker_1 | execute_from_command_line(sys.argv)
...
netbox-worker_1 | File "/usr/local/lib/python3.9/site-packages/saml2/saml.py", line 90, in <module>
netbox-worker_1 | _b64_decode_fn = getattr(base64, 'decodebytes', base64.decodestring)
netbox-worker_1 | AttributeError: module 'base64' has no attribute 'decodestring'
In diesem Fall sind
die beiden sed
Befehle nötig,
die oben am Ende der Datei Dockerfile-Plugins stehen.
Ist das Problem behoben und Netbox Docker einsatzbereit, kann man sich dem Test der Authentisierung mit SAML2 widmen.
Für den produktiven Einsatz muss auf jeden Fall noch ein Container für die Verschlüsselung des HTTP-Datenverkehrs vorgeschaltet werden. Das ist ein anderes Thema.
Posted 2021-01-12