Oxidized | Collecteur de configuration des équipements réseaux

Sommaire

Introduction

Oxidized est un projet lancé par ytti en Avril 2013.
Il a pour objectif de récupérer, de versionner et de gérer les configurations de vos équipement réseau. C’est un remplaçant de RANCID (Really Awesome New Cisco confIg Differ).

Oxidized se divise en trois paquets :

  • oxidized (core, codé en Ruby et Bash)
  • oxidized-script (CLI et Librairie permettant l’interaction entre les équipements réseaux et Oxidized, codé en Ruby)
  • oxidized-web (Interface web et API pour oxidized, codé en JavaScript, Ruby, HTML et CSS)

NB : « L’interface web » fournit par le module Oxidized-web était initialement destiné à un usage type API et ne fournit aucune sécurité pour l’usage de celle-ci. Néanmoins, si vous ne posséder pas d’outil capable d’exploiter cette outil (ex : librenms) vous voudrez surement renforcer l’accès par l’ajout d’une authentification. Ce point sera abordé dans le chapitre « Configuration avancée Oxidized-web »

Oxidized est compatible avec plusieurs systèmes GNU/Linux. (Ubuntu, Debian, CentOS, Oracle Linux, Red Hat Linux) et avec un bon nombre d’équipements/OS réseaux.

Dans cet article, nous verrons comment implémenter Oxidized afin qu’il réponde au cahier des charges suivants :

  • Récupération des configurations
  • Gestion des versions avec Git
  • Mise en place de rapport par mail
  • Ajout d’une authentification LDAP à l’interface Web

Installation et configuration Oxidized

Pré-requis

Oxidized nécessite l’installation des paquets suivant :

sudo apt-get install –y ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libssh2-1-dev

Si vous souhaitez procéder à la configuration avancé d’Oxidized-web, les paquets suivants seront nécessaires :

sudo apt-get install –y libicu-dev zlib1g-dev g++

Si vous souhaitez implémenter l’envoi de notifications par mail, pensez à installer un client SMTP :

sudo apt-get install -y mailutils

Création de l’utilisateur Oxidized. Au lancement de la commande, Oxidized s’installe dans son répertoire « home ».

sudo useradd -md /etc/oxidized -s /bin/bash oxidized

Oxidized

Installation

Pour installer Oxidized, connectez-vous en tant qu’Oxidized et lancer la commande « oxidized »

sudo su - oxidized
oxidized

L’arborescence suivante devrait alors se générer :

/
└── etc/
	└── oxidized/
		└── .config/
			└── oxidized/
				├── config
				├── crash
				├── extra/
				├── logs/
				├── oxidized.git/
				├── pid
				└── router.db

Explication des fichiers et répertoires :

  • Config = fichier de configuration Oxidized
  • Crash = journaux d’événements d’échec de l’application
  • Extra = répertoire contenant des scripts complémentaires
  • Logs = répertoire contenant les journaux d’événements
  • Oxidized.git = répertoire git contenant les différentes versions de configuration
  • Pid = permet d’identifier le numéro du processus en cours
  • Router.db = fichier contenant la liste des équipements à sauvegarder

Le répertoire « Extra » n’est pas créé automatiquement. Fermer Oxidized et se déconnecter de la session Oxidized.

sudo mkdir /etc/oxidized/.config/oxidized/extra

Pour activer les alertes par mail, vous devrez copier le fichier suivant :

sudo cp /var/lib/gems/2.5.0/gems/oxidized-0.26.3/extra/oxidized-report-git-commits /etc/oxidized/.config/oxidized/extra

Exécuter Oxidized en tant que service

Un script systemd est mis à disposition dans les répertoires du moteur Oxidized :

sudo cp /var/lib/gems/2.5.0/gems/oxidized-0.26.3/extra/oxidized.service /lib/systemd/system

Après avoir copier les différents fichiers, mettez à jour les droits :

sudo chown -R oxidized:oxidized /etc/oxidized/.config/oxidized
sudo chmod -R 750 /etc/oxidized/.config/oxidized

Lancer Oxidized au démarrage du système :

sudo systemctl enable oxidized

Configuration Oxidized

Description du fichier de configuration Oxidized :

  • username et password : sont les valeurs à utiliser par défaut pour se connecter à un équipement (utilisé si non renseigner dans le router.db)
  • model : est le modèle par défaut à utiliser pour récupérer la configuration d’un équipement (utilisé si non renseigner dans le router.db)
  • resolve_dns : active la résolution DNS (sert notamment pour afficher l’adresse IP de l’équipement dans l’interface web)
  • interval : correspond à l’intervalle de temps, en seconde, entre chaque mise à jour des configurations des équipements réseaux
  • use_syslog : Utilise syslog pour l’enregistrement des journaux
  • debug : active le mode debug
  • threads : correspond au nombre de threads utilisés par Oxidized dans sa tâche de récupération des configurations. Ici, il faut définir la valeur maximale. Cette valeur entre en vigueur uniquement à la fin du premier job se terminant avec succès
  • timeout : correspond au temps en secondes à partir duquel Oxidized considère que le job de récupération des configuration doit s’arrêter. NB : si vous utiliser Oxidized pour récupérer les configurations de pare-feu tel que Fortinet, cette valeur doit être revue à la hausse dû à la longueur des configuration de ces équipements
  • retries : correspond au nombre d’essaie à effectuer en cas d’échec d’un job Oxidized
  • prompt : correspond au prompt par défaut qu’Oxidized doit détecter pour considérer qu’il est connecté à un équipement. S’il ne détecte pas le prompt, il ne pourra pas récupérer la configuration. Le prompt doit être exprimé en ruby
  • rest : adresse et port d’écoute d’Oxidized-web
  • next_adds_job : si activé, permet grâce à l’interface web, de passer un équipement en haut de la liste d’attente des jobs. Peut être utile dans le cas où de nombreux équipements sont en attentes de récupération et que vous souhaitez mettre à jour rapidement la configuration d’un équipement dans Oxidized
  • vars : permet d’ajouter des variables qu’Oxidized devra utiliser. Par exemple, vous ajouter le mot de passe « enable » des équipements cisco
vars:
   enable: secretPassword
  • groups : permet de classer les équipements par groupe. Par exemple, on peut classer par type d’équipements (switch , router, ap…) ou par fonction (border, core, access…). Vous pouvez définir par group un login et mot de passe à utiliser par défaut
groups:
    border:
       username: borderUsername
       password: borderPassword
    core:
       username: coreUsername
       password: corePassword
  • models : permet de définir un utilisateur et un mot de passe à utiliser par défaut selon le modèle utilisé et donc selon la marque ou de l’OS de l’équipement.
models:
    junos:
       username: juniper
       password: mxIsCool
    cisco:
       username: cisco
       password: 2960willNeverDie
...
  • pid : permet de renseigner le chemin du fichier où Oxidized doit écrire le numéro du processus qui exécute Oxidized
  • crash : permet de définir la localisation des fichiers en cas de crash de l’application
  • input : permet de définir la méthode de connexion à un équipement (ssh, telnet)
  • output : permet de définir le support de sortie des configurations (file, git, git-crypt, http)
  • source : permet de définir la source contenant la liste des équipements à sauvegarder (csv, sql, mysql, sqlite, http)
    • Dans le cas du CSV, vous devez définir comment il doit être interprété par Oxidized. Dans map, vous devez définir l’entête du fichier CSV
source:
    default: csv
    csv:
        map:
            name: 0
            model: 1
            username: 2
            password: 3
# Ce qui donnera dans le routed.db
myhost.domain.tld:cisco:user:passwd
  • hooks : permet d’ajouter des fonctionnalités à Oxidized comme par exemple, l’envoi de mail à la fin d’un jobs utilisant git
    • events : permet de définir le type d’événement pour lequel Oxidized enverra un email :
      • node_fail : envoi un mail en cas d’échec de récupération de la configuration d’un équipement
      • post_store : envoi un mail en cas de mise à jour de la configuration d’un équipement
  • model_map : permet de définir les modèles et les scripts associés pour la récupération des configurations par Oxidized. Un modèle doit être déclaré comme ci-après. La liste des scripts est disponible ici et est disponible sur votre serveur à ce chemin : /var/lib/gems/2.5.0/gems/oxidized-0.26.3/extra/
    • nom: nomDuScript
    • cisco: ios

Exemple de configuration que vous pourriez avoir :

---
username: admin
password: admin
model: iso
resolve_dns: true
interval: 43200
use_syslog: true
debug: false
threads: 30
timeout: 300
retries: 2
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
rest: 127.0.0.1:8888
next_adds_job: true
vars: {}
groups: {}
models: {}
pid: "/etc/oxidized/.config/oxidized/pid"
crash:
    directory: "/etc/oxidized/.config/oxidized/crashes"
    hostnames: false
stats:
    history_size: 10
input:
    default: ssh, telnet
    debug: false
    ssh:
        secure: false
    ftp:
        passive: true
    utf8_encoded: true
output:
    default: git
    git:
        user: oxidized
        email: oxidized@example.com
        repo: "/etc/oxidized/.config/oxidized/oxidized.git"
source:
    default: csv
    csv:
        file: "/etc/oxidized/.config/oxidized/router.db"
        delimiter: !ruby/regexp /:/
        map:
            name: 0
            model: 1
            username: 2
            password: 3
        gpg: false
hooks:
    email_output:
        type: exec
        events: [node_fail,post_store]
        cmd: '/etc/oxidized/.config/oxidized/extra/oxidized-report-git-commits | mail -s "Oxidized updates for ${OX_NODE_NAME}" -a "FROM:oxidized
@example.com" support-it@example.com'
        async: true
        timeout: 120
model_map:
    cisco: ios
    fortigate: fortios

Une fois la configuration terminée, lancer Oxidized à l’aide de la commande suivante :

sudo systemctl start oxidized

Configuration avancée Oxidized-web

Comme je le disais précédemment, Oxidized-web a été créé à la base pour un usage de type API. Certains voudront surement s’en servir pour consulter les configurations de leurs équipements via une interface web.

Oxidized-web ne fournit pas par défaut de système d’authentification, rendant l’accès à l’information très facile pour n’importe qui.

Vous trouverez donc ci-après un moyen d’ajouter une authentification basé sur Active Directory par l’installation de Nginx en tant que reverse proxy. Bien entendu, il sera nécessaire de vous baser sur le protocole HTTPS pour l’accès à la page web.

L’implémentation d’authentification n’est pas native dans Nginx. Néanmoins, il existe un module permettant de répondre à notre besoin. Nous allons donc devoir recompiler Nginx pour ajouter le module à ce dernier. Commençons…

Téléchargement du module nginx-auth-ldap :

cd /tmp
sudo git clone https://github.com/kvspb/nginx-auth-ldap.git
cd nginx-auth-ldap

A la rédaction de l’article, il existe un bug dans l’utilisation du module et de l’authentification LDAP selon l’appartenance à un groupe. Pour cela, on restaure une version précédente.

sudo git checkout 5fd5a40851d8b7c1ba832b893d369a51825ff720

Préparation de Nginx :

cd /tmp
# Installation des dépendances
sudo apt-get install -y libldap2-dev libssl-dev libpcre3-dev
# Téléchargement de Nginx
sudo wget http://nginx.org/download/nginx-1.17.4.tar.gz
# Décompression et désarchivage de Nginx
tar -xvzf nginx-1.17.4.tar.gz
# Préparation de Nginx pour la compilation
cd nginx-1.17.4
sudo ./configure --user=www-data --group=www-data --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_gzip_static_module --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-file-aio --with-http_realip_module --add-module=/tmp/nginx-auth-ldap/ --with-debug
# Compilation
sudo make
# Installation
sudo make install

Création du service Nginx :

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

Activer Nginx et lancement de ce dernier au démarrage du système :

sudo systemctl enable nginx
sudo systemctl start nginx

Enfin, il ne reste plus qu’à configurer Nginx en tant que reverse proxy en ajoutant le fichier de configuration suivant :

worker_processes 1;
	events {
		worker_connections 1024;
	}
http {
	include mime.types;
	default_type application/octet-stream;
	sendfile on;
	keepalive_timeout 65;
	gzip on;
	
	##
	# LDAP
	##
	auth_ldap_cache_enabled on;
	auth_ldap_cache_expiration_time 1800;
	auth_ldap_cache_size 1000;
	ldap_server DC1 {
		url "ldap://dc1.ad.corp.tld/OU=Users,OU=Corporation,DC=ad,DC=corp,DC=tld?sAMAccountName?sub?(objectClass=person)";
		binddn "CN=svc-oxidized,OU=IT,OU=Corporation,DC=ad,DC=corp,DC=tld";
		binddn_passwd "svc-oxidizedPassword";
		group_attribute "member";
		group_attribute_is_dn on;
		require group "CN=GG-OXIDIZED,OU=Groupes,OU=IT,OU=Corporation,DC=ad,DC=corp,DC=tld";
		require valid_user;
		satisfy all;
	}
	ldap_server DC2 {
		url "ldap://dc2.ad.corp.tld/OU=Users,OU=Corporation,DC=ad,DC=corp,DC=tld?sAMAccountName?sub?(objectClass=person)";
		binddn "CN=svc-oxidized,OU=IT,OU=Corporation,DC=ad,DC=corp,DC=tld";
		binddn_passwd "svc-oxidizedPassword";
		group_attribute "member";
		group_attribute_is_dn on;
		require group "CN=GG-OXIDIZED,OU=Groupes,OU=IT,OU=Corporation,DC=ad,DC=corp,DC=tld";
		require valid_user;
		satisfy all;
	}

	##
	# Site
	##
	server {
		listen 80 default_server;
		server_name oxidized.ad.corp.tld;
		return 301 https://$host$request_uri;
	}
	server {
		listen 443 ssl;
		server_name oxidized.ad.corp.tld;
		ssl_certificate /etc/ssl/crt/201911-oxidized.ad.corp.tld.crt;
		ssl_certificate_key /etc/ssl/private/oxidized.ad.corp.tld.key;
		ssl_session_cache shared:SSL:1m;
		ssl_session_timeout 5m;
		location / {
			auth_ldap "Veuillez vous connecter : ";
			auth_ldap_servers DC1;
			auth_ldap_servers DC2;
			proxy_pass http://127.0.0.1:8888/;
	}
	error_page 500 502 503 504 /50x.html;
	location = /50x.html {
		root html;
		}
	}
}

Explication de l’essentiel de la configuration :

  • url : lieu de recherche de l’utilisateur souhaitant s’authentifier
  • binddn : identifiant du compte de service exécutant la requête LDAP
  • binddn_passwd : mot de passe du compte de service exécutant la requête LDAP
  • group_attribute : l’attribut de groupe que devra posséder l’utilisateur
  • group_attribute_is_dn : activer la fonction d’appartenance à un groupe pour l’authentification
  • require group : condition d’appartenir au groupe (renseigner le DN du groupe)
  • require valid_user : condition d’utiliser des identifiants validés lors de la requête LDAP
  • satisfy : correspond aux conditions à réunir pour autoriser la connexion (ALL=AND ; ANY=OR)

NB : Dans cette configuration j’ai préalablement configuré l’accès à Oxidized-web via HTTPS avec une redirection de HTTP vers HTTPS. Vous pouvez aussi activer HSTS.

About: gmillour