Qualys: - Recherche API temps réel + cache 24h base locale - Tags: liste DYN/STAT, mapping V3 (DOM-*, TYP-*, APP-*), nb assets cliquable - CRUD tags: créer STAT, supprimer, resync API - Détail asset: infos + décodage nomenclature V3 + tags assignés - Ajout/retrait tag unitaire avec autocomplete filtrable - Bulk add/remove tag en masse avec dropdown filtrable - Tags retirer: charge dynamiquement les STAT assignés aux assets sélectionnés - Resync assets sélectionnés + retour même recherche Contacts: - 50 contacts importés avec 93 scopes (domaine/app/serveur/zone par env) - 13 rôles (responsable_domaine, ra_prod, ra_recette, referent_technique...) - Recherche par nom/email/serveur (affiche contacts liés) - CRUD complet: éditer, scopes, activer/désactiver, supprimer - Serveurs liés calculés dynamiquement depuis les scopes Audit: - Restructuré: Audit général + sous-menu Spécifique - Dernier audit global affiché avec date - Lancer audit général avec exclusions (domaines/zones) et parallélisme - KPIs Qualys KO et S1 KO cliquables - Export CSV Serveurs: - Actions groupées bulk (domaine, env, tier, état, owner, licence) - Dashboard: KPI EOL ajouté - Filtre état: EOL + en décommissionnement ajoutés - 138 serveurs EOL importés depuis Qualys (owner=na, hors périmètre) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
80 lines
4.0 KiB
HTML
80 lines
4.0 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}Décodeur Qualys{% endblock %}
|
|
{% block content %}
|
|
<h2 class="text-xl font-bold text-cyber-accent mb-4">Décodeur nomenclature SANEF</h2>
|
|
|
|
<!-- Saisie -->
|
|
<form method="GET" class="card p-4 mb-4 flex gap-3 items-end">
|
|
<div class="flex-1">
|
|
<label class="text-xs text-gray-500">Hostname à décoder</label>
|
|
<input type="text" name="hostname" value="{{ hostname or '' }}" placeholder="vpdsiasat1, vrtrabkme1, ls-amiens..." class="w-full font-mono">
|
|
</div>
|
|
<button type="submit" class="btn-primary px-4 py-2 text-sm">Décoder</button>
|
|
</form>
|
|
|
|
{% if result %}
|
|
<!-- Résultat décodage -->
|
|
<div class="card p-5 mb-4">
|
|
<div class="flex items-center gap-4 mb-4">
|
|
<h3 class="text-xl font-bold font-mono text-cyber-accent">{{ result.hostname }}</h3>
|
|
<span class="badge {% if result.type == 'VM' %}badge-blue{% else %}badge-gray{% endif %}">{{ result.type }}</span>
|
|
<span class="badge {% if result.env == 'Production' %}badge-green{% elif result.env == 'Recette' %}badge-yellow{% else %}badge-gray{% endif %}">{{ result.env }}</span>
|
|
<span class="badge badge-blue">{{ result.domain }}</span>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-6">
|
|
<!-- Tags suggérés -->
|
|
<div>
|
|
<h4 class="text-xs text-cyber-accent font-bold uppercase mb-2 border-b border-cyber-border pb-1">Tags suggérés par la nomenclature</h4>
|
|
<div class="space-y-1">
|
|
{% for tag in result.tags %}
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="font-mono text-cyber-yellow">{{ tag }}</span>
|
|
{% set is_auto = false %}
|
|
{% for prefix in auto_prefixes %}
|
|
{% if tag.startswith(prefix) %}{% set is_auto = true %}{% endif %}
|
|
{% endfor %}
|
|
<span class="badge {% if is_auto %}badge-blue{% else %}badge-yellow{% endif %}">{{ 'DYN' if is_auto else 'STAT' }}</span>
|
|
{% set found = false %}
|
|
{% for ct in current_tags %}
|
|
{% if ct[0] == tag %}{% set found = true %}{% endif %}
|
|
{% endfor %}
|
|
{% if found %}
|
|
<span class="text-cyber-green text-xs">✓ Assigné</span>
|
|
{% else %}
|
|
<span class="text-cyber-red text-xs">✗ Manquant</span>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tags actuels Qualys -->
|
|
<div>
|
|
<h4 class="text-xs text-cyber-accent font-bold uppercase mb-2 border-b border-cyber-border pb-1">Tags actuels dans Qualys ({{ current_tags|length }})</h4>
|
|
{% if current_tags %}
|
|
<div class="flex flex-wrap gap-1">
|
|
{% for name, is_dyn in current_tags %}
|
|
<span class="badge {% if is_dyn %}badge-blue{% else %}badge-yellow{% endif %}">{{ name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-xs text-gray-500">{% if hostname %}Asset non trouvé dans Qualys ou aucun tag{% else %}Saisissez un hostname{% endif %}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Légende -->
|
|
<div class="card p-4">
|
|
<h4 class="text-xs text-cyber-accent font-bold uppercase mb-2">Légende</h4>
|
|
<div class="grid grid-cols-2 gap-2 text-xs">
|
|
<div class="flex items-center gap-2"><span class="badge badge-blue">DYN</span> Tag dynamique (géré automatiquement par Qualys via règle)</div>
|
|
<div class="flex items-center gap-2"><span class="badge badge-yellow">STAT</span> Tag statique (assignation manuelle requise)</div>
|
|
<div class="flex items-center gap-2"><span class="text-cyber-green">✓ Assigné</span> Tag présent sur l'asset</div>
|
|
<div class="flex items-center gap-2"><span class="text-cyber-red">✗ Manquant</span> Tag suggéré mais non assigné</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|