Skip to content

Teknis — OPA Config

Image yang menjalankan OPA (Open Policy Agent) server RAGA beserta policy Rego-nya. Bukan service HTTP kustom seperti opa-auth/opa-data — image ini hanya membungkus binary opa resmi, CLI Infisical, dan file policy, lalu menjalankan opa run --server yang diseklankan oleh subsistem OPA lainnya.

Repository

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

Tech Stack

LayerTeknologi
Base ImageAlpine 3.20
Policy EngineOPA binary v1.5.1 (diunduh langsung dari rilis GitHub saat build image)
Bahasa PolicyRego
Secret ManagementInfisical CLI (bukan SDK) — dijalankan lewat infisical run --watch

Environment Variables

Tidak ada file .env runtime — running.sh membaca variabel bootstrap dari environment container, lalu Infisical CLI menyuntikkan sisanya sebagai environment variable ke proses opa run.

VariableKeterangan
INFISICAL_CLIENT_IDClient ID Universal Auth (wajib, dicek di awal running.sh)
INFISICAL_CLIENT_SECRETClient Secret Universal Auth (wajib)
INFISICAL_PATHPath secrets di Infisical
INFISICAL_PROJECT_IDID project Infisical
INFISICAL_ENVIRONMENTEnvironment target (dev / staging / prod)
JWT_SECRETDideklarasikan di .env.example ("samakan dengan yang ada di user-service") untuk dipakai policy Rego memverifikasi signature JWT lewat opa.runtime()["env"]["JWT_SECRET"]

Struktur File

opa-config/
├── Dockerfile          # Alpine + binary opa + Infisical CLI
├── running.sh           # Entrypoint: login Infisical → jalankan `opa run --server`
├── config.yml            # Konfigurasi OPA server (decision log, dll — saat ini nonaktif)
├── policy.rego           # Policy Rego aktif (dimuat oleh running.sh)
├── policy.old.rego       # Varian policy sebelumnya (tidak dimuat)
├── policy.new.v0.rego    # Draft varian policy berikutnya (tidak dimuat)
└── .env.example

Hanya policy.rego yang dimuat oleh running.sh (lihat perintah di bawah). policy.old.rego dan policy.new.v0.rego ada di repo sebagai riwayat/draft, tidak aktif di runtime.

Startup (running.sh)

bash
# 1. Login ke Infisical pakai Universal Auth
export INFISICAL_TOKEN=$(infisical login \
  --method=universal-auth \
  --client-id="$INFISICAL_CLIENT_ID" \
  --client-secret="$INFISICAL_CLIENT_SECRET" \
  --silent --plain)

# 2. Jalankan OPA server dengan secret ter-inject sebagai env var,
#    memuat config, data, dan policy dari volume /share
exec infisical run --watch --path="$INFISICAL_PATH" --projectId="$INFISICAL_PROJECT_ID" --env="$INFISICAL_ENVIRONMENT" -- \
  opa run --log-level=debug --server --addr 0.0.0.0:8181 -c /share/config.yml /share/data.json /share/policy.rego

--watch membuat Infisical CLI memantau perubahan secret dan me-restart proses opa run bila ada update — sehingga rotasi secret di Infisical tidak butuh redeploy manual, kecuali untuk secret yang dihardcode langsung di file policy (lihat catatan di bawah).

Konfigurasi OPA Server (config.yml)

Saat ini seluruh isi config.yml dalam keadaan commented out — OPA server berjalan dengan pengaturan default (tanpa decision log ke service eksternal). Jika diaktifkan, konfigurasi ini akan mengirim setiap keputusan otorisasi ke service logger (opa-logger-v2) untuk audit trail:

yaml
# services:
#   logger:
#     url: http://opa-logger-v2:3000
# decision_logs:
#   console: true
#   service: logger
#   reporting:
#     min_delay_seconds: 0
#     max_delay_seconds: 1

Alur Keputusan Policy (policy.rego)

Policy verify_access menerima input: { method, token, path } dari opa-auth dan mengevaluasi lewat rule berikut:

RuleFungsi
tokenMemverifikasi signature JWT (HS256) lalu mendekode payload-nya. Gagal verifikasi → is_token_valid: false.
is_token_not_expTrue jika token.payload.exp belum lewat waktu sekarang.
user_rolesDiambil dari data.user_roles[token.payload.username] — data yang disuplai OPA Data.
user_is_grantedMenggabungkan seluruh grant dari data.role_grants[role] untuk semua role milik user.
path_matchesMencocokkan grant.path dengan input.path per segmen, mendukung wildcard * pada satu segmen.
user_casesGrant yang method-nya cocok, status == true, dan path-nya match.
allowtrue jika: method OPTIONS, atau path adalah /auth/login / /auth/refresh-token (whitelist tanpa token), atau (token belum expired dan ada minimal satu user_cases yang cocok).

Catatan teknis: policy.rego yang aktif saat ini memverifikasi signature JWT dengan secret yang di-hardcode langsung di file policy, bukan dibaca dari environment variable JWT_SECRET seperti pada policy.old.rego/policy.new.v0.rego. Akibatnya, rotasi JWT_SECRET di Infisical/user-service tidak akan otomatis diikuti oleh policy yang sedang aktif — perlu penyelarasan agar mekanismenya konsisten dengan dua varian file lain.

Build & Run

bash
docker build -t opa-config .

docker run -p 8181:8181 \
  -v /host/share:/share \
  -e INFISICAL_CLIENT_ID=... \
  -e INFISICAL_CLIENT_SECRET=... \
  -e INFISICAL_PATH=... \
  -e INFISICAL_PROJECT_ID=... \
  -e INFISICAL_ENVIRONMENT=dev \
  opa-config

Volume -v /host/share:/share wajib ada dan sama dengan volume yang dipakai OPA Dataconfig.yml, data.json, dan policy.rego semuanya dibaca dari path /share.