import os import sys from nautobot.core.settings import * # noqa F401,F403 from nautobot.core.settings_funcs import is_truthy, parse_redis_connection if DATABASES["default"]["ENGINE"].endswith("mysql"): DATABASES["default"]["OPTIONS"] = {"charset": "utf8mb4"} SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "05^)=zgn3ytglmp_iv4@era^e23u3#_wtop-@yeaeazempdy^=") INSTALLATION_METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_INSTALLATION_METRICS_ENABLED", "True")) # --- BF-Netzwerk additions: Golden Config + Nornir (TP21) --- # # Extends the stock config shipped in the base ghcr.io/nautobot/nautobot image # (unchanged above this point) instead of replacing it, so a rollback is just # "point the compose file's image tag back at ghcr.io/nautobot/nautobot:3.1.7". PLUGINS = [ "nautobot_plugin_nornir", "nautobot_golden_config", ] PLUGINS_CONFIG = { "nautobot_plugin_nornir": { "nornir_settings": { # Per-device creds via each Device's SecretsGroup (ap1/ap2 -> "RouterOS # Nornir" group, access_type=Generic to match this class's default -- # see get_device_creds()/_get_access_type_value() in nautobot_secrets.py). # Switched 2026-07-22 from env_vars.CredentialsEnvVars (a single global # NAPALM_USERNAME/PASSWORD pair for the whole fleet) so future devices # (CRS326 etc.) can carry their own credentials. "credentials": "nautobot_plugin_nornir.plugins.credentials.nautobot_secrets.CredentialsNautobotSecrets", "runner": {"plugin": "threaded", "options": {"num_workers": 5}}, }, # nautobot-plugin-nornir 2.0+ dropped PLUGINS_CONFIG["dispatcher_mapping"] # (it now errors on boot if present) -- per-platform dispatcher overrides # moved onto the Platform model itself (network_driver_mappings). The # ALLNET sg8316m custom driver will be wired in there once credentials # are sorted, not here. }, "nautobot_golden_config": { # Backup + Intended-Config + Compliance enabled 2026-07-22 (TP21 follow-up # session) once a Jinja template + Git repo target existed. # # Plan + Deploy enabled 2026-08-13 (TP22 Schritt 3), after backup scrubbing # (ConfigReplace) and compliance were green on all four RouterOS devices. # Two binding governance rules apply -- see docs/teilprojekte.md TP22: # 1. Config Plans ONLY feature-/manual-scoped, never "full intended": # a full push would write the literal `passphrase="<>"` to the # APs (kicking every WLAN client) and `private-key="<>"` to the # core (killing the WireGuard hub). Sections containing the mask are # excluded from any push. # 2. The AP template is never pushed line-by-line to a live device: it # transiently sets vlan-filtering=no, which severs the vlan99 management # path mid-session. Full re-provisioning goes via file upload + /import. # # enable_postprocessing stays OFF on purpose: render_secrets would not fix the # compliance side (the stored intended would keep the un-rendered Jinja # expression -> permanent false positive) and pushing PSKs has no use here. "enable_backup": True, "enable_compliance": True, "enable_intended": True, "enable_sotagg": True, "enable_plan": True, "enable_deploy": True, "enable_postprocessing": False, # REQUIRED for deploy on RouterOS (found the hard way, 2026-08-13): # the default dispatcher resolves to NAPALM because Platform.network_driver_mappings # carries `napalm: ros` -- but napalm-ros is a READ-ONLY driver. Backup (get_config) # works, merge_config does not and fails with an empty error: # NornirNautobotException: E1015: The method merge_config failed ... `` # nornir-nautobot ships a RouterOS-specific Netmiko dispatcher whose merge_config # pushes via netmiko_send_config -- pin it explicitly. Key = network_driver name. "custom_dispatcher": { "mikrotik_routeros": "nornir_nautobot.plugins.tasks.dispatcher.mikrotik_routeros.NetmikoMikrotikRouteros", }, "postprocessing_callables": [], "postprocessing_subscribed": [], "per_feature_bar": True, "per_feature_width": 0.13, "per_feature_height": 4, "default_deploy_status": "Not Approved", "get_custom_compliance": None, "sot_agg_transposer": None, }, } NAPALM_USERNAME = os.getenv("NAUTOBOT_NAPALM_USERNAME", "") NAPALM_PASSWORD = os.getenv("NAUTOBOT_NAPALM_PASSWORD", "") NAPALM_TIMEOUT = int(os.getenv("NAUTOBOT_NAPALM_TIMEOUT", "30"))