Files
Deep-Package-Inspection/DOKUMENTASI-FILTER-PER-SITE.md
T

8.9 KiB

DETAIL TEKNIS: Cara Proxy Memfilter Data per Site (SIAB vs Office)

Dokumen ini menjelaskan secara kode bagaimana data dipisahkan per site. Ada 3 lapis filter yang bekerja dari Netify API sampai ke tampilan dashboard.


LAPIS 1 — Saat Minta Data ke Netify API

File: proxy/netifyClientCore.js

NETIFY_SITE_UUIDS = "6681452d_....(SIAB), 1959bb55_....(Office)"
                          |
              proxy loop satu per satu:
              ┌─────────────────────────┐
              │  for SIAB UUID:         │
              │    kirim request ke     │
              │    Netify dengan header │
              │    x-net-site: SIAB-UUID│
              └─────────────────────────┘
              ┌─────────────────────────┐
              │  for Office UUID:       │
              │    kirim request ke     │
              │    Netify dengan header │
              │    x-net-site: OFFICE-UUID│
              └─────────────────────────┘

KODE ASLI — cara header dikirim:

// proxy/netifyClientCore.js baris 14-18
function getHeaders(siteUuid) {
  const headers = {
    'x-api-key': process.env.NETIFY_API_KEY,
    'Accept': 'application/json'
  };

  if (siteUuid) headers['x-net-site'] = siteUuid;
  //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Ini yang memfilter data di sisi Netify!
  // Netify API hanya kembalikan data untuk site ini saja.

  return headers;
}

async function netifyFetch(endpoint, params = {}, agentUuid, siteUuid) {
  const res = await axios.get(`${BASE_URL}${endpoint}`, {
    headers: getHeaders(siteUuid),  // <--- siteUuid dikirim ke Netify
    params,
    timeout: 30000,
  });
}

Artinya: Netify API sendiri yang memfilter. Kalau kita kirim header x-net-site: SIAB-UUID, Netify HANYA kembalikan data milik SIAB. Kita tidak perlu filter manual — Netify sudah filter dari sumbernya.


LAPIS 2 — Saat Simpan ke MongoDB

File: proxy/collector.js (loop utama)

Setelah data dari Netify masuk, setiap dokumen diberi stempel site_uuid sebelum disimpan ke MongoDB.

KODE ASLI — loop per site di collector.js:

// proxy/collector.js baris 123-222

// SITE_UUIDS diambil dari env:
// NETIFY_SITE_UUIDS="6681452d_..., 1959bb55_..."
const SITE_UUIDS = SITE_UUIDS_STR.split(','); // ["SIAB-UUID", "OFFICE-UUID"]

for (const siteUuid of SITE_UUIDS) {
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//   Loop: pertama SIAB, lalu Office (satu per satu)

  console.log(`Fetching agents for Site: ${siteUuid}`);
  const agents = await netify.fetchAgents(siteUuid);
  //                                      ^^^^^^^^^
  //  fetchAgents pakai siteUuid → Netify hanya beri agent milik site ini

  // --- PENTING: Anti-duplikat antar site ---
  // Kadang Netify bisa kembalikan agent yang sama untuk 2 site.
  // Di sini kita cegah agar 1 agent hanya masuk 1 site.
  const agents = rawAgents.filter(a => {
    if (processedAgentUuids.has(a.uuid)) {
      console.log(`Skipping ${a.uuid} — already assigned to another site.`);
      return false;  // lewati agent yang sudah diproses site lain
    }
    return true;
  });
  for (const agent of agents) processedAgentUuids.add(agent.uuid);

  // Simpan agent ke MongoDB dengan site_uuid
  await AgentRegistry.findOneAndUpdate(
    { uuid: agent.uuid },
    { $set: {
        uuid: agent.uuid,
        site_uuid: siteUuid,  // <--- stempel site di sini!
        ...
    }},
    { upsert: true }
  );

  // Kumpulkan data untuk setiap agent di site ini
  for (const agent of agents) {
    await collectForAgent(agent.uuid, timestamp, siteUuid);
    //                                           ^^^^^^^^^
    //   siteUuid terus dibawa ke setiap fungsi collect
  }
}

KODE ASLI — cara flows disimpan dengan site_uuid:

// proxy/collectorHelperDpi2.js baris 88-98

const flowDocs = flows.map(f => ({
  timestamp,
  agent_uuid: agentUuid,   // siapa agent-nya
  site_uuid:  SITE_UUID,   // <--- data ini milik site mana! (SIAB atau Office)
  flow_id:    f.flow_id,
  src_ip:     f.src_ip,
  dst_ip:     f.dst_ip,
  download:   f.download,
  upload:     f.upload,
  // ...
}));

// Upsert ke MongoDB (tidak duplikat berdasarkan flow_id + agent_uuid)
await Flow.bulkWrite(flowDocs.map(f => ({
  updateOne: {
    filter: { flow_id: f.flow_id, agent_uuid: f.agent_uuid },
    update: { $set: f },
    upsert: true,
  }
})));

Hasilnya di MongoDB — data terpisah per site:

Collection: flows
┌────────────────────┬────────────────────────────────────────────────────┬────────┬──────────┐
│ flow_id            │ site_uuid                                          │ src_ip │ download │
├────────────────────┼────────────────────────────────────────────────────┼────────┼──────────┤
│ flow-001           │ 6681452d_9cae_4ff4_8ae8_0d504774265e  (SIAB)       │ 10.0.x │ 1234     │
│ flow-002           │ 6681452d_9cae_4ff4_8ae8_0d504774265e  (SIAB)       │ 10.0.x │ 5678     │
│ flow-003           │ 1959bb55_045b_47c7_bbdd_f33b7db197b9  (Office)     │ 192.168.x │ 9012  │
│ flow-004           │ 1959bb55_045b_47c7_bbdd_f33b7db197b9  (Office)     │ 192.168.x │ 3456  │
└────────────────────┴────────────────────────────────────────────────────┴────────┴──────────┘
                       ^^^^^^^^^^ Field ini yang memisahkan data ^^^^^^^^^^

Semua collection lain juga sama:

  • devices → tiap dokumen ada site_uuid
  • threats → tiap dokumen ada site_uuid
  • events → tiap dokumen ada site_uuid
  • summaries → tiap dokumen ada site_uuid
  • telemetry → tiap dokumen ada site_uuid

LAPIS 3 — Saat Dashboard Baca dari MongoDB

File: backend/routes/dashboard/flows.js (contoh)

Ketika user login sebagai admin SIAB dan buka halaman Flows, backend hanya query dokumen dengan site_uuid yang sesuai:

// backend/routes/dashboard/flows.js (contoh query)
const userSiteUuid = req.user.site_uuid;
// → "6681452d_9cae_4ff4_8ae8_0d504774265e" (SIAB)

const flows = await Flow.find({
  site_uuid: userSiteUuid,  // <--- hanya ambil data site ini!
  // ...filter waktu, pagination, dsb
}).limit(50);

Admin Office login → site_uuid = 1959bb55_... → hanya lihat data Office. Admin SIAB login → site_uuid = 6681452d_... → hanya lihat data SIAB. Super Admin → bisa pilih site mana yang ingin dilihat.


RINGKASAN — Alur Lengkap Filter Data

Netify API
    |
    |-- Lapis 1: Header x-net-site dikirim ke Netify
    |   Netify hanya kirim data milik site tersebut
    |
    v
Proxy Server (setiap 5 menit)
    |
    |-- Lapis 2: Setiap dokumen diberi stempel site_uuid
    |   - SIAB data → { site_uuid: "6681452d_..." }
    |   - Office data → { site_uuid: "1959bb55_..." }
    |   - Anti-duplikat: 1 agent hanya masuk 1 site
    |
    v
MongoDB (semua data tercampur tapi ter-tag per site)
    |
    |-- Lapis 3: Backend query MongoDB dengan filter site_uuid
    |   - Admin SIAB login → WHERE site_uuid = SIAB-UUID
    |   - Admin Office login → WHERE site_uuid = OFFICE-UUID
    |
    v
Web Dashboard (tampil hanya data site yang sesuai)

Skenario Konkret

Skenario: Network agent "F6-2V-DT-8A" ada di SIAB. Network agent "23-TE-6L-I2" ada di Office.

Langkah 1 — Proxy request ke Netify

[Iter 1] siteUuid = "6681452d..." (SIAB)
  → GET /data/flows
    Header: x-net-site: 6681452d...
  → Netify kembalikan: flows dari F6-2V-DT-8A (agent SIAB)
  → Simpan ke MongoDB: { site_uuid: "6681452d...", agent_uuid: "F6-2V-DT-8A", flow_id: ... }

[Iter 2] siteUuid = "1959bb55..." (Office)
  → GET /data/flows
    Header: x-net-site: 1959bb55...
  → Netify kembalikan: flows dari 23-TE-6L-I2 (agent Office)
  → Simpan ke MongoDB: { site_uuid: "1959bb55...", agent_uuid: "23-TE-6L-I2", flow_id: ... }

Langkah 2 — Dashboard tampilkan

User siab login:
  req.user.site_uuid = "6681452d..."
  DB query: Flow.find({ site_uuid: "6681452d..." })
  Hasil: hanya flow dari F6-2V-DT-8A ✓

User office login:
  req.user.site_uuid = "1959bb55..."
  DB query: Flow.find({ site_uuid: "1959bb55..." })
  Hasil: hanya flow dari 23-TE-6L-I2 ✓

Data tidak pernah tercampur karena ada 3 lapis isolasi ini.


Dokumentasi teknis Source 2 — 29 Juli 2026