Ketika data berubah tanpa jejak, tiga pertanyaan selalu muncul: siapa yang melakukannya, kapan, dan dari koneksi mana. Audit trail menjawab ketiganya — dan menjadi syarat kepatuhan di banyak regulasi, termasuk kebutuhan pelaporan insiden pelindungan data pribadi. MongoDB Enterprise menyediakan auditing facility bawaan yang mencatat event keamanan ke file, syslog, atau console; pemegang Community Edition tetap memiliki dua alat yang bisa kita uji langsung di server latihan: database profiler dan oplog.

Peta materi Chapter ini:

  • Audit facility Enterprise: auditDestination, format JSON/BSON, dan filter event.
  • Anatomi satu event audit beserta kategori operasi yang dicatat.
  • Alternatif Community #1: database profiler dan system.profile.
  • Alternatif Community #2: oplog untuk melacak perubahan data.
  • Auditing di MongoDB Atlas.

Audit Facility (Khusus Enterprise) #

Auditing diaktifkan lewat blok auditLog pada file konfigurasi. Penerapannya menuntut restart mongod, jadi contoh berikut adalah rujukan untuk deployment produksi Anda, bukan untuk server latihan bersama:

text
auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/auditLog.json

Tiga tujuan keluaran tersedia, masing-masing dengan karakter berbeda:

destinationKarakteristik
fileFormat JSON (mudah dibaca) atau BSON (lebih ringan performa); dirotasi bersama log server
syslogMasuk log sistem Linux; pesan panjang berisiko terpotong; tidak tersedia di Windows
consoleKe stdout — cocok untuk container dan uji coba

Yang dicatat mencakup empat kategori: operasi schema/DDL seperti createCollection dan dropDatabase, operasi replica set dan sharded cluster, serta authentication dan authorization — termasuk percobaan login yang gagal. Operasi CRUD baru ikut terekam bila parameter auditAuthorizationSuccess dinyalakan, dengan konsekuensi penurunan performa. Untuk membatasi kebisingan, filter bisa memilih event tertentu saja — contoh berikut hanya merecord event authentication:

text
auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/auditLog.json
  filter: '{ atype: { $eq: "authenticate" } }'

Anatomi Satu Event Audit #

Bentuk event mengikuti skema resmi — satu baris JSON per kejadian. Berikut contoh event authenticate yang gagal (ilustrasi sesuai skema dokumentasi, bukan hasil eksekusi):

text
{
  atype: "authenticate",
  ts: { "$date": "2026-10-17T09:30:00.000Z" },
  local: { ip: "10.0.0.11", port: 27017 },
  remote: { ip: "203.0.113.50", port: 51522 },
  users: [],
  param: { user: "budi_operator", db: "toko", mechanism: "SCRAM-SHA-256" },
  result: 18
}

Mari kita bedah field pentingnya: atype menyatakan jenis aksi, ts waktu kejadian dalam UTC, local dan remote adalah dua ujung koneksi — alamat asal di remote menjadi petunjuk investigasi — sedangkan param memuat detail spesifik per jenis aksi. Field result berupa kode galat: 18 berarti AuthenticationFailed. Format satu baris semacam ini mempermudah pengiriman ke sistem log terpusat atau SIEM untuk dianalisis bersama log aplikasi lain.

Alternatif Community: Profiler #

Database profiler lahir sebagai alat performa, tetapi system.profile juga merekam jejak operasi: jenis operasi, namespace, command lengkap, durasi, dan identitas user bila authentication aktif. Level 2 merekam semua operasi pada satu database. Kita nyalakan, jalankan dua operasi, lalu baca hasilnya:

js
db = db.getSiblingDB("latihan_audit")
db.setProfilingLevel(0)
db.dropDatabase()
db.pesanan.insertOne({ _id: 1, pelanggan: "Budi", total: 250000 })
db.pesanan.updateOne({ _id: 1 }, { $set: { status: "dibayar" } })
db.setProfilingLevel(2, { slowms: 0 })
db.pesanan.insertOne({ _id: 2, pelanggan: "Siti", total: 120000 })
db.pesanan.find({ pelanggan: "Siti" }).toArray()
db.system.profile.find({}, { op: 1, ns: 1, millis: 1, "command.filter": 1, _id: 0 }).toArray()

Output yang Dihasilkan (gema setProfilingLevel dipadatkan — field $clusterTime, operationTime, dan slowinprogms diringkas):

text
latihan_audit

{
  was: 0,
  slowms: 0,
  sampleRate: 1,
  ok: 1
}
{ ok: 1, dropped: 'latihan_audit' }
{ acknowledged: true, insertedId: 1 }
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
{
  was: 0,
  slowms: 0,
  sampleRate: 1,
  ok: 1
}
{ acknowledged: true, insertedId: 2 }
[ { _id: 2, pelanggan: 'Siti', total: 120000 } ]
[
  { op: 'insert', ns: 'latihan_audit.pesanan', command: {}, millis: 0 },
  {
    op: 'query',
    ns: 'latihan_audit.pesanan',
    command: { filter: { pelanggan: 'Siti' } },
    millis: 0
  }
]

Dua entri terakhir adalah intinya: profiler menangkap insert dan query pada latihan_audit.pesanan lengkap dengan filter yang dipakai — field command pada operasi insert tampak kosong karena projection kita hanya mengambil command.filter, yang memang tidak ada pada insert. Batasannya jelas: system.profile adalah capped collection berukuran kecil sehingga hanya menyimpan operasi terbaru, profil berhenti di operasi database (kegagalan login tidak terekam), dan level 2 menimbulkan overhead — nyalakan untuk penyelidikan, jangan biarkan menyala tanpa alasan.

Alternatif Community: Oplog #

Oplog adalah mekanisme replication: setiap operasi tulis direkam di local.oplog.rs agar disalin ke anggota lain. Sisi baiknya, rekaman itu bisa kita baca:

js
db.getSiblingDB("local").oplog.rs.find(
  {}, { op: 1, ns: 1, o: 1, _id: 0 }
).sort({ $natural: -1 }).limit(3).toArray()

Output yang Dihasilkan:

text
[
  {
    op: 'i',
    ns: 'latihan_audit.pesanan',
    o: { _id: 2, pelanggan: 'Siti', total: 120000 }
  },
  {
    op: 'u',
    ns: 'latihan_audit.pesanan',
    o: { '$v': 2, diff: { i: { status: 'dibayar' } } }
  },
  {
    op: 'i',
    ns: 'latihan_audit.pesanan',
    o: { _id: 1, pelanggan: 'Budi', total: 250000 }
  }
]

Tiga entri terakhir menampilkan dua insert (op i) dan satu update (op u) pada latihan_audit.pesanan; field o memuat isi perubahannya — update tersimpan sebagai diff ($v dan diff) yang menjelaskan field mana yang ditambahkan. Sebagai alat audit, oplog punya tiga batasan: hanya menangkap operasi tulis (read tidak tercatat), berjangka waktu pendek karena entri lama terpotong, dan tidak memuat identitas user.

AlatMenangkapIdentitas userRetensi
Auditing (Enterprise)Auth, DDL, CRUD, operasi clusterYaFile terkelola + rotasi
ProfilerSemua operasi pada satu databaseYa, bila auth aktifCapped collection, sangat pendek
OplogOperasi tulis data sajaTidakWindow terbatas ukuran oplog

Sebelum lanjut, kita matikan profiler dan bersihkan database latihan:

js
db = db.getSiblingDB("latihan_audit")
db.setProfilingLevel(0)
db.dropDatabase()

Output yang Dihasilkan (diringkas serupa):

text
latihan_audit

{
  was: 2,
  slowms: 0,
  sampleRate: 1,
  ok: 1
}
{ ok: 1, dropped: 'latihan_audit' }

Auditing di Atlas #

MongoDB Atlas mendukung database auditing untuk cluster M10 ke atas. Alurnya naratif: buka pengaturan cluster, aktifkan Database Auditing, susun filter — bila perlu lewat audit filter builder yang berbasis form — lalu hasilnya bisa ditelusuri di log viewer atau diunduh untuk analisis eksternal. Filter-nya memakai sintaks yang sama dengan atype yang kita bahas di atas, sehingga pengetahuan tersebut langsung terpakai.

Rangkuman #

  • Auditing Enterprise diaktifkan lewat blok auditLog dengan tujuan file, syslog, atau console; filter membatasi event yang dicatat.
  • Satu event audit memuat atype, ts, local/remote, users, param, dan result — kode 18 menandai kegagalan authentication.
  • Community Edition memakai profiler (setProfilingLevel(2) + system.profile) untuk jejak operasi terbaru, dengan overhead sebagai harganya.
  • Oplog merekam semua operasi tulis beserta isinya, tetapi tanpa identitas user dan berwindow pendek.
  • Atlas menyediakan auditing siap pakai pada cluster M10 ke atas dengan filter berbasis skema yang sama.