296 lines
12 KiB
Markdown
296 lines
12 KiB
Markdown
|
|
# 🤖 AGENTS.md
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
# 🤖 AGENTS.md - Network Config Backup Plugin for GLPI 11
|
||
|
|
|
||
|
|
> **Documento di contesto per AI Agent / Assistente di sviluppo**
|
||
|
|
> **Progetto**: `glpi-plugin-netconfig`
|
||
|
|
> **Ultimo aggiornamento**: 2026-05-22
|
||
|
|
> **GLPI Target**: 11.0.6+ | **PHP**: 8.2+ | **Database**: MySQL/MariaDB
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 Obiettivo del Progetto
|
||
|
|
|
||
|
|
Sviluppare un plugin GLPI 11 che permetta di:
|
||
|
|
1. **Salvare configurazioni** di apparati di rete (switch, router, firewall) nel database MySQL di GLPI
|
||
|
|
2. **Tracciare le variazioni** delle configurazioni nel tempo (versioning con hash SHA256)
|
||
|
|
3. **Visualizzare differenze** (diff) tra versioni successive
|
||
|
|
4. **Esportare configurazioni** in file di testo (con controllo diritti e redaction credenziali)
|
||
|
|
5. **Lanciare il recupero configurazioni** tramite massive actions o trigger manuali
|
||
|
|
6. **Integrare GLPI Agent remoto** per l'esecuzione distribuita del backup via SSH (netmiko/napalm)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🧠 Contesto Tecnico Chiave
|
||
|
|
|
||
|
|
### Stack Tecnologico
|
||
|
|
| Componente | Versione/Nota |
|
||
|
|
|------------|--------------|
|
||
|
|
| GLPI | 11.0.6+ (CLI: `php bin/console glpi:version`) |
|
||
|
|
| PHP | 8.2+ con strict_types, namespace PSR-4 |
|
||
|
|
| Database | MySQL/MariaDB, InnoDB, utf8mb4_unicode_ci |
|
||
|
|
| Composer | 2.7.1+ (cache Packagist OK) |
|
||
|
|
| Template Engine | Twig 3 (nativo in GLPI 11) |
|
||
|
|
| Crittografia | `Glpi\Toolbox\Encryption` (AES-256-GCM) |
|
||
|
|
| Diff Engine | `symfony/diff` ^6.4 |
|
||
|
|
| HTTP Client | `guzzlehttp/guzzle` ^7.8 (opzionale per agent PHP) |
|
||
|
|
| Agent Script | Python 3 + netmiko + requests + pyyaml |
|
||
|
|
|
||
|
|
### Architettura Plugin
|
||
|
|
```
|
||
|
|
plugins/netconfig/
|
||
|
|
├── setup.php # Hook init, versioning, diritti
|
||
|
|
├── hook.php # Install/uninstall DB
|
||
|
|
├── composer.json # Dipendenze + autoload PSR-4
|
||
|
|
├── install/mysql/install.sql # Schema tabella configs
|
||
|
|
├── src/
|
||
|
|
│ ├── Config.php # CommonDBTM: CRUD, massive actions, diff
|
||
|
|
│ ├── Agent/Receive.php # Endpoint API per agent
|
||
|
|
│ └── Api/GlpiApiClient.php # Client REST API GLPI (opzionale)
|
||
|
|
├── ajax/
|
||
|
|
│ ├── export.php # Download sicuro configurazioni
|
||
|
|
│ └── agent_receive.php # Fallback endpoint agent
|
||
|
|
├── templates/config_tab.html.twig # Vista tab GLPI con storico
|
||
|
|
└── locales/ # Traduzioni it_IT/en_GB
|
||
|
|
```
|
||
|
|
|
||
|
|
### Flusso Dati Principale
|
||
|
|
```
|
||
|
|
[Apparato di Rete]
|
||
|
|
│
|
||
|
|
▼ (SSH via netmiko)
|
||
|
|
[GLPI Agent Python] ──(POST JSON)──► [Plugin Endpoint]
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
[Validazione Token + Hash]
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
[Cifratura + Salvataggio DB]
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
[Notifica UI GLPI + Diff]
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔑 Decisioni Architetturali Critiche
|
||
|
|
|
||
|
|
### ✅ Scelte Confermate
|
||
|
|
1. **Namespace PSR-4**: `PluginNetconfig\` mappato su `src/` (obbligatorio GLPI 11)
|
||
|
|
2. **Cifratura nativa**: Uso di `Glpi\Toolbox\Encryption` invece di soluzioni custom
|
||
|
|
3. **Versioning via hash**: SHA256 su contenuto config per rilevamento modifiche
|
||
|
|
4. **Massive actions native**: Integrazione con sistema GLPI invece di UI custom
|
||
|
|
5. **Agent remoto Python**: Netmiko per compatibilità multi-vendor (Cisco, HP, Juniper, etc.)
|
||
|
|
6. **Token-based auth**: `NETCONFIG_AGENT_TOKEN` per validazione richieste agent
|
||
|
|
7. **Diff lato server**: `symfony/diff` con output HTML sanitizzato per Twig
|
||
|
|
8. **Export con redaction**: Regex per mascherare password/secret prima del download
|
||
|
|
|
||
|
|
### ⚠️ Alternative Valutate e Scartate
|
||
|
|
| Alternativa | Motivo Scarto |
|
||
|
|
|-------------|--------------|
|
||
|
|
| Backup via SSH diretto da PHP (phpseclib) | Scaling problematico, timeout, gestione credenziali complessa |
|
||
|
|
| Integrazione Oxidized/RANCID via webhook | Overhead infrastrutturale, duplicazione logica versioning |
|
||
|
|
| Archiviazione config su filesystem invece di DB | Perdita integrazione con ACL/profile GLPI, backup/disaster recovery più complesso |
|
||
|
|
| Agent in PHP invece di Python | Netmiko/napalm hanno supporto multi-vendor più maturo in Python |
|
||
|
|
|
||
|
|
### 🔐 Security by Design
|
||
|
|
- **Credenziali di rete**: Mai hardcodate. Usare variabili d'ambiente o vault esterno
|
||
|
|
- **Token agente**: Generato con `openssl rand -hex 32`, rotazione periodica consigliata
|
||
|
|
- **Cifratura a riposo**: `config_content` cifrato con chiave GLPI (`crypt_key` in config_db.php)
|
||
|
|
- **Export sicuro**: Controllo `Session::haveRight()` + redaction automatica credenziali
|
||
|
|
- **API endpoint**: Validazione CSRF per chiamate browser, token per chiamate agent
|
||
|
|
- **Log sensibili**: Nessun dato di configurazione nei log di sistema
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📡 Endpoint API del Plugin
|
||
|
|
|
||
|
|
### POST `/plugins/netconfig/ajax/agent_receive.php`
|
||
|
|
**Scopo**: Ricevere configurazioni da GLPI Agent remoto
|
||
|
|
|
||
|
|
**Request JSON**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"device_id": 123,
|
||
|
|
"config": "!\nhostname SW-TEST\n...\nend",
|
||
|
|
"token": "your_secure_agent_token",
|
||
|
|
"timestamp": "2026-05-22T10:30:00+00:00",
|
||
|
|
"agent_version": "1.0.0"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response JSON**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "ok",
|
||
|
|
"message": "Configuration saved and versioned"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
Oppure:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "ok",
|
||
|
|
"message": "No changes detected"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Codici HTTP**:
|
||
|
|
- `200`: Successo (controllare `status` nel JSON)
|
||
|
|
- `400`: Payload incompleto
|
||
|
|
- `401`: Token non valido
|
||
|
|
- `405`: Metodo HTTP non consentito
|
||
|
|
- `500`: Errore database/server
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🐍 Script Agent Python: Punti Chiave
|
||
|
|
|
||
|
|
### Configurazione Dispositivi (`netconfig_devices.yaml`)
|
||
|
|
```yaml
|
||
|
|
devices:
|
||
|
|
- name: "SW-Core-01"
|
||
|
|
ip: "10.0.0.1"
|
||
|
|
platform: "cisco_ios" # Mappatura netmiko
|
||
|
|
glpi_id: 123 # ID in glpi_networkdevices
|
||
|
|
username: "${NETCONFIG_DEFAULT_USER}" # Variabile d'ambiente
|
||
|
|
enable_password: "${NETCONFIG_ENABLE_PASS}"
|
||
|
|
command: "show running-config"
|
||
|
|
delay_factor: 2
|
||
|
|
```
|
||
|
|
|
||
|
|
### Gestione Errori Robusta
|
||
|
|
- Retry logic con backoff per timeout di rete
|
||
|
|
- Distinzione tra errori di autenticazione (no retry) e timeout (retry)
|
||
|
|
- Logging strutturato con livelli: INFO per successi, WARNING per retry, ERROR per fallimenti
|
||
|
|
|
||
|
|
### Ottimizzazioni
|
||
|
|
- Invio a GLPI solo se hash diverso dall'ultimo salvato (controllo lato client opzionale)
|
||
|
|
- Pulizia output da caratteri di controllo prima dell'invio
|
||
|
|
- Supporto per piattaforme multiple tramite mapping `device_type`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 Massive Actions Supportate
|
||
|
|
|
||
|
|
| Action ID | Etichetta UI | Permesso Richiesto | Comportamento |
|
||
|
|
|-----------|-------------|-------------------|---------------|
|
||
|
|
| `PluginNetconfig\Config:BackupNow` | "Force backup now" | CREATE | Triggera recupero configurazione immediato per dispositivi selezionati |
|
||
|
|
| `PluginNetconfig\Config:ExportSelected` | "Export selected" | READ | Genera download file .txt per configurazioni selezionate |
|
||
|
|
|
||
|
|
**Implementazione**: Override di `getSpecificMassiveActions()` e `processMassiveActionsForOneItemtype()` in `Config.php`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🗄️ Schema Database
|
||
|
|
|
||
|
|
### Tabella: `glpi_plugin_netconfig_configs`
|
||
|
|
```sql
|
||
|
|
CREATE TABLE `glpi_plugin_netconfig_configs` (
|
||
|
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||
|
|
`networkdevices_id` int unsigned NOT NULL DEFAULT '0', -- FK a glpi_networkdevices
|
||
|
|
`config_content` mediumtext NOT NULL, -- Cifrato AES-256-GCM
|
||
|
|
`config_hash` char(64) NOT NULL, -- SHA256 hex
|
||
|
|
`is_encrypted` tinyint NOT NULL DEFAULT '1', -- Flag cifratura
|
||
|
|
`created_at` datetime NOT NULL, -- Timestamp salvataggio
|
||
|
|
`users_id` int unsigned NOT NULL DEFAULT '0', -- 0 = system/agent
|
||
|
|
PRIMARY KEY (`id`),
|
||
|
|
KEY `networkdevices_id` (`networkdevices_id`),
|
||
|
|
KEY `created_at` (`created_at`),
|
||
|
|
KEY `config_hash` (`config_hash`)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note**:
|
||
|
|
- `MEDIUMTEXT` supporta config fino a ~16MB (sufficiente per switch/router enterprise)
|
||
|
|
- Indici su `networkdevices_id` e `created_at` per query efficienti dello storico
|
||
|
|
- `config_hash` indicizzato per rilevamento rapido duplicati
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎨 Integrazione UI GLPI
|
||
|
|
|
||
|
|
### Tab Personalizzato su NetworkEquipment
|
||
|
|
- **Posizione**: Scheda aggiuntiva "Config History" nel form di `NetworkEquipment`
|
||
|
|
- **Contenuto**: Tabella con data, hash abbreviato, utente, azioni (export, diff)
|
||
|
|
- **Diff Visual**: Modal dialog con output HTML di `symfony/diff` (aggiunte in verde, rimozioni in rosso)
|
||
|
|
- **Pulsante Trigger**: "Retrieve configuration now" visibile solo a utenti con diritto CREATE
|
||
|
|
|
||
|
|
### Template Twig (`config_tab.html.twig`)
|
||
|
|
- Uso di helper GLPI: `path()`, `getUserName`, `__()` per traduzioni
|
||
|
|
- Sanitizzazione output diff con `|escape('js')` per prevenzione XSS
|
||
|
|
- Responsive design con classi Bootstrap native di GLPI 11
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🛠️ Comandi Utili per Sviluppo & Debug
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Verifica ambiente GLPI
|
||
|
|
php /var/www/glpi/bin/console glpi:version
|
||
|
|
php /var/www/glpi/bin/console glpi:system:status
|
||
|
|
|
||
|
|
# Installazione plugin
|
||
|
|
cd /var/www/glpi/plugins/netconfig
|
||
|
|
composer install --no-dev -o
|
||
|
|
chown -R www-data:www-data .
|
||
|
|
# Poi: UI GLPI > Configurazione > Plugin > Installa
|
||
|
|
|
||
|
|
# Test endpoint agent
|
||
|
|
curl -X POST http://localhost/glpi/plugins/netconfig/ajax/agent_receive.php \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d '{"device_id":123,"config":"test","token":"CHANGE_ME"}'
|
||
|
|
|
||
|
|
# Log utili
|
||
|
|
tail -f /var/log/glpi/php-errors.log
|
||
|
|
tail -f /var/log/glpi_agent_netconfig.log
|
||
|
|
journalctl -u glpi-netconfig.service -f
|
||
|
|
|
||
|
|
# Verifica cifratura DB
|
||
|
|
mysql -e "SELECT config_content FROM glpi_plugin_netconfig_configs LIMIT 1" glpi_db
|
||
|
|
# Deve restituire blob cifrato, non testo in chiaro
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🚨 Troubleshooting Ricorrenti
|
||
|
|
|
||
|
|
| Sintomo | Causa Probabile | Soluzione |
|
||
|
|
|---------|----------------|-----------|
|
||
|
|
| `symfony/diff not found` | Cache Composer corrotta o minimum-stability mancante | `composer clear-cache && composer install -vvv` |
|
||
|
|
| Agent riceve 401 | Token non configurato o mismatch | Verificare `NETCONFIG_AGENT_TOKEN` in env e payload |
|
||
|
|
| Config non salvata ma nessun errore | Hash identico all'ultima versione (nessuna modifica) | Controllare log: messaggio "No changes detected" è normale |
|
||
|
|
| Diff non visualizzato | `symfony/diff` non installato o autoload non aggiornato | `composer dump-autoload -o` |
|
||
|
|
| Export scarica file vuoto | Permessi insufficienti o config cifrata senza chiave valida | Verificare `crypt_key` in `config_db.php` e diritti profilo |
|
||
|
|
| Massive action non appare | Plugin non attivato o hook non registrato | Controllare `setup.php` e stato plugin in UI GLPI |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📈 Roadmap Futura (Opzionale)
|
||
|
|
|
||
|
|
- [ ] Supporto per backup multipli paralleli (queue RabbitMQ/Redis)
|
||
|
|
- [ ] Integrazione con GLPI Notifications per alert su config change
|
||
|
|
- [ ] Plugin settings UI per configurare token, timeout, piattaforme supportate
|
||
|
|
- [ ] Supporto per dispositivi via API REST (non solo SSH)
|
||
|
|
- [ ] Reportistica: grafico frequenza modifiche, compliance check
|
||
|
|
- [ ] Webhook outbound per integrazione con SIEM/ITSM esterni
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📚 Riferimenti Ufficiali
|
||
|
|
|
||
|
|
- [GLPI 11 Developer Documentation](https://glpi-developer-documentation.readthedocs.io/en/11.0/)
|
||
|
|
- [GLPI Plugin Development Guidelines](https://github.com/glpi-project/glpi/blob/11.0/DEV/PLUGIN.md)
|
||
|
|
- [Netmiko Documentation](https://ktbyers.github.io/netmiko/)
|
||
|
|
- [Symfony Diff Component](https://symfony.com/doc/current/components/diff.html)
|
||
|
|
- [GLPI REST API Reference](https://github.com/glpi-project/glpi/blob/11.0/apirest.md)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
> 💡 **Nota per l'Agent AI**: Quando assisti nello sviluppo di questo plugin, priorizza:
|
||
|
|
> 1. Conformità alle linee guida GLPI 11 (namespace, strict_types, DBConnection)
|
||
|
|
> 2. Sicurezza (cifratura, validazione input, controllo diritti)
|
||
|
|
> 3. Performance (query indicizzate, diff calcolato on-demand)
|
||
|
|
> 4. Manutenibilità (codice commentato, log chiari, configurazione esterna)
|
||
|
|
```
|