🎯 Mục Tiêu Lab
Tạo VNet với subnet và bật Service Endpoint Microsoft.Storage
Tạo Storage Account với TLS 1.2 và cấu hình firewall chỉ cho phép subnet
Kiểm tra truy cập từ VM trong subnet được phép và VM ngoài subnet bị từ chối
Hiểu traffic vẫn đi qua public IP của Storage — backbone Microsoft
Phân biệt Service Endpoint vs Private Endpoint: use case, chi phí, DNS
Áp dụng chuẩn 2026: tắt anonymous access, bật minimum TLS 1.2
📋 Chuẩn Bị
- Azure subscription đang Active
- Quyền Contributor hoặc Owner trên resource group
- Azure CLI đã cài đặt (az version ≥ 2.50)
- Đã hoàn thành Lab 22 (NSG Flow Logs) hoặc nắm cơ bản VNet/NSG
- Service Endpoint KHÔNG tạo private IP — traffic vẫn đi qua public endpoint
- Service Endpoint Policy (SEP) để giới hạn đến storage account cụ thể
- Region:
southeastasia - Xóa resource sau lab để tránh phát sinh chi phí VM
🏗️ Kịch Bản
Doanh nghiệp có subnet ứng dụng (snet-app) chứa VM backend. Yêu cầu bảo mật: Storage Account chỉ truy cập được từ subnet này, không cho phép truy cập từ Internet hoặc các subnet khác. Dùng Service Endpoint vì chi phí thấp và triển khai nhanh — đủ dùng khi không cần private IP hoàn toàn.
10.10.0.0/16
10.10.1.0/24
TLS 1.2, no public
So Sánh: Service Endpoint vs Private Endpoint
| Tiêu chí | Service Endpoint | Private Endpoint |
|---|---|---|
| IP endpoint | Public IP (vẫn là *.blob.core.windows.net) |
Private IP trong VNet (NIC riêng) |
| DNS thay đổi | Không — DNS giữ nguyên public | Có — cần Private DNS Zone |
| Chi phí | Miễn phí | Có phí (~$7.3/tháng + data) |
| On-premises | Không hỗ trợ | Hỗ trợ qua VPN/ExpressRoute |
| Tắt public access | Không bắt buộc (firewall restrict) | Nên tắt hoàn toàn |
| Khi nào dùng | Đơn giản, nhanh, VNet cùng region | Bảo mật cao, hybrid, cross-region |
🧪 Các Bước Thực Hiện
Tạo Resource Group, VNet và Subnet
Tạo hạ tầng mạng cơ bản: VNet 10.10.0.0/16, subnet ứng dụng 10.10.1.0/24, subnet test 10.10.2.0/24 (để kiểm tra truy cập bị từ chối).
1. Portal → Resource groups → + Create - Name: rg-az500-ch07-private - Region: Southeast Asia - Tags: course=az500, chapter=ch07 2. Portal → Virtual networks → + Create - Name: vnet-az500-private - Resource group: rg-az500-ch07-private - Region: Southeast Asia - IPv4 address space: 10.10.0.0/16 3. Tab "Subnets" → Add subnet: Subnet 1: - Name: snet-app - Address range: 10.10.1.0/24 - Services (Service Endpoint): Microsoft.Storage ← BẬT TẠI ĐÂY Subnet 2: - Name: snet-test - Address range: 10.10.2.0/24 - Services: (để trống — không có Service Endpoint) 4. Review + Create → Create
# Tạo resource group az group create \ --name rg-az500-ch07-private \ --location southeastasia \ --tags "course=az500" "chapter=ch07" "owner=hoatranlab" # Tạo VNet az network vnet create \ --name vnet-az500-private \ --resource-group rg-az500-ch07-private \ --location southeastasia \ --address-prefix 10.10.0.0/16 # Tạo snet-app với Service Endpoint Microsoft.Storage az network vnet subnet create \ --name snet-app \ --vnet-name vnet-az500-private \ --resource-group rg-az500-ch07-private \ --address-prefix 10.10.1.0/24 \ --service-endpoints Microsoft.Storage # Tạo snet-test không có Service Endpoint az network vnet subnet create \ --name snet-test \ --vnet-name vnet-az500-private \ --resource-group rg-az500-ch07-private \ --address-prefix 10.10.2.0/24 # Xác nhận subnet và service endpoint az network vnet subnet show \ --name snet-app \ --vnet-name vnet-az500-private \ --resource-group rg-az500-ch07-private \ --query "serviceEndpoints"
[
{
"locations": ["southeastasia"],
"provisioningState": "Succeeded",
"service": "Microsoft.Storage"
}
]
Tạo Storage Account với TLS 1.2 và Cấu Hình Firewall
Tạo Storage Account theo chuẩn 2026: tắt anonymous access, bật TLS 1.2 tối thiểu, cấu hình network firewall chỉ cho phép snet-app.
1. Portal → Storage accounts → + Create
Basics:
- Resource group: rg-az500-ch07-private
- Storage account name: staz500lab28[4-ký-tự-random] (ví dụ: staz500lab28xk9m)
- Region: Southeast Asia
- Performance: Standard
- Redundancy: LRS
Advanced:
- Minimum TLS version: TLS 1.2 ← BẮT BUỘC
- Allow Blob anonymous access: DISABLED ← BẮT BUỘC
Networking:
- Network access: "Enable from selected virtual networks and IP addresses"
- Virtual networks → + Add existing virtual network:
VNet: vnet-az500-private
Subnet: snet-app ← CHỈ subnet này
2. Review + Create → Create
# Lấy subnet ID SUBNET_ID=$(az network vnet subnet show \ --name snet-app \ --vnet-name vnet-az500-private \ --resource-group rg-az500-ch07-private \ --query id -o tsv) # Tạo Storage Account với network rule az storage account create \ --name staz500lab28xk9m \ --resource-group rg-az500-ch07-private \ --location southeastasia \ --sku Standard_LRS \ --min-tls-version TLS1_2 \ --allow-blob-public-access false \ --default-action Deny \ --bypass AzureServices # Thêm subnet rule cho snet-app az storage account network-rule add \ --account-name staz500lab28xk9m \ --resource-group rg-az500-ch07-private \ --subnet $SUBNET_ID # Xác nhận network rules az storage account show \ --name staz500lab28xk9m \ --resource-group rg-az500-ch07-private \ --query "networkRuleSet" \ --output json
{
"bypass": "AzureServices",
"defaultAction": "Deny",
"ipRules": [],
"virtualNetworkRules": [
{
"action": "Allow",
"state": "Succeeded",
"virtualNetworkResourceId": "/subscriptions/.../snet-app"
}
]
}
Tạo VM Kiểm Tra trong Cả Hai Subnet
Tạo 2 VM: vm-app trong snet-app (được phép) và vm-test trong snet-test (bị từ chối).
# VM trong snet-app (có Service Endpoint — được phép truy cập storage) az vm create \ --resource-group rg-az500-ch07-private \ --name vm-app \ --image Ubuntu2204 \ --size Standard_B1s \ --vnet-name vnet-az500-private \ --subnet snet-app \ --public-ip-sku Standard \ --admin-username azureuser \ --generate-ssh-keys \ --no-wait # VM trong snet-test (KHÔNG có Service Endpoint — bị từ chối) az vm create \ --resource-group rg-az500-ch07-private \ --name vm-test \ --image Ubuntu2204 \ --size Standard_B1s \ --vnet-name vnet-az500-private \ --subnet snet-test \ --public-ip-sku Standard \ --admin-username azureuser \ --generate-ssh-keys
Tạo Blob Container và Upload File Test
1. Storage account → Containers → + Container - Name: lab28-container - Public access: Private 2. Vào container → Upload → chọn file bất kỳ (vd: test.txt) 3. Ghi lại URL: https://staz500lab28xk9m.blob.core.windows.net/lab28-container/test.txt
# Lấy connection string (chạy từ máy local hoặc Cloud Shell) CONN=$(az storage account show-connection-string \ --name staz500lab28xk9m \ --resource-group rg-az500-ch07-private \ --query connectionString -o tsv) # Tạo container az storage container create \ --name lab28-container \ --connection-string "$CONN" \ --public-access off # Upload file test echo "Hello from AZ-500 Lab 28" > /tmp/test.txt az storage blob upload \ --container-name lab28-container \ --name test.txt \ --file /tmp/test.txt \ --connection-string "$CONN"
Kiểm Tra Truy Cập Từ Hai VM
Kiểm tra: vm-app (snet-app có Service Endpoint) được phép; vm-test (snet-test không có Service Endpoint) bị từ chối 403.
# SSH vào vm-app ssh azureuser@<public-ip-vm-app> # Cài azure-cli trên Ubuntu curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # Đăng nhập (dùng device code) az login --use-device-code # List blob từ snet-app — KẾT QUẢ: thành công az storage blob list \ --account-name staz500lab28xk9m \ --container-name lab28-container \ --output table \ --auth-mode login
# SSH vào vm-test ssh azureuser@<public-ip-vm-test> # Thử truy cập blob — KẾT QUẢ: 403 AuthorizationFailure curl -I https://staz500lab28xk9m.blob.core.windows.net/lab28-container/test.txt # HTTP/1.1 403 This request is not authorized to perform this operation. # Nguyên nhân: snet-test không có Service Endpoint, # request đi qua public internet → bị Deny theo default-action
📊 Kết Quả Đầu Ra Lab 28
snet-app có service endpoint Microsoft.Storage → state: Succeeded
defaultAction: Deny, chỉ snet-app trong virtualNetworkRules
az storage blob list từ snet-app trả về danh sách thành công
curl từ snet-test → HTTP 403 AuthorizationFailure
minimumTlsVersion: TLS1_2 — chuẩn Azure 2026
allowBlobPublicAccess: false — không ai đọc public được
🧹 Dọn Dẹp Tài Nguyên
Giữ lại VNet và subnet nếu tiếp tục Lab 29. Xóa VM để tránh chi phí.
# Xóa VM để tránh chi phí (giữ VNet và Storage cho Lab 29)
az vm delete --resource-group rg-az500-ch07-private --name vm-app --yes --no-wait
az vm delete --resource-group rg-az500-ch07-private --name vm-test --yes --no-wait
# Xóa public IPs và NICs liên quan
az network public-ip list \
--resource-group rg-az500-ch07-private \
--query "[].name" -o tsv | \
xargs -I {} az network public-ip delete \
--resource-group rg-az500-ch07-private --name {}
# Xóa toàn bộ nếu không cần tiếp tục
# az group delete --name rg-az500-ch07-private --yes --no-wait
❓ Câu Hỏi Ôn Tập
1. Service Endpoint cho Storage tạo ra private IP trong VNet không? Traffic đi qua đâu?
Gợi ý: Không có private IP. Traffic vẫn dùng public IP của Storage nhưng đi qua backbone Microsoft (không ra internet public). Storage firewall nhận diện nguồn là subnet được trust.
2. Tại sao VM trong snet-test nhận 403 dù đã đăng nhập đúng Azure credential?
Gợi ý: 403 từ Storage firewall network rule, không phải lỗi authentication. snet-test không có Service Endpoint → request đến từ public internet → defaultAction: Deny.
3. Service Endpoint Policy (SEP) là gì? Khi nào cần dùng thêm SEP?
Gợi ý: SEP giới hạn traffic qua Service Endpoint chỉ đến storage account cụ thể (không phải toàn bộ Microsoft.Storage). Dùng khi muốn ngăn exfiltration sang storage account khác.
4. Cần thêm điều kiện gì để VM on-premises truy cập được Storage Account này?
Gợi ý: Service Endpoint không hỗ trợ on-premises. Phải dùng Private Endpoint (Lab 29) kết hợp với VPN/ExpressRoute, hoặc thêm IP rule trong Storage firewall.
5. Tham số --bypass AzureServices có ý nghĩa gì trong network rule Storage?
Gợi ý: Cho phép một số dịch vụ Azure trusted (như Azure Backup, Azure Monitor) truy cập storage dù defaultAction là Deny. Không ảnh hưởng đến traffic từ VNet.