Otorisasi MCP dengan Cerbos: Policy-as-Code untuk AI Agent

Foto oleh Unsplash

Foto oleh Unsplash
Model Context Protocol (MCP) oleh Anthropic memungkinkan AI agent memanggil tool — membaca file, query database, mengirim email, menghapus record. Itu powerful. Ini juga masalah keamanan yang menunggu terjadi jika setiap pengguna yang bisa chat dengan agent-mu juga bisa memanggil delete_record atau send_invoice. Sebagian besar implementasi MCP yang saya lihat tidak memiliki otorisasi sama sekali atau hard-code pemeriksaan peran di dalam setiap handler tool. Cerbos adalah solusi bersih: engine otorisasi policy-as-code yang berjalan sebagai sidecar.
Ketika kamu membangun server MCP untuk alat internal — misalnya, asisten ERP yang bisa query purchase order, menyetujui invoice, dan mengirim notifikasi — kamu tidak ingin setiap karyawan memiliki akses ke setiap kemampuan. Petugas gudang harus bisa membaca record inventaris tapi tidak menyetujui penggajian. Manajer harus menyetujui invoice tapi tidak menghapusnya.
Cerbos (cerbos.dev) adalah engine otorisasi open-source yang agnostik terhadap bahasa. Kamu menulis kebijakan dalam YAML yang mendefinisikan peran mana yang dapat melakukan aksi mana pada tipe resource mana. Cerbos berjalan sebagai container sidecar (atau layanan mandiri) dan mengekspos REST dan gRPC API. Aplikasimu memanggil Cerbos dengan principal (pengguna + peran + atribut) dan resource dan mendapatkan keputusan allow/deny.
Tool MCP diidentifikasi dengan nama — tool seperti 'read_orders', 'approve_invoice', 'delete_record', 'send_email'. Server MCP-mu menerima permintaan panggilan tool dari klien. Tanpa middleware otorisasi, server mengeksekusi setiap panggilan tool dari sesi yang terotentikasi. Perbaikannya adalah layer middleware yang mencegat setiap panggilan tool dan bertanya kepada Cerbos: 'Apakah principal ini diizinkan untuk memanggil tool ini?'
MCP Authorization Flow with Cerbos
User / Agent Client
│
│ MCP tool call request
│ { tool: "delete_record", principal: { id, role } }
▼
┌───────────────────────────────────┐
│ MCP Server │
│ ┌────────────────────────────┐ │
│ │ Auth Middleware │ │
│ │ 1. Extract JWT / API key │ │
│ │ 2. Build principal obj │ │
│ └────────────┬───────────────┘ │
└───────────────┼───────────────────┘
│ CheckResourceRequest
▼
┌───────────────────────────────────┐
│ Cerbos PDP (sidecar) │
│ ┌────────────────────────────┐ │
│ │ Policy Engine │ │
│ │ resource: mcp_tool │ │
│ │ action: call │ │
│ │ principal.role → ALLOW? │ │
│ └────────────┬───────────────┘ │
└───────────────┼───────────────────┘
│ { allowed: true | false }
▼
┌───────────────┐
│ ALLOW │──▶ Tool Execution → Response
│ DENY │──▶ 403 Forbidden
└───────────────┘Jalankan Cerbos sebagai sidecar Docker dengan --set=server.logLevel=info dan mount direktori kebijakan-mu sebagai volume. Dengan cara ini, memperbarui file YAML kebijakan memicu hot reload di Cerbos tanpa memulai ulang server MCP-mu. Di produksi, gunakan Cerbos Hub (layanan terkelola mereka) untuk penyimpanan kebijakan dengan audit logging dan deployment kebijakan gaya GitOps.
Menjalankan Cerbos secara lokal membutuhkan sekitar lima menit. Mulai sidecar, tulis kebijakan resource untuk tool MCP-mu, dan panggil REST atau gRPC API Cerbos dari middleware server MCP-mu. YAML kebijakan mendefinisikan resource (mcp_tool), aksi (call), peran (admin, pro, free), dan kondisi (nama tool spesifik mana yang diizinkan untuk setiap peran).
Untuk produk SaaS di mana setiap organisasi pelanggan memiliki pengguna dan perannya sendiri, Cerbos mendukung scoping kebijakan per tenant. Kamu menambahkan field scope ke principal-mu yang mengidentifikasi organisasi, dan menulis kebijakan yang di-scope yang hanya berlaku untuk tenant tersebut. Ini memungkinkan satu instance Cerbos melayani semua tenant-mu tanpa konflik kebijakan.
# cerbos/policies/mcp_tool.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
version: "default"
resource: mcp_tool
rules:
# Admin can call any tool
- actions: ["*"]
effect: EFFECT_ALLOW
roles: ["admin"]
# Pro users can call data tools but not destructive ones
- actions: ["call"]
effect: EFFECT_ALLOW
roles: ["pro"]
condition:
match:
expr: >
resource.attr.toolName in [
"read_records", "search_records",
"create_record", "update_record",
"generate_report", "export_csv"
]
# Free users: read-only tools only
- actions: ["call"]
effect: EFFECT_ALLOW
roles: ["free"]
condition:
match:
expr: >
resource.attr.toolName in ["read_records", "search_records"]
---
# MCP Server middleware — TypeScript
import { GRPC as Cerbos } from "@cerbos/grpc"
const cerbos = new Cerbos("localhost:3593", { tls: false })
export async function checkToolPermission(
principal: { id: string; role: string; attributes?: Record<string, unknown> },
toolName: string
): Promise<boolean> {
const decision = await cerbos.checkResource({
principal: {
id: principal.id,
roles: [principal.role],
attributes: principal.attributes ?? {},
},
resource: {
kind: "mcp_tool",
id: toolName,
attributes: { toolName },
},
actions: ["call"],
})
return decision.isAllowed("call")
}
// Usage in MCP tool handler
server.tool("delete_record", async (args, context) => {
const allowed = await checkToolPermission(
{ id: context.user.id, role: context.user.role },
"delete_record"
)
if (!allowed) {
throw new McpError(
ErrorCode.MethodNotFound,
"You do not have permission to call delete_record"
)
}
// proceed with deletion...
return await deleteRecord(args.id)
})Kekuatan kebijakan Cerbos adalah deklaratif dan dapat diaudit. File kebijakan memberi tahu non-developer dengan tepat siapa yang bisa melakukan apa. Kamu bisa menambahkan kondisi menggunakan Common Expression Language (CEL) — misalnya, hanya izinkan aksi delete pada record yang dibuat oleh principal, atau hanya izinkan read pada record di mana status != 'confidential'.
Jalan pintas umum adalah melewatkan otorisasi pada tool MCP read-only karena 'read tidak bisa menyebabkan kerusakan.' Tapi akses read ke data yang salah adalah pelanggaran data. Tool record HR tidak boleh dapat dibaca oleh semua orang — hanya staf HR. Tool pelaporan keuangan tidak boleh mengekspos data transaksi mentah ke peran non-keuangan. Terapkan kebijakan Cerbos ke setiap tool MCP.
Cerbos memiliki framework pengujian kebijakan bawaan — kamu menulis file YAML tes di samping file kebijakan-mu yang mendefinisikan fixture tes dengan principal, resource, dan hasil yang diharapkan (allow/deny). Jalankan 'cerbos compile .' untuk memvalidasi kebijakan dan 'cerbos test .' untuk menjalankan semua tes kebijakan.
Di produksi, deploy Cerbos sebagai sidecar di pod yang sama dengan server MCP-mu (Kubernetes) atau VM yang sama. Jaga komunikasi tetap lokal (localhost:3593) untuk meminimalkan latensi — keputusan Cerbos biasanya sub-milidetik di mesin yang sama. Gunakan Cerbos Hub untuk manajemen kebijakan jika kamu menginginkan audit trail, deployment GitOps, dan UI web untuk pengeditan kebijakan. Instance Cerbos yang gagal harus fail-closed (tolak semua) bukan fail-open.