🎯 Mục Tiêu Lab
Bật blob soft delete và container soft delete với retention 7 ngày
Bật blob versioning để lưu lịch sử thay đổi tự động
Tạo immutable policy (time-based retention) cho container
Thử xóa/ghi đè blob trong container immutable — xác nhận bị chặn
Khôi phục blob đã xóa bằng soft delete và rollback version cũ
Hiểu sự khác biệt giữa soft delete, versioning và immutable storage
📋 Chuẩn Bị
- Azure subscription với quyền Contributor
- Azure CLI 2.50+ hoặc Cloud Shell
- Storage Account StorageV2 (không phải BlobStorage)
- Lưu ý: immutable policy sau khi lock không thể xóa cho đến hết retention
- RG: rg-az500-lab39
- Storage: staz500lab39[suffix]
- Container (versioning): versioned-data
- Container (immutable): immutable-data
🏗️ Kịch Bản
Công ty lưu trữ báo cáo tài chính và log audit trên Azure Blob. Cần ba lớp bảo vệ: (1) Soft delete — khôi phục nếu xóa nhầm trong 7 ngày; (2) Versioning — tự động lưu mọi phiên bản khi blob bị ghi đè; (3) Immutable storage — đảm bảo dữ liệu compliance không thể sửa/xóa trong thời gian retention theo quy định.
Blob/container bị xóa vẫn còn trong "recycle bin" N ngày. Có thể khôi phục thủ công.
Mỗi lần overwrite blob → version cũ được lưu tự động. Rollback về bất kỳ version nào.
WORM (Write Once Read Many) — không ai có thể sửa/xóa blob kể cả admin trong thời gian retention.
🧪 Các Bước Thực Hiện
Bật Blob Soft Delete và Container Soft Delete
- 1.1Tạo Storage Account
staz500lab39xxxx(StorageV2, TLS 1.2, anonymous disabled) - 1.2Storage → Data protection → Enable soft delete for blobs: 7 days → Enable soft delete for containers: 7 days → Save
- 1.3Tạo container
versioned-data(Private access) - 1.4Upload file → Xóa file → Storage → Data protection → Show deleted blobs → xác nhận blob vẫn còn → Undelete
# Tạo resource group và storage
az group create --name rg-az500-lab39 --location southeastasia
STORAGE_NAME="staz500lab39$(shuf -i 1000-9999 -n 1)"
echo "Storage: $STORAGE_NAME"
az storage account create \
--resource-group rg-az500-lab39 \
--name $STORAGE_NAME \
--location southeastasia \
--sku Standard_LRS \
--kind StorageV2 \
--min-tls-version TLS1_2 \
--allow-blob-public-access false
# Bật blob soft delete (7 ngày) và container soft delete (7 ngày)
az storage account blob-service-properties update \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--enable-delete-retention true \
--delete-retention-days 7 \
--enable-container-delete-retention true \
--container-delete-retention-days 7
# Lấy connection string
CONN_STR=$(az storage account show-connection-string \
--resource-group rg-az500-lab39 \
--name $STORAGE_NAME --query connectionString --output tsv)
# Tạo container và upload blob test
az storage container create --name versioned-data --connection-string "$CONN_STR"
echo "Version 1 - Original Content" > /tmp/report.txt
az storage blob upload --container-name versioned-data --name report.txt \
--file /tmp/report.txt --connection-string "$CONN_STR"
# Xóa blob
az storage blob delete --container-name versioned-data --name report.txt \
--connection-string "$CONN_STR"
# Xem soft-deleted blobs (--include d = include deleted)
az storage blob list \
--container-name versioned-data \
--include d \
--connection-string "$CONN_STR" \
--query "[].{Name:name, Deleted:deleted, DeletedTime:properties.deletedTime}" \
--output table
# Khôi phục blob đã xóa
az storage blob undelete \
--container-name versioned-data \
--name report.txt \
--connection-string "$CONN_STR"
# Xác nhận blob đã được khôi phục
az storage blob show \
--container-name versioned-data \
--name report.txt \
--connection-string "$CONN_STR" \
--query "properties.deletedTime"
Bật Blob Versioning và Rollback Version Cũ
- 2.1Storage → Data protection → Enable versioning for blobs → Save
- 2.2Upload cùng file blob 3 lần với nội dung khác nhau
- 2.3Click vào blob → tab Versions → thấy danh sách versions → click version cũ → Make current
# Bật blob versioning
az storage account blob-service-properties update \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--enable-versioning true
# Upload version 1
echo "Version 1 - Q1 2026 Report - DRAFT" > /tmp/report.txt
az storage blob upload --container-name versioned-data --name report.txt \
--file /tmp/report.txt --connection-string "$CONN_STR" --overwrite
# Upload version 2 (ghi đè — version 1 được lưu tự động)
echo "Version 2 - Q1 2026 Report - REVIEW" > /tmp/report.txt
az storage blob upload --container-name versioned-data --name report.txt \
--file /tmp/report.txt --connection-string "$CONN_STR" --overwrite
# Upload version 3
echo "Version 3 - Q1 2026 Report - FINAL" > /tmp/report.txt
az storage blob upload --container-name versioned-data --name report.txt \
--file /tmp/report.txt --connection-string "$CONN_STR" --overwrite
# Liệt kê tất cả versions
az storage blob list \
--container-name versioned-data \
--include v \
--connection-string "$CONN_STR" \
--query "[?name=='report.txt'].{VersionId:versionId, IsCurrent:isCurrentVersion}" \
--output table
# Lấy version ID của version 1 (version cũ nhất)
OLD_VERSION_ID=$(az storage blob list \
--container-name versioned-data \
--include v \
--connection-string "$CONN_STR" \
--query "[?name=='report.txt' && isCurrentVersion==null] | [0].versionId" \
--output tsv)
echo "Old Version ID: $OLD_VERSION_ID"
# Rollback: copy version cũ thành current version
az storage blob copy start \
--destination-container versioned-data \
--destination-blob report.txt \
--source-container versioned-data \
--source-blob "report.txt" \
--source-version $OLD_VERSION_ID \
--connection-string "$CONN_STR"
# Xác nhận nội dung đã rollback
az storage blob download \
--container-name versioned-data --name report.txt \
--file /tmp/rolled-back.txt --connection-string "$CONN_STR"
cat /tmp/rolled-back.txt
Tạo Immutable Policy (WORM) và Legal Hold
- 3.1Tạo container
immutable-data→ vào container → Access policy - 3.2Immutable blob storage → + Add policy → Policy type: Time-based retention → Retention period: 1 day (test) → Save
- 3.3Upload blob vào container → thử xóa blob → xác nhận lỗi "This operation is not permitted as the blob is immutable"
- 3.4Thêm Legal hold tag:
investigation-2026→ xác nhận blob không thể xóa kể cả sau hết retention
# Tạo container cho immutable storage
az storage container create \
--name immutable-data \
--connection-string "$CONN_STR"
# Upload blob compliance trước khi set policy
echo "Audit Log - 2026-05-21 - Financial Report - FINAL" > /tmp/audit.txt
az storage blob upload \
--container-name immutable-data \
--name audit-2026-q1.txt \
--file /tmp/audit.txt \
--connection-string "$CONN_STR"
# Tạo time-based immutable policy (1 ngày = test; production thường 7–365 ngày)
# Lưu ý: sau khi lock policy thì không thể xóa container cho đến hết retention!
az storage container immutability-policy create \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data \
--period 1
# Xem trạng thái policy (Unlocked = có thể xóa/sửa policy chưa lock)
az storage container immutability-policy show \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data
# Thử xóa blob — vẫn có thể xóa khi policy chưa lock
# Khi lock: az storage container immutability-policy lock ... (KHÔNG THỂ ĐẢOT NGƯỢC)
# => Chỉ lock trong production khi chắc chắn!
# Thêm Legal Hold (không cần lock, ngay lập tức bảo vệ)
az storage container legal-hold set \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data \
--tags investigation-2026
# Bây giờ thử xóa blob — sẽ bị chặn vì Legal Hold
az storage blob delete \
--container-name immutable-data \
--name audit-2026-q1.txt \
--connection-string "$CONN_STR" 2>&1
# Kết quả: BlobImmutableDueToLegalHold - This blob is immutable due to a legal hold.
# Xóa legal hold để dọn dẹp
az storage container legal-hold clear \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data \
--tags investigation-2026
immutability-policy lock là KHÔNG THỂ ĐẢO NGƯỢC. Container sẽ không thể xóa cho đến khi hết retention period. Chỉ dùng trong production khi có yêu cầu compliance thực sự. Trong lab, test với Legal Hold thay vì Lock.
📊 Kết Quả Mong Đợi
Blob xóa vẫn hiển thị với --include d, undelete khôi phục thành công
3 lần upload → 3 versions, rollback về version 1 bằng copy start
Xóa blob với legal hold → BlobImmutableDueToLegalHold error
Policy state: Unlocked, period: P1D, có thể upgrade/delete khi chưa lock
🧹 Dọn Dẹp Tài Nguyên
# Xóa immutable policy (chỉ được khi chưa lock)
ETAG=$(az storage container immutability-policy show \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data \
--query etag --output tsv)
az storage container immutability-policy delete \
--resource-group rg-az500-lab39 \
--account-name $STORAGE_NAME \
--container-name immutable-data \
--if-match $ETAG
# Xóa resource group
az group delete --name rg-az500-lab39 --yes --no-wait
❓ Câu Hỏi Ôn Tập
1. Soft delete và versioning khác nhau thế nào khi blob bị ghi đè (overwrite)?
Gợi ý: Soft delete chỉ bảo vệ khi xóa (delete), không bảo vệ khi ghi đè. Versioning bảo vệ cả hai — mỗi lần overwrite đều tạo version cũ tự động
2. Sự khác biệt giữa Time-based Retention Policy (locked) và Legal Hold?
Gợi ý: Time-based có thời hạn cố định, có thể unlock nếu chưa lock. Legal Hold không có thời hạn, bảo vệ cho đến khi tag bị xóa thủ công. Cả hai đều ngăn xóa/sửa blob
3. Khi immutable policy đã bị lock, admin có thể xóa container không?
Gợi ý: Không — không ai có thể xóa container (kể cả subscription admin) cho đến khi retention period hết hạn VÀ không còn legal hold nào
4. Tại sao versioning cần bật cùng soft delete để bảo vệ toàn diện?
Gợi ý: Versioning lưu lịch sử overwrite; soft delete bảo vệ nếu cả current version và previous versions bị xóa; kết hợp hai tính năng đảm bảo có thể khôi phục mọi tình huống
5. Blob versioning có tự động xóa versions cũ không? Làm sao quản lý chi phí lưu trữ?
Gợi ý: Không tự động — cần dùng Lifecycle Management policy để tự động xóa versions cũ hơn N ngày hoặc chuyển sang Cool/Archive tier để giảm chi phí