L424 Okt 2026EN · ID
Lock Instalasi yang Memblokir Aplikasi
Setelah test install sungguhan pertama untuk empat produk AI, semua panggilan AI gagal. Di salah satu produk, setiap analisis berakhir dengan 401 PermissionDenied dari Document Intelligence, Azure OpenAI, dan Prompt Shields. Padahal managed identity aplikasinya sudah memegang role yang benar.
Penyebabnya adalah lock yang sebenarnya bekerja sesuai tugasnya. Resource group milik managed application dikunci supaya tidak ada yang bisa mengubahnya selain publisher. Termasuk aplikasinya sendiri.
Semua ini terjadi di test install pada subscription uji. Paketnya sudah siap untuk Marketplace dan tervalidasi lewat instalasi sungguhan, tetapi offer di Partner Center belum dibuat, dan tidak ada yang berjalan untuk pelanggan berbayar.
Empat produk, satu instalasi per pelanggan
Di Metrodata saya mengerjakan empat produk AI: ARIA (voice agent realtime), Pris.AI (keamanan kode), MII E-Recruitment (screening CV), dan MII Fraud Detection (review fraud pada dokumen). Pada Oktober, keempatnya sedang disiapkan untuk Microsoft Marketplace.
Tanggal 7 Oktober, manajer saya memutuskan untuk menawarkan keempatnya sebagai Azure Application dengan plan Managed Application, bukan SaaS multi-tenant. Saya memimpin sisi engineering dari perubahan itu di keempat codebase. Dengan managed application, setiap pelanggan memasang salinannya sendiri di subscription Azure miliknya. Data pelanggan dan pemakaian Azure OpenAI tetap di sana, sementara publisher mengelola instalasi lewat managed resource group.
Struktur paket yang kami pakai berasal dari implementasi referensi seorang rekan tim untuk produk internal lain. Saya me-review-nya dan menyeragamkan keempat produk ke struktur itu, alih-alih membuat struktur kedua.
Azure melindungi managed resource group dengan lock. Pada level ReadOnly, Azure membuat system deny assignment di resource group tersebut. Semua pihak bisa membaca, tetapi hanya publisher yang bisa mengubah apa pun. Pelanggan tidak bisa mengganti app settings atau menukar kode di belakang publisher.
Satu instalasi berjalan seperti ini:
- Pelanggan memulai instalasi dari wizard di subscription miliknya.
- Deployment script di dalam managed resource group memverifikasi rilis yang ditandatangani dan membuat secret langsung di tempat.
- Tier aplikasi berjalan dengan managed identity miliknya sendiri.
- Setiap write atau panggilan data dari identity tersebut bertemu deny assignment. Hanya read dan pengecualian yang terdaftar yang lolos.
- Setelah itu, Azure RBAC menentukan apakah identity tersebut boleh bertindak.
Langkah 4 itulah inti tulisan ini.
Menguji seperti pelanggan memasang
Paketnya sudah lolos ARM-TTK dan pemeriksaan statis. Namun, belum ada satu pun yang dipasang dengan cara pelanggan memasangnya. Antara 18 dan 20 Oktober, saya menjalankan instalasi Service Catalog sungguhan di subscription uji. Ada satu sesi AI agent per produk yang menjalankan instalasi dengan sign-in Azure dan persetujuan saya.
Satu pilihan setup membuat hasilnya bermakna: saya memasang sebagai pelanggan, bukan sebagai publisher. Misalnya di definisi uji Pris.AI, publisher diwakili identity pengganti yang hanya punya Reader, dan akun saya sendiri berperan sebagai pelanggan, jadi deny assignment berlaku untuk saya persis seperti untuk pelanggan sungguhan.
Semua panggilan AI gagal
Gejalanya berbeda di tiap produk, tetapi mengarah ke hal yang sama:
- MII Fraud Detection: analisis berakhir
Failed, dengan 401 dari Document Intelligence, Azure OpenAI, dan Prompt Shields. - ARIA: tidak ada panggilan AI yang berhasil.
- Pris.AI: backend tidak bisa memanggil Azure OpenAI, mengirim ke Service Bus, atau menulis secret di Key Vault.
- MII E-Recruitment: tidak ada panggilan AI, tidak ada blob write, dan task hub Durable Functions tidak bisa berjalan.
Sebagian panggilan tetap berhasil. Read ke Cosmos DB dan Key Vault lancar.
Role assignment-nya benar, jadi saya berhenti memeriksanya dan membaca deny assignment di managed resource group. Pengecualiannya hanya berisi satu pola, */read, dan satu-satunya principal yang dikecualikan adalah publisher. Setiap aksi yang bukan read ditolak untuk semua principal lain, termasuk managed identity milik instalasi itu sendiri.
Itu cocok dengan gejalanya. Completion Azure OpenAI, analisis Document Intelligence, pengiriman ke Service Bus, dan blob write semuanya data action yang bukan read, jadi deny assignment menolaknya sebelum RBAC sempat diperiksa. Read tetap diizinkan. Cosmos DB mengotorisasi data lewat RBAC data-plane miliknya sendiri, dan sejauh yang saya pahami, itulah sebabnya Cosmos DB tetap berjalan.
Saya juga membuat managed application probe kecil untuk menguji perilaku lock secara terpisah, di luar template produk.
Daftar pendek, dengan alasan di setiap baris
Managed application bisa membawa pengecualian untuk deny assignment-nya: allowed control actions dan allowed data actions. Di Partner Center, pengecualian ini ada di technical configuration milik plan. Di definisi Service Catalog, pengecualian ini ada di locking policy. Setiap produk mendapat daftarnya sendiri, terhubung ke keduanya, dengan alasan untuk setiap entri.
Bentuknya kira-kira seperti ini. Ini ilustrasi, bukan file produksi:
{
"allowedDataActions": [
{
"action": "Microsoft.CognitiveServices/accounts/OpenAI/deployments/chat/completions/action",
"why": "AI summaries and chat (backend identity)"
},
{
"action": "Microsoft.ServiceBus/namespaces/messages/send/action",
"why": "Scan jobs are queued (backend identity)"
}
]
}
Bagian yang paling lama saya terima: pengecualian tidak dibatasi untuk aplikasi saja. Pengecualian membuka deny assignment untuk semua principal. RBAC tetap menentukan siapa yang boleh bertindak. Pelanggan tidak bisa membuat role assignment di dalam managed resource group, jadi pengecualian data action terutama berpengaruh pada identity yang sudah memegang role di sana. Control action lebih berisiko, karena pelanggan bisa saja memegang role di level subscription. Setiap entri memperluas apa yang bisa dilakukan siapa pun yang memegang role yang tepat, di dalam instalasi yang menjadi tanggung jawab publisher.
Karena itu daftarnya harus tetap pendek, dan sebuah build check menjaganya. Di MII E-Recruitment, build paket menolak entri tanpa alasan, aksi Authorization atau Key Vault apa pun, tag write, wildcard polos, write ke app settings, dan aksi code-publish. Aturannya berbeda per produk. Pris.AI tetap menyimpan satu write ke Key Vault, karena alur setup-nya menyimpan key GitHub App milik pelanggan, dan entri itu membawa alasannya seperti entri lain.
Setelah perbaikan, probe data-plane ARIA mengembalikan 200 dari Azure OpenAI, Speech, Language, dan Content Safety, serta 202 dari Document Intelligence. Untuk MII Fraud Detection, pengecualian yang baru dikonfirmasi pada instance yang sudah terpasang.
Temuan ini berasal dari instalasi MII Fraud Detection. Saya menyalinnya ke MII E-Recruitment sebelum instalasi berikutnya untuk produk itu, supaya kegagalan yang sama tidak ditemukan ulang produk demi produk.
Lock yang sama, tiga kali lagi
Lock ini muncul lagi dalam bentuk lain:
- Deployment kode. Awalnya MII E-Recruitment membutuhkan aksi code-publish di daftar pengecualiannya, yang bisa dipakai principal mana pun yang memegang role. Saat memperbaiki race deployment pada Kudu yang masih cold, saya memindahkan deployment kode ke dalam template dengan langkah warm-up, lalu menghapus pengecualian publish sepenuhnya. Di instalasi berikutnya, identity installer mendapat 403 saat publish. Bug reliability justru menghasilkan perbaikan keamanan.
- Token yang di-cache sehari. App Service bisa menyimpan token managed identity sampai 24 jam. Di ARIA, role assignment salah satu service baru muncul setelah token pertamanya terbit, sehingga panggilan antar-service mendapat 403. Restart aplikasi akan memperbarui token, tetapi pelanggan tidak bisa me-restart aplikasi di dalam resource group yang terkunci. Kini service itu juga menerima peer-nya lewat object ID yang di-pin.
- Key Vault reference yang ter-cache sebagai ditolak. Di MII E-Recruitment, reader role dibuat setelah App Service telanjur menyimpan penolakan, dan restart tidak membantu. Perbaikannya menambahkan reader role dan refresh reference di health gate. Aksi otorisasi untuk panggilan refresh itu bukan operasi yang terdaftar, sehingga locking policy menolaknya berdasarkan nama. Solusinya adalah wildcard app-settings yang terdaftar, dengan alasan tertulis di sampingnya.
36 defect sebelum instalasi bersih
Deny assignment adalah defect yang paling banyak mengajari saya, tetapi bukan satu-satunya. Di keempat produk, instalasi menemukan 36 defect yang memblokir instalasi: 14 di ARIA, 12 di MII E-Recruitment, 5 di Pris.AI, dan 5 di MII Fraud Detection. Setiap instalasi yang gagal saya perlakukan sebagai temuan dengan root cause, perbaikan, dan run ulang. Selain lock, kelas utamanya adalah:
- Plan private yang terblokir karena urutan: worker job dibuat sebelum network peering dan DNS link yang dibutuhkannya, serta firewall storage di depan deployment script.
- Deployment script gagal karena container image Azure CLI tidak memiliki tool seperti
awk,unzip, ataucurl. - Paket rilis kehilangan file runtime yang ada di repository. Repository-nya benar; artefaknya yang tidak.
- Upgrade yang gagal karena tag pada Key Vault key yang immutable, dan langkah drain yang bisa membuat voice service menolak panggilan.
- Kuota Container Instances di region instalasi yang sudah terpakai tim lain.
Setelah itu, pemeriksaan pasca-instalasi lolos:
| Produk | Hasil | |---|---| | ARIA | 25/25 public, 22/22 private, dan upgrade dengan drain (sekitar 10,5 menit) | | Pris.AI | 16/16 public, 24/24 private | | MII E-Recruitment | Dua instalasi 0.1.1 yang lolos, lalu 0.1.2 tanpa pengecualian publish | | MII Fraud Detection | 2 dari 5 percobaan berhasil (Starter public, Enterprise private) |
Semua resource uji dihapus setelahnya.
Posisinya sekarang
Paketnya siap untuk Marketplace dan tervalidasi lewat test install Service Catalog sungguhan. Metrodata sudah terdaftar di Partner Center, tetapi offer-nya belum dibuat atau disertifikasi. Metering sudah diimplementasikan di keempat produk, nonaktif secara default, dan belum pernah memanggil Metering API live, karena offer-nya memang belum ada.
Beberapa pemeriksaan masih terbuka: pemeriksaan interaktif pada instance yang terpasang (sign-in admin pertama dengan MFA dan alur AI live), sandbox CreateUiDefinition di portal, serta latihan upgrade dan rollback untuk tiga dari empat produk. Catatan instalasi Pris.AI menyebutnya dengan jelas: pemeriksaan otomatis yang hijau tidak membuktikan setiap pengecualian secara end to end. Satu scan sungguhan dan satu giliran chat pada instance yang terpasang yang membuktikannya.
Yang akan saya lakukan secara berbeda
- Uji platformnya lebih dulu. Perilaku lock adalah sifat Azure, bukan kode kami. Saya mempelajarinya dari empat produk yang gagal. Satu instalasi kecil yang terkunci sebelum paket pertama sudah cukup untuk memperlihatkannya.
- Rancang daftar pengecualian bersama role. Setiap role assignment untuk identity aplikasi memunculkan pertanyaan kedua: apakah deny assignment akan meloloskan aksi ini? Sekarang saya menulis keduanya berdampingan di desain.
- Jalankan pemeriksaan interaktif di jendela yang sama. Pemeriksaan otomatis lolos, tetapi bukti end to end masih tertunda. Celah itu seharusnya ditutup selagi test install masih ada.
Lock yang melindungi instalasi juga membatasi aplikasi di dalamnya. Pengecualiannya adalah bagian dari desain keamanan, dan perlu di-review seketat izin lainnya.