Authentication sudah menjawab “siapa yang terhubung”; sekarang server perlu menjawab “identitas ini boleh melakukan apa”. Jawaban MongoDB atas pertanyaan itu adalah Role-Based Access Control (RBAC): hak akses tidak diberikan langsung ke user, melainkan dikemas dalam role yang bisa dipakai ulang. Chapter ini membongkar anatomi privilege, memetakan role bawaan yang tersedia, lalu membangun role kustom ketika role bawaan terlalu besar atau terlalu kecil.

Peta materi Chapter ini:

  • Anatomi privilege: pasangan resource + actions.
  • Peta role bawaan dan use case-nya, termasuk peringatan untuk root.
  • Role kustom dengan db.createRole(): privilege presisi pada satu collection.
  • Penerusan role (inheritance) lewat field roles.

Privilege: Resource dan Actions #

Satu privilege selalu memuat dua bagian: resource (di mana) dan actions (apa yang boleh dilakukan). Resource bisa berupa satu collection, seluruh database, cluster, atau kombinasi khusus. Actions adalah daftar operasi seperti find, insert, remove, atau createIndex. Role adalah sekumpulan privilege — dan role juga bisa mewarisi role lain lewat field roles.

Kita intip isi role bawaan read langsung dari server latihan:

js
use latihan_uji
const privilegePertama = db.getRole("read", { showPrivileges: true }).privileges[0]
printjson(privilegePertama)

Output yang Dihasilkan:

text
switched to db latihan_uji

{
  resource: {
    db: 'latihan_uji',
    collection: ''
  },
  actions: [
    'changeStream',
    'collStats',
    'dbHash',
    'dbStats',
    'find',
    'killCursors',
    'listCollections',
    'listIndexes',
    'listSearchIndexes',
    'planCacheRead',
    'performRawDataOperations'
  ]
}

Terbaca dua bagian itu persis: resource { db: "latihan_uji", collection: "" } berarti seluruh collection di latihan_uji (string kosong adalah wildcard collection), dan actions-nya dipimpin find — operasi baca inti — ditemani actions pendukung seperti listCollections dan dbStats. Method db.getRole() di atas adalah pembungkus dari perintah rolesInfo; tambahkan showBuiltinRoles: true bila ingin melihat role bawaan pada database admin.

Peta Role Bawaan #

MongoDB mengirim role bawaan yang menutupi kebutuhan umum. Mengenal peta ini menghemat banyak keputusan:

RoleBerlaku diUse case
readSemua dbDashboard analitik, pelaporan read-only
readWriteSemua dbUser aplikasi CRUD standar
dbAdminSemua dbMaintenance satu database: index, statistik, validasi
dbOwnerSemua dbPemilik penuh satu database (readWrite + dbAdmin + userAdmin)
userAdminSemua dbMengelola user dan role pada satu database
clusterMonitoradminMonitoring cluster read-only (serverStatus, replSetGetStatus)
backup / restoreadminMenjalankan mongodump / mongorestore
rootadminSemua hal di semua database

Varian readAnyDatabase, readWriteAnyDatabase, dbAdminAnyDatabase, dan userAdminAnyDatabase adalah versi lintas-database dari empat role pertama, dan semuanya hanya bisa diberikan dari database admin. Role backup dan restore sengaja dipisahkan — tugas pencadangan rutin hanya butuh backup, dan restore yang lebih berbahaya hanya dipasang saat pemulihan.

Role Kustom #

Role bawaan selalu menyapu satu database penuh. Ketika sebuah aplikasi hanya boleh membaca satu collection — misalnya layanan katalog yang hanya butuh collection buku — role kustom memberi privilege presisi. Kita buat role pembaca khusus:

js
db.buku.drop()
db.buku.insertOne({ judul: "Bumi", penulis: "Tere Liye", harga: 89000 })
db.createRole({
  role: "bacaJudulBuku",
  privileges: [
    { resource: { db: "latihan_uji", collection: "buku" }, actions: ["find"] }
  ],
  roles: []
})
db.getRole("bacaJudulBuku", { showPrivileges: true })

Output yang Dihasilkan (bagian $clusterTime dan operationTime yang berulang diringkas):

text
true
{
  acknowledged: true,
  insertedId: ObjectId('6ad3bede35f0a6cf9b086b48')
}
{ ok: 1 }
{
  _id: 'latihan_uji.bacaJudulBuku',
  role: 'bacaJudulBuku',
  db: 'latihan_uji',
  privileges: [
    {
      resource: { db: 'latihan_uji', collection: 'buku' },
      actions: [ 'find' ]
    }
  ],
  roles: [],
  inheritedRoles: [],
  inheritedPrivileges: [
    {
      resource: { db: 'latihan_uji', collection: 'buku' },
      actions: [ 'find' ]
    }
  ],
  isBuiltin: false
}

Bedah bagiannya:

  1. privileges: satu privilege berisi tepat satu resource — collection buku di latihan_uji — dengan satu action find. Tidak ada action tulis, tidak ada collection lain.
  2. roles: []: role ini tidak mewarisi role lain. Field inilah jalur inheritance — isi dengan [{ role: "read", db: "latihan_uji" }] dan role kustom langsung mewarisi seluruh privilege read.
  3. db.getRole(): mengembalikan definisi tersimpan; inheritedPrivileges menunjukkan privilege efektif setelah semua warisan dihitung.

Role kustom dipakai persis seperti role bawaan — sebagai entri roles pada db.createUser() atau grantRolesToUser():

js
db.createUser({
  user: "budi_pembaca",
  pwd: "sandiBudi123",
  roles: [{ role: "bacaJudulBuku", db: "latihan_uji" }]
})
db.getUsers()

Output yang Dihasilkan (diringkas serupa):

text
{ ok: 1 }
{
  users: [
    {
      _id: 'latihan_uji.budi_pembaca',
      userId: UUID('2c8cb6a5-4787-405d-b854-7b6bb3ed670c'),
      user: 'budi_pembaca',
      db: 'latihan_uji',
      roles: [ { role: 'bacaJudulBuku', db: 'latihan_uji' } ],
      mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
    }
  ],
  ok: 1
}

Pada server dengan authorization aktif, user budi_pembaca kini hanya bisa menjalankan find pada latihan_uji.buku — mencoba membaca collection lain atau menulis akan ditolak. Server latihan kita tidak menegakkan aturan itu, tetapi struktur data role dan user-nya nyata dan persis seperti produksi.

Terakhir, kita rapikan semua artefak percobaan:

js
db.dropUser("budi_pembaca")
db.dropRole("bacaJudulBuku")
db.buku.drop()
db.getRoles()

Output yang Dihasilkan (bagian $clusterTime dan operationTime yang berulang diringkas):

text
{ ok: 1 }
{ ok: 1 }
true
{
  roles: [],
  ok: 1
}

Perlu diketahui: db.dropRole() segera mencabut role yang dihapus dari semua user pemegangnya — user yang kehilangan satu-satunya role menjadi tanpa hak akses. Kita menjatuhkan user dahulu agar tidak menyisakan user menganggur. Pengelolaan role lanjutan (updateRole, grantPrivilegesToRole, grantRolesToRole) mengikuti pola yang sama dengan manajemen user di chapter sebelumnya.

Rangkuman #

  • Privilege = resource (di mana) + actions (apa); role adalah kumpulan privilege dan bisa mewarisi role lain.
  • Mulai dari role bawaan: read/readWrite untuk aplikasi, dbAdmin/dbOwner untuk operasional, clusterMonitor/backup untuk tugas khusus.
  • Varian *AnyDatabase, clusterMonitor, backup, restore, dan root hidup di database admin.
  • db.createRole() merakit privilege presisi — misalnya find pada satu collection — untuk kebutuhan yang tidak pas dengan role bawaan.
  • root dan userAdmin di admin adalah tiket superuser: simpan sebagai akun darurat, bukan user harian.