patchcenter/app/templates/safe_patching_terminal.html
Khalid MOUTAOUAKIL 49d5658475 Safe Patching wizard, SSE terminal, SSH password fallback, Qualys VMDR testé
Safe Patching Quick Win:
- Wizard 4 steps: Prérequis → Snapshot → Exécution → Post-patch
- Step 1: vérif SSH/disque/satellite par branche, exclure les KO
- Step 2: snapshot vSphere VMs
- Step 3: commande yum éditable, lancer hprod puis prod (100% requis)
- Step 4: vérification post-patch, export CSV
- Terminal SSE live (Server-Sent Events) avec couleurs
- Exclusion serveurs par checkbox dans chaque branche
- Label auto Quick Win SXX YYYY

SSH:
- Fallback password depuis settings si clé SSH absente
- Détection auto root (id -u) → pas de sudo si déjà root
- Testé sur VM doli CentOS 7 (10.0.2.4)

Qualys VMDR:
- API 2.0 testée et fonctionnelle avec compte sanef-ae
- Knowledge Base (CVE/QID/packages) accessible
- Host Detections (vulns par host) accessible
- Migration vers API 4.0 à prévoir (EOL dans 85 jours)

Qualys Agent installé sur doli (activation perso qg2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 06:49:31 +02:00

80 lines
3.0 KiB
HTML

{% extends 'base.html' %}
{% block title %}Terminal — {{ c.label }}{% endblock %}
{% block content %}
<div class="flex justify-between items-center mb-4">
<div>
<a href="/safe-patching/{{ c.id }}" class="text-xs text-gray-500 hover:text-gray-300">← Retour campagne</a>
<h2 class="text-xl font-bold text-cyber-accent">{{ c.label }} — Exécution {{ 'Hors-prod' if branch == 'hprod' else 'Production' }}</h2>
</div>
<div class="flex items-center gap-2">
<span id="status-badge" class="badge badge-yellow">En cours</span>
<span id="counter" class="text-xs text-gray-500">0 traité(s)</span>
</div>
</div>
<!-- Terminal -->
<div class="card" style="background:#0d1117; border-color:#1e3a5f">
<div class="p-2 border-b border-cyber-border flex items-center gap-2">
<span class="w-3 h-3 rounded-full bg-cyber-red"></span>
<span class="w-3 h-3 rounded-full bg-cyber-yellow"></span>
<span class="w-3 h-3 rounded-full bg-cyber-green"></span>
<span class="text-xs text-gray-500 ml-2">PatchCenter Terminal — Safe Patching</span>
</div>
<div id="terminal" class="p-4 font-mono text-xs overflow-y-auto" style="height:500px; line-height:1.6">
<div class="text-gray-500">Connexion au stream...</div>
</div>
</div>
<div class="flex gap-2 mt-4">
<a href="/safe-patching/{{ c.id }}" class="btn-primary px-4 py-2 text-sm" id="btn-back" style="display:none">Voir les résultats</a>
</div>
<script>
var terminal = document.getElementById('terminal');
var counter = 0;
var source = new EventSource('/safe-patching/{{ c.id }}/stream');
source.onmessage = function(e) {
var data = JSON.parse(e.data);
if (data.level === 'done') {
source.close();
document.getElementById('status-badge').textContent = 'Terminé';
document.getElementById('status-badge').className = 'badge badge-green';
document.getElementById('btn-back').style.display = '';
return;
}
var line = document.createElement('div');
var color = {
'header': 'color:#00d4ff; font-weight:bold',
'server': 'color:#00d4ff; font-weight:bold; margin-top:4px',
'step': 'color:#94a3b8',
'ok': 'color:#00ff88',
'error': 'color:#ff3366',
'success': 'color:#00ff88; font-weight:bold',
'info': 'color:#e2e8f0',
}[data.level] || 'color:#94a3b8';
if (data.msg === '') {
line.innerHTML = '&nbsp;';
} else {
line.innerHTML = '<span style="color:#4a5568">[' + data.ts + ']</span> <span style="' + color + '">' + data.msg + '</span>';
}
terminal.appendChild(line);
terminal.scrollTop = terminal.scrollHeight;
if (data.level === 'success') counter++;
document.getElementById('counter').textContent = counter + ' traité(s)';
};
source.onerror = function() {
var line = document.createElement('div');
line.innerHTML = '<span style="color:#ff3366">Connexion perdue. Rafraîchir la page.</span>';
terminal.appendChild(line);
source.close();
};
</script>
{% endblock %}