Anda telah men-deploy Azure Function menggunakan Docker ke produksi, semuanya terlihat baik, tetapi ketika Anda mencoba memanggil endpoint fungsi Anda, Anda mendapatkan kesalahan 401 Unauthorized yang membuat frustrasi:
curl -X POST \ "https://my-prod-functions.azurewebsites.net/api/MyFunction?code=my-function-key" \ -H "Content-Type: application/json" # Response: 401 Unauthorized
Sementara itu, lingkungan pengembangan non-dockerized Anda bekerja dengan sempurna dengan kode dan kunci yang sama persis. Apa yang terjadi?
Pertama, saya memeriksa semua tersangka biasa:
AuthorizationLevel.Function dalam kode saya.Application Insights mengungkapkan sesuatu yang menarik:
Request successfully matched the route with name 'MyFunction' and template 'api/MyFunction' Executing StatusCodeResult, setting HTTP status code 401
Permintaan berhasil mencapai fungsi dan mencocokkan rute, tetapi Azure mengembalikan 401 sebelum kode bahkan dieksekusi. Ini berarti masalahnya ada pada lapisan autentikasi runtime Azure Functions, bukan dalam kode saya.
Saya memeriksa variabel lingkungan melalui konsol Kudu (https://my-functions.scm.azurewebsites.net) dan menemukan:
AzureWebJobsSecretStorageType = files WEBSITES_ENABLE_APP_SERVICE_STORAGE = false # I THOUGHT THIS IS THE PROBLEM!
Inilah yang terjadi:
Azure Functions dapat menyimpan kunci autentikasi dengan dua cara:
AzureWebJobsSecretStorageType = files)/home/data/Functions/secrets/AzureWebJobsSecretStorageType = blob)Ketika Anda mengatur WEBSITES_ENABLE_APP_SERVICE_STORAGE = false (umum untuk kontainer Docker stateless), Azure tidak memasang penyimpanan persisten ke kontainer Anda.
Ini berarti:
Mari saya verifikasi ini di kontainer:
# SSH into container or via Kudu ls -la /home/data/ # Result: No such file or directory ls -la /azure-functions-host/Secrets/ #Result: No such file or directory
Direktori rahasia tidak ada karena penyimpanan tidak terpasang!
Ketika awalnya saya mencoba memperbaiki ini dengan mengatur WEBSITES_ENABLE_APP_SERVICE_STORAGE = true, autentikasi berhasil tetapi saya malah mendapatkan 404 Not Found!
\ Mengapa? Karena pemasangan penyimpanan persisten Azure di /home/site/wwwroot/ menimpa file aplikasi kontainer Docker saya. Direktori yang terpasang hanya memiliki host.json tetapi tidak ada DLL terkompilasi (dalam kontainer docker, bukan kontainer host, sangat penting untuk diingat bahwa ada dua kontainer di sini: kontainer host dan kontainer docker aplikasi) sehingga runtime Azure Functions menemukan 0 fungsi untuk dimuat, jadi ketika permintaan masuk, Autentikasi berhasil (kunci dalam blob) tetapi Fungsi tidak ditemukan sehingga kita mendapatkan 404. Singkatnya, opsi ini membuat host menemukan file kunci fungsi (sehingga autentikasi berhasil) tetapi kehilangan fungsi itu sendiri. Kita tidak bisa menggunakannya dan WEBSITES_ENABLE_APP_SERVICE_STORAGE harus false.
Perbaikan yang benar untuk Azure Functions yang di-Dockerized adalah menggunakan penyimpanan rahasia berbasis blob:
Di Azure Portal:
AzureWebJobsSecretStorageTypeblobWEBSITES_ENABLE_APP_SERVICE_STORAGE adalah falseKlik Save, kemudian mulai ulang function app. Azure akan secara otomatis:
azure-webjobs-secrets di akun penyimpanan AndaBuka Portal → Function App → Functions → [Fungsi Anda] → Function Keys
Salin kunci dari Portal (ini adalah versi yang didekripsi).
curl -X POST \ "https://my-prod-functions.azurewebsites.net/api/MyFunction?code=<KEY_FROM_PORTAL>" \ -H "Content-Type: application/json" \ -d '{"test": "data"}' # Response: 200 OK
Memahami Enkripsi Kunci
Ketika Anda memeriksa penyimpanan blob, Anda akan melihat kunci disimpan seperti ini:
{ "keys": [ { "name": "default", "value": "CfDJ8AAAAAAA...encrypted-value...", "encrypted": true } ] }
Penting: Anda tidak dapat menggunakan nilai terenkripsi ini secara langsung! Azure secara otomatis:
Selalu dapatkan kunci Anda dari UI Azure Portal, yang menampilkan versi yang didekripsi.
FROM mcr.microsoft.com/azure-functions/dotnet:4 AS base WORKDIR /home/site/wwwroot EXPOSE 80 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY ["MyFunction/MyFunction.csproj", "MyFunction/"] RUN dotnet restore "MyFunction/MyFunction.csproj" COPY . . WORKDIR "/src/MyFunction" RUN dotnet build "MyFunction.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "MyFunction.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /home/site/wwwroot COPY --from=publish /app/publish . ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ AzureFunctionsJobHost__Logging__Console__IsEnabled=true
\
# Secret storage configuration AzureWebJobsSecretStorageType = blob AzureWebJobsStorage = <your-storage-connection-string> # Docker configuration WEBSITES_ENABLE_APP_SERVICE_STORAGE = false WEBSITE_RUN_FROM_PACKAGE = 0 # Functions runtime FUNCTIONS_WORKER_RUNTIME = dotnet FUNCTIONS_EXTENSION_VERSION = ~4
Masalah ini khusus untuk Docker + Azure Functions karena:
Aplikasi fungsi non-dockerized tidak memiliki masalah ini karena mereka secara alami memiliki akses ke sistem file App Service.
Masalah: Azure Functions yang di-Dockerized mengembalikan 401 saat menggunakan penyimpanan rahasia berbasis file tanpa volume yang terpasang.
Solusi: Gunakan penyimpanan rahasia berbasis blob, yang stateless dan ramah Docker.
Pengaturan Kunci:
AzureWebJobsSecretStorageType = blob WEBSITES_ENABLE_APP_SERVICE_STORAGE = false
Konfigurasi ini memungkinkan kontainer Docker Anda tetap stateless sambil tetap mengakses kunci autentikasi dengan aman dari Azure Blob Storage.
Memecahkan masalah serupa? Jangan ragu untuk menghubungi di komentar di bawah!

