{
  "name": "Audit Active Directory — ETC Collector",
  "nodes": [
    {
      "parameters": {
        "path": "audit-ad",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "n1",
      "name": "Rapport à la demande",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -480,
        304
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://YOUR-COLLECTOR-HOST:8444/api/v1/auth/token",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={}",
        "options": {
          "allowUnauthorizedCerts": true
        }
      },
      "id": "n2",
      "name": "S'authentifier",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -48,
        384
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://YOUR-COLLECTOR-HOST:8444/api/v1/audit/ad",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={}",
        "options": {
          "allowUnauthorizedCerts": true,
          "timeout": 300000
        }
      },
      "id": "n3",
      "name": "Auditer l'Active Directory",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        176,
        384
      ]
    },
    {
      "parameters": {
        "jsCode": "// Agrégation + fragments HTML compatibles messagerie (tables, styles en ligne).\nconst r = $input.first().json;\nconst a = r.audit || {};\nconst s = a.summary || {};\n\nconst findings = [];\nfor (const [cat, bloc] of Object.entries(a)) {\n  if (!bloc || typeof bloc !== 'object') continue;\n  for (const sous of Object.values(bloc)) {\n    if (sous && Array.isArray(sous.findings))\n      for (const f of sous.findings) findings.push({ ...f, categorie: f.category || cat });\n  }\n}\n\nconst G = { critical:0, high:0, medium:0, low:0, info:0 };\nfindings.forEach(f => { if (G[f.severity] !== undefined) G[f.severity]++; });\n\nconst score = Number(s.risk?.score ?? 0);\nconst note = score >= 85 ? 'A' : score >= 70 ? 'B' : score >= 55 ? 'C' : score >= 40 ? 'D' : 'E';\nconst col  = score >= 85 ? '#2f8f22' : score >= 70 ? '#58a832' : score >= 55 ? '#eab308'\n           : score >= 40 ? '#f2801f' : '#e5484d';\nconst verdict = score >= 85 ? 'Posture saine — maintenir la surveillance'\n  : score >= 70 ? 'Posture correcte — quelques écarts à corriger'\n  : score >= 55 ? 'Écarts significatifs — plan de remédiation à engager'\n  : score >= 40 ? 'Exposition élevée — traitement prioritaire requis'\n  : 'Exposition critique — action immédiate';\n\nconst C = { critical:'#e5484d', high:'#f2801f', medium:'#eab308', low:'#3165be', info:'#8a93a1' };\nconst L = { critical:'Critique', high:'Élevée', medium:'Moyenne', low:'Faible', info:'Information' };\nconst ordre = { critical:0, high:1, medium:2, low:3, info:4 };\nconst F = \"-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif\";\n\nconst objetsExposes = findings.filter(f => ['critical','high'].includes(f.severity))\n  .reduce((n,f) => n + (f.count || (f.affectedEntities||[]).length || 0), 0);\n\nconst parCat = {};\nfindings.filter(f => f.severity !== 'info')\n        .forEach(f => { parCat[f.categorie] = (parCat[f.categorie]||0) + 1; });\nconst maxCat = Math.max(1, ...Object.values(parCat));\n\nconst conformite = s.complianceScores || [];\nconst confMoy = conformite.length\n  ? Math.round(conformite.reduce((n,c) => n + (c.score||0), 0) / conformite.length) : '—';\n\n// ── KPI : une ligne de 4 cellules, pas une grille\nconst kpi = [[G.critical,'détections critiques','#e5484d'],\n             [G.high,'détections élevées','#f2801f'],\n             [objetsExposes,'objets exposés','#0d0f13'],\n             [confMoy,'conformité moyenne','#0d0f13']]\n  .map(([v,l,c]) => `<td width=\"25%\" style=\"background:#fff;padding:16px 18px;border-right:1px solid #e6e8ec;vertical-align:top\">\n    <div style=\"font:700 27px/1 ${F};color:${c}\">${v}</div>\n    <div style=\"font:400 11px/1.35 ${F};color:#5b6572;padding-top:6px\">${l}</div></td>`).join('');\n\n// ── Échelle de notes : une ligne par échelon\nconst echelle = [['A',85,100,'Posture saine','#2f8f22'],['B',70,84,'Écarts mineurs','#58a832'],\n                 ['C',55,69,'Écarts significatifs','#eab308'],['D',40,54,'Exposition élevée','#f2801f'],\n                 ['E',0,39,'Exposition critique','#e5484d']]\n  .map(([l,mn,mx,t,c]) => {\n    const on = l === note;\n    return `<tr style=\"background:${on ? '#fffdf5' : '#fff'}\">\n      <td width=\"46\" style=\"padding:9px 0 9px 14px\">\n        <div style=\"width:26px;height:26px;background:${on ? c : '#eef0f3'};color:${on ? '#fff' : '#a7aeb8'};\n          font:700 14px/26px ${F};text-align:center\">${l}</div></td>\n      <td width=\"72\" style=\"font:400 12px/1.4 ${F};color:#8a93a1;padding:9px 0\">${mn}–${mx}</td>\n      <td style=\"font:${on ? 600 : 400} 13px/1.4 ${F};color:${on ? '#0d0f13' : '#5b6572'};padding:9px 14px 9px 0\">${t}</td>\n    </tr>`;\n  }).join('');\n\n// ── Gravités : une ligne de 4\nconst sev = [['critical',G.critical],['high',G.high],['medium',G.medium],['low',G.low]]\n  .map(([k,n]) => `<td width=\"25%\" style=\"background:#fff;padding:0;border-right:1px solid #e6e8ec\">\n    <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>\n      <td width=\"3\" style=\"background:${C[k]};font-size:0;line-height:0\">&nbsp;</td>\n      <td style=\"padding:13px 16px\">\n        <div style=\"font:700 21px/1 ${F}\">${n}</div>\n        <div style=\"font:400 10.5px/1.3 ${F};color:#5b6572;text-transform:uppercase;letter-spacing:.05em;padding-top:5px\">${L[k]}</div>\n      </td></tr></table></td>`).join('');\n\n// ── Catégories : barre en table, largeur en pourcentage\nconst barres = Object.entries(parCat).sort((x,y)=>y[1]-x[1]).slice(0,8).map(([c,n]) => {\n  const p = Math.round(n/maxCat*100);\n  return `<tr><td style=\"padding:11px 0 4px\">\n      <span style=\"font:500 13px/1.4 ${F};text-transform:capitalize\">${c}</span>\n      <span style=\"font:400 12px/1.4 ${F};color:#8a93a1;float:right\">${n}</span></td></tr>\n    <tr><td style=\"padding:0 0 3px\">\n      <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#eef0f3\">\n        <tr><td width=\"${p}%\" style=\"background:#3165be;height:6px;font-size:0;line-height:0\">&nbsp;</td>\n            <td style=\"font-size:0;line-height:0\">&nbsp;</td></tr></table></td></tr>`;\n}).join('');\n\n// ── Priorités\nconst lignes = findings.filter(f => ['critical','high'].includes(f.severity))\n  .sort((x,y)=>ordre[x.severity]-ordre[y.severity]).slice(0,10)\n  .map((f,i) => `<tr>\n    <td style=\"padding:11px 8px 11px 14px;border-bottom:1px solid #f0f1f4;font:700 12px/1 ${F};color:#c8ccd3\">${String(i+1).padStart(2,'0')}</td>\n    <td style=\"padding:11px 8px;border-bottom:1px solid #f0f1f4\">\n      <span style=\"background:${C[f.severity]};color:#fff;font:600 9.5px/1 ${F};letter-spacing:.05em;\n        text-transform:uppercase;padding:4px 7px;display:inline-block;white-space:nowrap\">${L[f.severity]}</span></td>\n    <td style=\"padding:11px 8px;border-bottom:1px solid #f0f1f4;font:500 13px/1.4 ${F}\">${f.title}</td>\n    <td style=\"padding:11px 8px;border-bottom:1px solid #f0f1f4;font:400 12px/1.4 ${F};color:#5b6572;text-transform:capitalize\">${f.categorie}</td>\n    <td align=\"right\" style=\"padding:11px 14px 11px 8px;border-bottom:1px solid #f0f1f4;font:600 13px/1.4 ${F}\">${f.count || (f.affectedEntities||[]).length || 0}</td>\n  </tr>`).join('');\n\n// ── Conformité\nconst conf = conformite.slice(0,9).map(c => {\n  const sc = c.score || 0;\n  const cc = sc >= 70 ? '#2f8f22' : sc >= 40 ? '#eab308' : '#e5484d';\n  return `<tr>\n    <td width=\"160\" style=\"padding:8px 12px 8px 0;font:500 12.5px/1.4 ${F};border-bottom:1px solid #f0f1f4\">${c.framework}</td>\n    <td style=\"padding:8px 12px 8px 0;border-bottom:1px solid #f0f1f4\">\n      <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#eef0f3\">\n        <tr><td width=\"${Math.max(2,sc)}%\" style=\"background:${cc};height:7px;font-size:0;line-height:0\">&nbsp;</td>\n            <td style=\"font-size:0;line-height:0\">&nbsp;</td></tr></table></td>\n    <td width=\"44\" align=\"right\" style=\"padding:8px 0;font:700 13px/1.4 ${F};color:${cc};border-bottom:1px solid #f0f1f4\">${sc}</td>\n  </tr>`;\n}).join('');\n\nreturn [{ json: {\n  domaine: s.domain || 'example.local', note, score: score.toFixed(1), couleur: col, verdict,\n  nbCritique: G.critical, nbEleve: G.high, nbTotal: findings.length,\n  date: new Date().toLocaleDateString('fr-FR',{day:'numeric',month:'long',year:'numeric'}),\n  heure: new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'}),\n  kpi, echelle, sev, barres, lignes, conf,\n}}];\n"
      },
      "id": "n4",
      "name": "Agréger les détections",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        512,
        384
      ]
    },
    {
      "parameters": {
        "html": "<!doctype html><html lang=\"fr\"><head><meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>Audit Active Directory — {{ $json.domaine }}</title></head>\n<body style=\"margin:0;padding:0;background:#f2f1ec\">\n<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#f2f1ec\">\n<tr><td align=\"center\" style=\"padding:28px 14px\">\n\n<table width=\"680\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"max-width:680px;background:#faf9f5;border:1px solid #d3d7dd\">\n\n<!-- bandeau -->\n<tr><td style=\"padding:26px 28px 22px\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>\n    <td style=\"vertical-align:top\">\n      <div style=\"font:600 10px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.14em;text-transform:uppercase;color:#8a93a1\">Audit de sécurité — Active Directory</div>\n      <div style=\"font:700 27px/1.15 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13;padding-top:9px\">Rapport de posture</div>\n      <div style=\"font:400 13px/1.4 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding-top:7px\">{{ $json.domaine }} · {{ $json.date }} à {{ $json.heure }}</div>\n    </td>\n    <td width=\"130\" align=\"right\" style=\"vertical-align:top\">\n      <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"right\"><tr>\n        <td width=\"60\" style=\"background:{{ $json.couleur }};height:60px;text-align:center;\n          font:700 30px/60px -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#fff\">{{ $json.note }}</td>\n        <td width=\"12\" style=\"font-size:0\">&nbsp;</td>\n        <td style=\"vertical-align:middle;text-align:right\">\n          <div style=\"font:700 22px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">{{ $json.score }}</div>\n          <div style=\"font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:#8a93a1;padding-top:5px\">/ 100</div>\n        </td></tr></table>\n    </td></tr></table>\n</td></tr>\n\n<!-- verdict -->\n<tr><td style=\"padding:0 28px 24px\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#fff;border:1px solid #e6e8ec\">\n    <tr><td width=\"3\" style=\"background:{{ $json.couleur }};font-size:0;line-height:0\">&nbsp;</td>\n        <td style=\"padding:14px 18px;font:400 14px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">{{ $json.verdict }}</td></tr></table>\n</td></tr>\n\n<!-- chiffres cles -->\n<tr><td style=\"padding:0 28px 26px\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #e6e8ec;border-right:0\">\n    <tr>{{ $json.kpi }}</tr></table>\n</td></tr>\n\n<!-- echelle -->\n<tr><td style=\"padding:0 28px 8px\">\n  <div style=\"font:700 15px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">Comment lire cette note</div>\n  <div style=\"font:400 12.5px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding:5px 0 13px\">Le score agrège la gravité de chaque détection et le nombre d'objets réellement exposés.</div>\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #e6e8ec\">{{ $json.echelle }}</table>\n</td></tr>\n\n<!-- gravites -->\n<tr><td style=\"padding:26px 28px 8px\">\n  <div style=\"font:700 15px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">Répartition par gravité</div>\n  <div style=\"font:400 12.5px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding:5px 0 13px\">{{ $json.nbTotal }} détections sur l'ensemble du domaine.</div>\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #e6e8ec;border-right:0\">\n    <tr>{{ $json.sev }}</tr></table>\n</td></tr>\n\n<!-- priorites -->\n<tr><td style=\"padding:26px 28px 8px\">\n  <div style=\"font:700 15px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">À traiter en priorité</div>\n  <div style=\"font:400 12.5px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding:5px 0 13px\">Les dix détections les plus graves, du plus urgent au moins urgent.</div>\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#fff;border:1px solid #e6e8ec\">\n    <tr style=\"background:#f6f7f9\">\n      <td style=\"padding:9px 8px 9px 14px;font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#8a93a1;border-bottom:1px solid #e6e8ec\">#</td>\n      <td style=\"padding:9px 8px;font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#8a93a1;border-bottom:1px solid #e6e8ec\">Gravité</td>\n      <td style=\"padding:9px 8px;font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#8a93a1;border-bottom:1px solid #e6e8ec\">Détection</td>\n      <td style=\"padding:9px 8px;font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#8a93a1;border-bottom:1px solid #e6e8ec\">Catégorie</td>\n      <td align=\"right\" style=\"padding:9px 14px 9px 8px;font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#8a93a1;border-bottom:1px solid #e6e8ec\">Objets</td>\n    </tr>{{ $json.lignes }}</table>\n</td></tr>\n\n<!-- categories -->\n<tr><td style=\"padding:26px 28px 8px\">\n  <div style=\"font:700 15px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">Détections par catégorie</div>\n  <div style=\"font:400 12.5px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding:5px 0 4px\">Où se concentrent les écarts.</div>\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">{{ $json.barres }}</table>\n</td></tr>\n\n<!-- conformite -->\n<tr><td style=\"padding:26px 28px 8px\">\n  <div style=\"font:700 15px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#0d0f13\">Référentiels de conformité</div>\n  <div style=\"font:400 12.5px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#5b6572;padding:5px 0 10px\">Score par référentiel, sur les contrôles réellement évalués.</div>\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">{{ $json.conf }}</table>\n</td></tr>\n\n<!-- a propos -->\n<tr><td style=\"padding:32px 28px 0\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background:#0d0f13\">\n    <tr><td style=\"padding:26px 26px 22px\">\n\n      <div style=\"font:600 9.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;letter-spacing:.16em;text-transform:uppercase;color:#8a93a1\">Ce rapport a été généré par</div>\n      <div style=\"font:700 23px/1.2 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#fff;padding:11px 0 0\">ETC&nbsp;Collector</div>\n      <div style=\"font:400 13.5px/1.6 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#a7aeb8;padding:11px 0 0;max-width:52ch\">\n        Auditeur de sécurité <strong style=\"color:#fff\">Active Directory</strong> et\n        <strong style=\"color:#fff\">Microsoft Entra ID</strong>, écrit en Go. Un binaire statique unique —\n        pas d'agent, pas de dépendance, pas de .NET ni de Python à installer.\n      </div>\n\n      <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:20px 0 0\">\n        <tr>\n          <td style=\"padding:0 26px 0 0;border-right:1px solid #252a32\">\n            <div style=\"font:700 20px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#fff\">500+</div>\n            <div style=\"font:400 10.5px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#8a93a1;padding-top:5px\">contrôles de sécurité</div></td>\n          <td style=\"padding:0 26px;border-right:1px solid #252a32\">\n            <div style=\"font:700 20px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#fff\">9</div>\n            <div style=\"font:400 10.5px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#8a93a1;padding-top:5px\">référentiels de conformité</div></td>\n          <td style=\"padding:0 0 0 26px\">\n            <div style=\"font:700 20px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#fff\">1</div>\n            <div style=\"font:400 10.5px/1.3 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#8a93a1;padding-top:5px\">binaire, zéro dépendance</div></td>\n        </tr></table>\n\n      <div style=\"border-top:1px solid #252a32;margin:22px 0 0;padding:18px 0 0\">\n        <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>\n          <td style=\"padding:0 10px 0 0\">\n            <a href=\"https://etc-collector.com\" style=\"display:inline-block;background:#fff;color:#0d0f13;\n              font:600 12.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;text-decoration:none;padding:11px 18px\">Découvrir le produit</a></td>\n          <td style=\"padding:0 10px 0 0\">\n            <a href=\"https://github.com/etcsec-com/etc-collector-com\" style=\"display:inline-block;\n              border:1px solid #333a45;color:#fff;font:600 12.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;text-decoration:none;padding:10px 17px\">Code source</a></td>\n          <td>\n            <a href=\"https://etcsec.com\" style=\"display:inline-block;\n              border:1px solid #333a45;color:#fff;font:600 12.5px/1 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;text-decoration:none;padding:10px 17px\">Audits EtcSec</a></td>\n        </tr></table>\n      </div>\n\n      <div style=\"font:400 11.5px/1.6 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#78838f;padding:18px 0 0\">\n        <strong style=\"color:#a7aeb8\">FSL-1.1-ALv2</strong> — libre d'usage, entreprises comprises.\n        Chaque version devient Apache&nbsp;2.0 deux ans après sa publication.<br>\n        <span style=\"color:#5b6572\">etc-collector.com&nbsp; ·&nbsp; github.com/etcsec-com/etc-collector-com&nbsp; ·&nbsp; etcsec.com</span>\n      </div>\n\n    </td></tr></table>\n</td></tr>\n\n<tr><td style=\"padding:20px 28px 26px\">\n  <div style=\"border-top:1px solid #d3d7dd;padding-top:14px;font:400 11px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;color:#8a93a1\">\n    ETC Collector v3.2.0 — audit hebdomadaire déclenché depuis n8n, comparable d'une semaine sur l'autre.</div>\n</td></tr>\n\n</table></td></tr></table></body></html>"
      },
      "id": "n5",
      "name": "Mettre en page le rapport",
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        736,
        384
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.html }}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      },
      "id": "n6",
      "name": "Servir le rapport",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        944,
        384
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "sendTo": "you@example.com",
        "subject": "=[{{ $('Agréger les détections').item.json.note }}] Audit AD {{ $('Agréger les détections').item.json.domaine }} — {{ $('Agréger les détections').item.json.nbCritique }} critiques, {{ $('Agréger les détections').item.json.nbEleve }} élevées",
        "message": "={{ $('Mettre en page le rapport').item.json.html }}",
        "options": {
          "appendAttribution": false,
          "senderName": "ETC Collector"
        }
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        1168,
        384
      ],
      "id": "76882ae3-eae9-449b-aa39-1a16a31df238",
      "name": "Envoyer le rapport"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 7
            }
          ]
        }
      },
      "id": "cron1",
      "name": "Chaque lundi 7h",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -480,
        480
      ]
    },
    {
      "parameters": {
        "content": "## Déclenchement\nDeux entrées vers la même chaîne :\n\n**Webhook** — un lien unique, pour une démonstration à la demande.\n**Cron** — tous les lundis à 7 h, pour comparer d'une semaine sur l'autre.",
        "height": 652,
        "width": 300,
        "color": 4
      },
      "id": "note0",
      "name": "Note 1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -560,
        16
      ]
    },
    {
      "parameters": {
        "content": "## Le collecteur\nDeux appels à l'**API REST d'ETC Collector**, sur la machine auditée.\n\nUn jeton court est émis, puis l'audit est lancé : le binaire Go interroge l'Active Directory et applique plus de 500 contrôles.",
        "height": 652,
        "width": 588,
        "color": 3
      },
      "id": "note1",
      "name": "Note 2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -192,
        16
      ]
    },
    {
      "parameters": {
        "content": "## Analyse\nLes détections brutes sont agrégées : note **A–E**, score, objets réellement exposés, priorités et scores de conformité.",
        "height": 652,
        "width": 260,
        "color": 5
      },
      "id": "note2",
      "name": "Note 3",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        416,
        16
      ]
    },
    {
      "parameters": {
        "content": "## Restitution\nLe rapport est mis en page en HTML, servi immédiatement sur le lien, puis envoyé par courriel.\n\nL'objet du message porte la note et le nombre de détections critiques : on trie sans ouvrir.",
        "height": 652,
        "width": 688,
        "color": 6
      },
      "id": "note3",
      "name": "Note 4",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        688,
        16
      ]
    },
    {
      "parameters": {
        "content": "# Audit Active Directory automatisé - ETC&nbsp;Collector\n\n**Auditeur de sécurité Active Directory et Microsoft Entra ID, écrit en Go.**\nUn binaire statique unique : pas d'agent, pas de dépendance, ni .NET ni Python à installer.\n\n|  |  |\n|---|---|\n| **500+** | contrôles de sécurité |\n| **9** | référentiels de conformité (ANSSI, CIS, NIST, DISA, HDS, NIS2, RGPD…) |\n| **1** | binaire, zéro dépendance |\n\nCe workflow appelle son **API REST**, agrège les détections et produit un rapport noté **A–E**\n— servi sur un lien et envoyé par courriel. Aucune intervention humaine.\n\n**[etc-collector.com](https://etc-collector.com)** · [Code source](https://github.com/etcsec-com/etc-collector-com) · [Audits EtcSec](https://etcsec.com)\nFSL-1.1-ALv2 — libre d'usage, entreprises comprises",
        "height": 652,
        "width": 704,
        "color": 7
      },
      "id": "noteAd",
      "name": "À propos",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1280,
        16
      ]
    }
  ],
  "connections": {
    "Rapport à la demande": {
      "main": [
        [
          {
            "node": "S'authentifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "S'authentifier": {
      "main": [
        [
          {
            "node": "Auditer l'Active Directory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auditer l'Active Directory": {
      "main": [
        [
          {
            "node": "Agréger les détections",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agréger les détections": {
      "main": [
        [
          {
            "node": "Mettre en page le rapport",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mettre en page le rapport": {
      "main": [
        [
          {
            "node": "Servir le rapport",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chaque lundi 7h": {
      "main": [
        [
          {
            "node": "S'authentifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Servir le rapport": {
      "main": [
        [
          {
            "node": "Envoyer le rapport",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {},
  "pinData": {}
}