AZ-500 LAB 18 ~60 phút Chương 04 Managed Identity

User-assigned Managed Identity cho App Service

Tạo user-assigned managed identity như một Azure resource độc lập, gán cho App Service, cấp quyền Key Vault Secrets User (RBAC), và xác minh App Service đọc secret từ Key Vault qua IMDS token — identity có thể tái sử dụng cho nhiều resource khác nhau.

🎯 Mục Tiêu Lab

Tạo user-assigned managed identity như Azure resource độc lập (không gắn với VM/App)

Tạo App Service Plan và App Service (Web App) trên Linux

Gán user-assigned MI cho App Service và xác nhận trong Identity tab

Cấp role Key Vault Secrets User (RBAC) cho MI trên scope Key Vault

Dùng IMDS để lấy token trong App Service và đọc secret từ Key Vault

Hiểu khi nào dùng user-assigned MI thay vì system-assigned MI

📋 Chuẩn Bị

Yêu cầu:
  • Azure subscription quyền Owner hoặc Contributor + User Access Administrator
  • Azure CLI 2.50+ đã đăng nhập
  • Resource provider Microsoft.ManagedIdentity đã registered
  • Region: southeastasia
So sánh nhanh MI types:
Thuộc tínhSystem-assignedUser-assigned
LifecycleGắn với resourceĐộc lập
Tái sử dụngKhôngCó (nhiều resource)
Quản lýTự độngThủ công

🏗️ Kịch Bản

Công ty triển khai 3 App Service (Web, API, Worker) đều cần đọc cùng một bộ secrets từ Key Vault. Dùng system-assigned MI sẽ phải gán RBAC 3 lần và quản lý 3 service principal riêng. Giải pháp tối ưu: tạo một user-assigned managed identity duy nhất, gán RBAC một lần, rồi attach vào cả 3 App Service. Lab này thực hành với 1 App Service để minh họa toàn bộ luồng.

🧪 Các Bước Thực Hiện

1

Tạo User-assigned Managed Identity

User-assigned MI là Azure resource độc lập — tồn tại riêng, không phụ thuộc vào VM hay App Service. Tạo trước rồi mới gán cho resource cần dùng.

Cách 1 — Portal
  1. 1.1Portal → tìm kiếm "Managed Identities""+ Create"
  2. 1.2Resource group: rg-az500-mi-lab18, Region: Southeast Asia
  3. 1.3Name: mi-az500-appservice-lab18Review + create
  4. 1.4Sau khi tạo: ghi lại Client IDObject (principal) ID từ Overview tab
  5. 1.5Click "Azure role assignments" — hiện chưa có role nào
Cách 2 — Azure CLI
Azure CLI— tạo user-assigned MI và hạ tầng
# Biến môi trường
RG="rg-az500-mi-lab18"
LOCATION="southeastasia"
MI_NAME="mi-az500-appservice-lab18"
KV_NAME="kv-az500-lab18-$(date +%s | tail -c 5)"
APP_PLAN="plan-az500-lab18"
APP_NAME="app-az500-lab18-$(date +%s | tail -c 5)"

# Tạo Resource Group
az group create --name $RG --location $LOCATION

# Tạo User-assigned Managed Identity (Azure resource độc lập)
az identity create \
  --name $MI_NAME \
  --resource-group $RG \
  --location $LOCATION

# Lấy thông tin MI
MI_CLIENT_ID=$(az identity show \
  --name $MI_NAME \
  --resource-group $RG \
  --query clientId -o tsv)

MI_OBJECT_ID=$(az identity show \
  --name $MI_NAME \
  --resource-group $RG \
  --query principalId -o tsv)

MI_RESOURCE_ID=$(az identity show \
  --name $MI_NAME \
  --resource-group $RG \
  --query id -o tsv)

echo "MI Client ID:    $MI_CLIENT_ID"
echo "MI Object ID:    $MI_OBJECT_ID"
echo "MI Resource ID:  $MI_RESOURCE_ID"
2

Tạo Key Vault, Secret và App Service

Tạo Key Vault với RBAC model, thêm secret cần bảo vệ, và tạo App Service Plan + Web App trên Linux.

Cách 1 — Portal
  1. 2.1Tạo Key Vault: name kv-az500-lab18-*, Permission model: Azure RBAC, Soft delete: 7 days
  2. 2.2Gán Key Vault Secrets Officer cho account của bạn → tạo secret: api-key = sk-lab18-supersecret-2026
  3. 2.3Tạo App Service Plan: OS = Linux, Pricing = Free F1 (đủ để lab)
  4. 2.4Tạo Web App: Runtime = Python 3.11, gắn vào App Service Plan vừa tạo
Cách 2 — Azure CLI
Azure CLI— Key Vault, secret, App Service
# Tạo Key Vault với RBAC model và TLS 1.2 minimum
az keyvault create \
  --name $KV_NAME \
  --resource-group $RG \
  --location $LOCATION \
  --enable-rbac-authorization true \
  --sku standard \
  --enable-soft-delete true \
  --retention-days 7

KV_ID=$(az keyvault show --name $KV_NAME --query id -o tsv)
echo "Key Vault ID: $KV_ID"

# Gán quyền Secrets Officer cho user hiện tại để tạo secret
CURRENT_USER=$(az ad signed-in-user show --query id -o tsv)
az role assignment create \
  --assignee $CURRENT_USER \
  --role "Key Vault Secrets Officer" \
  --scope $KV_ID

# Tạo secret
sleep 15
az keyvault secret set \
  --vault-name $KV_NAME \
  --name "api-key" \
  --value "sk-lab18-supersecret-2026"

# Tạo App Service Plan (Linux, Free tier)
az appservice plan create \
  --name $APP_PLAN \
  --resource-group $RG \
  --location $LOCATION \
  --is-linux \
  --sku F1

# Tạo Web App Python 3.11
az webapp create \
  --name $APP_NAME \
  --resource-group $RG \
  --plan $APP_PLAN \
  --runtime "PYTHON:3.11"

echo "Web App URL: https://$APP_NAME.azurewebsites.net"
3

Gán User-assigned MI cho App Service

Attach user-assigned MI vào App Service — App Service có thể dùng identity này để xác thực với các Azure service khác.

Cách 1 — Portal
  1. 3.1Portal → Web App → menu trái → "Identity"
  2. 3.2Tab "User assigned" → click "+ Add"
  3. 3.3Chọn mi-az500-appservice-lab18Add
  4. 3.4Identity xuất hiện trong danh sách với Client ID và Object ID — lưu lại Client ID
  5. 3.5Lưu ý: Tab "System assigned" vẫn Off — đây là user-assigned, không phải system-assigned
Cách 2 — Azure CLI
Azure CLI— gán user-assigned MI cho web app
# Gán user-assigned MI cho App Service
az webapp identity assign \
  --resource-group $RG \
  --name $APP_NAME \
  --identities $MI_RESOURCE_ID

# Xác nhận MI đã được gán
az webapp identity show \
  --resource-group $RG \
  --name $APP_NAME \
  --query "{type:type, userAssignedIdentities:userAssignedIdentities}" \
  --output json
Kết quả (Output)— user-assigned MI gán thành công
{
  "type": "UserAssigned",
  "userAssignedIdentities": {
    "/subscriptions/.../mi-az500-appservice-lab18": {
      "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "principalId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
    }
  }
}
4

Gán Role Key Vault Secrets User cho MI

Gán role trên Object ID của MI (không phải app service). Role này áp dụng cho mọi resource được gán MI này — gán một lần dùng được nhiều App Service.

Cách 1 — Portal
  1. 4.1Portal → Key Vault → "Access control (IAM)""+ Add role assignment"
  2. 4.2Role: "Key Vault Secrets User" → Next
  3. 4.3Assign access to: "Managed identity" → Select members → Managed identity: "User-assigned managed identity"
  4. 4.4Chọn mi-az500-appservice-lab18 → Review + assign
Cách 2 — Azure CLI
Azure CLI— gán Key Vault Secrets User cho MI object ID
# Gán Key Vault Secrets User cho MI (dùng Object ID của MI, không phải App Service)
az role assignment create \
  --assignee-object-id $MI_OBJECT_ID \
  --assignee-principal-type ServicePrincipal \
  --role "Key Vault Secrets User" \
  --scope $KV_ID

# Xác nhận
az role assignment list \
  --assignee $MI_OBJECT_ID \
  --scope $KV_ID \
  --query "[].{Role:roleDefinitionName, Principal:principalName, Scope:scope}" \
  --output table
5

Đọc Secret qua IMDS trong App Service

App Service dùng IMDS endpoint tương tự VM. Khi có nhiều MI (cả system + user-assigned), phải chỉ định Client ID của MI cần dùng qua tham số client_id.

Cách 1 — Portal (Kudu Console)
  1. 5.1Portal → Web App → menu trái → "Advanced Tools""Go" (Kudu)
  2. 5.2Kudu → "Debug console""Bash"
  3. 5.3Chạy lệnh IMDS trong bước CLI bên dưới trực tiếp trong Kudu bash console
Cách 2 — Deploy script và test qua CLI
Bash (Kudu Console hoặc App Service SSH)— IMDS với client_id cho user-assigned MI
# === Chạy bên trong App Service (Kudu Bash / SSH) ===

# Lấy token — PHẢI chỉ định client_id của user-assigned MI
# (nếu không App Service không biết dùng MI nào)
MI_CLIENT_ID="PASTE_CLIENT_ID_HERE"  # Thay bằng Client ID thực từ bước 1
KV_NAME="kv-az500-lab18-XXXXX"       # Thay bằng KV name thực

TOKEN=$(curl -s \
  "http://169.254.169.254/metadata/identity/oauth2/token?\
api-version=2018-02-01&\
resource=https%3A%2F%2Fvault.azure.net&\
client_id=$MI_CLIENT_ID" \
  -H "Metadata: true" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

echo "Token obtained: ${TOKEN:0:30}..."

# Đọc secret "api-key" từ Key Vault
SECRET=$(curl -s \
  "https://$KV_NAME.vault.azure.net/secrets/api-key?api-version=7.4" \
  -H "Authorization: Bearer $TOKEN" | \
  python3 -c "import sys,json; print(json.load(sys.stdin)['value'])")

echo "Secret value: $SECRET"
Cách Production — Key Vault Reference trong App Settings

Cách được khuyến nghị trong production: thay vì code gọi IMDS thủ công, dùng Key Vault Reference trực tiếp trong Application Settings.

Azure CLI— Key Vault Reference trong App Settings
# Lấy Secret URI từ Key Vault
SECRET_URI=$(az keyvault secret show \
  --vault-name $KV_NAME \
  --name "api-key" \
  --query id -o tsv)

echo "Secret URI: $SECRET_URI"

# Cấu hình App Setting dùng Key Vault Reference syntax
# App Service tự động resolve @Microsoft.KeyVault(...) lúc runtime
az webapp config appsettings set \
  --resource-group $RG \
  --name $APP_NAME \
  --settings "[email protected](SecretUri=$SECRET_URI)"

# Xác nhận App Setting đã set
az webapp config appsettings list \
  --resource-group $RG \
  --name $APP_NAME \
  --query "[?name=='API_KEY']" \
  --output table

# App sẽ đọc os.environ['API_KEY'] và nhận giá trị thực của secret
# Không cần code gọi IMDS — platform tự lo
Tại sao Key Vault Reference tốt hơn? App Service runtime tự lấy secret khi start, auto-refresh khi secret rotate, không cần code SDK, env var sẵn sàng cho mọi ngôn ngữ. Chỉ cần MI có Key Vault Secrets User là đủ.

📊 Kết Quả Đầu Ra Lab 18

User-assigned MI tạo thành công

Managed Identities resource tồn tại độc lập trong RG với Client ID và Object ID riêng

MI gán cho App Service

Web App Identity tab: User assigned tab có entry mi-az500-appservice-lab18

RBAC role assigned

Key Vault IAM: mi-az500-appservice-lab18 có role Key Vault Secrets User

Token lấy qua IMDS với client_id

IMDS trả về access_token khi có client_id parameter của user-assigned MI

Secret đọc được từ Key Vault

API trả về giá trị secret đúng, không có credential nào hardcode trong app

Key Vault Reference hoạt động

App Setting API_KEY resolve thành giá trị thực khi App Service start

🧹 Dọn Dẹp

Azure CLI— xóa toàn bộ resource group
# Xóa resource group (xóa cả App Service, Key Vault, MI, App Service Plan)
az group delete \
  --name rg-az500-mi-lab18 \
  --yes \
  --no-wait

# Purge Key Vault nếu muốn tái dùng tên (soft-delete giữ 7 ngày)
# az keyvault purge --name $KV_NAME --location $LOCATION

# User-assigned MI bị xóa theo RG — service principal trong Entra cũng bị xóa
echo "Cleanup initiated."

❓ Câu Hỏi Ôn Tập

1. Tại sao cần chỉ định client_id khi gọi IMDS cho user-assigned MI? Điều gì xảy ra nếu không chỉ định và có cả system-assigned MI lẫn user-assigned MI?

Gợi ý: Không chỉ định → IMDS dùng system-assigned MI (nếu có). Nếu chỉ có user-assigned mà không chỉ định client_id và chỉ có 1 user-assigned MI → vẫn work. Nhưng best practice luôn chỉ định để code rõ ràng và không bị lỗi khi môi trường thay đổi.

2. Khi nào nên chọn user-assigned MI thay vì system-assigned MI? Cho 2 ví dụ thực tế.

Gợi ý: Dùng user-assigned khi: (1) Nhiều resource cần cùng identity và quyền (3 App Service cùng đọc KV). (2) Resource bị xóa và tạo lại thường xuyên — không muốn mất role assignments. (3) Cần pre-provision identity trước khi resource được tạo.

3. Key Vault Reference trong App Settings hoạt động như thế nào? App Service lấy secret khi nào và bao lâu refresh một lần?

Gợi ý: App Service resolve reference khi start và mỗi 24 giờ (hoặc khi restart). Nếu KV secret rotate, cần restart app để lấy version mới. Dùng version-less URI để luôn lấy latest version.

4. Nếu cần gán cùng user-assigned MI cho 3 App Service, bạn cần tạo bao nhiêu role assignment? So sánh với system-assigned MI.

Gợi ý: User-assigned = 1 role assignment duy nhất trên Key Vault scope (vì cùng Object ID). System-assigned = 3 role assignments (mỗi app có object ID riêng). User-assigned tiết kiệm quản lý hơn nhiều.

5. Azure SDK (.NET, Python, Java) có cần code đặc biệt để dùng managed identity không? DefaultAzureCredential hoạt động như thế nào?

Gợi ý: Không cần code đặc biệt. DefaultAzureCredential tự thử nhiều auth method theo thứ tự: environment → workload identity → managed identity → Azure CLI → ... Trong Azure resource, nó tự dùng IMDS. Trong local dev, dùng az login credential.

Lab 17: System-assigned MI cho VM Thư viện Labs Lab 19: NSG & VM Access
Zalo