Skip to content

Teknis — OPA Data

Service sinkronisasi data policy RAGA yang dibangun di atas Bun + Express 5. Bertugas menarik data user-role dan role-grant dari user-service, menggabungkannya ke dalam shared JSON file, lalu mendorong data tersebut ke OPA (Open Policy Agent) melalui data API. Dipanggil oleh user-service setiap kali ada perubahan role atau policy.

Repository

KeyValue
Git Remotehttps://git.tlab.co.id/tarantula/tarantula-v2/opa-bun/opa-data.git
Branch Aktifmain
bash
git clone https://git.tlab.co.id/tarantula/tarantula-v2/opa-bun/opa-data.git
cd opa-data

Tech Stack

LayerTeknologi
RuntimeBun 1
FrameworkExpress 5 (TypeScript)
HTTP ClientAxios
File I/OBun native (file, write)
Secret ManagementInfisical SDK v5
LoggingMorgan (HTTP request log)
Buildbun build --compile → binary tunggal

Environment Variables

Tidak ada file .env — semua variabel diinjeksikan sebagai env var container.

Bootstrap (env var container)

VariableDefaultKeterangan
NODE_PORT3666Port server Express
INFISICAL_SITE_URLhttps://app.infisical.comURL Infisical server
INFISICAL_CLIENT_IDClient ID Universal Auth
INFISICAL_CLIENT_SECRETClient Secret Universal Auth
INFISICAL_ENVIRONMENTEnvironment target (dev / staging / prod)
INFISICAL_PROJECT_IDID project Infisical
INFISICAL_PATHPath secrets di Infisical

Secrets via Infisical

VariableKeterangan
URL_USERBase URL user-service; digunakan untuk fetch /open-api/role-users dan /open-api/role-grants
URL_OPABase URL OPA server; digunakan untuk PUT data ke {URL_OPA}/v1/data

Endpoints

MethodPathKeterangan
GET/role-usersSync mapping user → role dari user-service ke OPA
GET/role-grantsSync mapping role → policy grants dari user-service ke OPA
GET/healthHealth check → { status: "UP" }

Jika response dari user-service bukan status 200, opa-data membalas 403 { info: "Conflict in timetable (blocked by OPA)" } (pesan bawaan dari kode, bukan konflik OPA sesungguhnya). Jika terjadi exception (mis. user-service atau OPA tidak dapat dihubungi), opa-data membalas 500 { info: "Internal Server Error" }.

Alur Sinkronisasi

Struktur Data di OPA

Data yang di-push ke OPA (PUT /v1/data) berbentuk JSON dengan struktur:

json
{
  "user_roles": {
    "john_doe": ["admin"],
    "jane_smith": ["viewer"]
  },
  "role_grants": {
    "admin": [
      { "id": 1, "name": "read", "label": "Read Workspace", "method": "GET", "path": "/workspace", "status": true },
      { "id": 2, "name": "write", "label": "Write Workspace", "method": "POST", "path": "/workspace", "status": true }
    ],
    "viewer": [
      { "id": 1, "name": "read", "label": "Read Workspace", "method": "GET", "path": "/workspace", "status": true }
    ]
  }
}

Isi tiap grant di role_grants[role] bukan hasil transformasi opa-data — melainkan disalin apa adanya dari field policies pada response GET /open-api/role-grants milik user-service (id, name, label, method, path, status). Field method, path, dan status-lah yang benar-benar dipakai oleh policy Rego di OPA Config (grant.method, grant.path dengan wildcard *, grant.status == true); id, name, dan label ikut terbawa hanya sebagai metadata referensi. Request PUT /v1/data ke OPA dikirim dengan header Content-Type: application/json-patch+json.

Data ini digunakan oleh policy Rego di OPA Config untuk membuat keputusan otorisasi yang kemudian dikonsumsi oleh OPA Auth.

File /share/data.json

File ini berada di volume bersama antara container opa-data dan OPA. Setiap sync:

  1. File dibaca (jika tidak ada, dibuat baru dengan {})
  2. Data baru di-merge (Object.assign) ke existing data
  3. File ditulis ulang
  4. Isi file yang sama di-PUT ke OPA data API

Posisi dalam Arsitektur

Build & Run

bash
# Install dependencies
bun install

# Jalankan development
bun run index.ts

# Build binary tunggal (digunakan di Docker)
bun build --compile --minify --sourcemap --target=bun-linux-x64 ./index.ts --outfile opa-data

# Jalankan binary
./opa-data

Docker

bash
docker build -t opa-data .
docker run -p 3666:3666 \
  -v /host/share:/share \
  -e INFISICAL_SITE_URL=http://... \
  -e INFISICAL_CLIENT_ID=... \
  -e INFISICAL_CLIENT_SECRET=... \
  -e INFISICAL_ENVIRONMENT=dev \
  -e INFISICAL_PROJECT_ID=... \
  -e INFISICAL_PATH=... \
  opa-data

Volume -v /host/share:/share diperlukan agar file data.json dapat dibaca oleh container OPA.