Practice Assessment for Exam AZ-204: Developing Solutions for Microsoft AzureOnline version
Practice Assessment for Exam AZ-204: Developing Solutions for Microsoft Azure
1
You plan to use Azure API Management for Hybrid and multicloud API management.
You need to create a self-hosted gateway for production.
Which container image tag should you use?
Select only one answer.
2
You have an Azure event hub.
You need to add partitions to the event hub.
Which code segment should you use?
3
You manage an Azure event hub.
You need to ensure that multiple load-balanced instances of a .NET application (version 5.0) can be used to scale event processing.
Which event processor client should you use?
4
You need to write a filter condition for an Azure Service Bus topic.
Which three filters can you use? Each correct answer presents a complete solution.
5
You need to delete an image with the tag dev/nginx:latest from an Azure container registry named devregistry.
Which code segment should you use?
6
You plan to develop an Azure App Service web app named app1 by using a Windows custom container.
You need to load a TLS/SSL certificate in application code.
Which app setting should you configure?
7
You manage the staging and production deployment slots of an Azure App Service web app named app1.
You need to ensure a connection string is not swapped when swapping is performed.
Which configuration should you use?
8
You need to configure a web app to allow external requests from https://myapps.com.
Which Azure CLI command should you use?
9
You manage a multi-instance deployment of an Azure App Service web app named app1.
You need to ensure a client application is routed to the same instance for the life of the session.
Which platform setting should you use?
10
You manage an Azure App Service web app named app1. App1 is registered as a multi-tenant application in a Microsoft Entra ID tenant named tenant1.
You need to grant app1 the permission to access the Microsoft Graph API in tenant1.
Which service principal should you use?
11
You manage a Microsoft Entra ID registered application named app1. App1 calls a web API, which then calls Microsoft Graph.
You need to ensure the signed-in user identity is delegated through the request chain.
Which authentication flow should you use?
12
You develop a multitenant web application named App1. You plan to register App1 with multiple Microsoft Entra ID tenants.
You need to identify the relationship between the application objects and security principals associated with App1.
Which relationship should you identify?
13
You plan to generate a shared access signature (SAS) token for read access to a blob in a storage account.
You need to secure the token from being compromised.
What should you use?
14
You need to generate a shared access signature token that grants the Read permission to a blob container.
Which code segment should you use?
Feedback
🚀🔐📦 Khi triển khai self-hosted gateway trong Azure API Management cho môi trường production, bạn nên sử dụng một container image tag có định dạng rõ ràng {major}.{minor}.{patch}, chẳng hạn như 2.0.1. Đây là lựa chọn được khuyến nghị vì đảm bảo tính ổn định, không bị ảnh hưởng bởi các bản cập nhật tự động như khi dùng các tag latest, v3, hay V3-preview.
📌📉🧪 Trong đó, latest chủ yếu phục vụ mục đích đánh giá, v3 luôn trỏ đến phiên bản mới nhất của major version (dễ gây thay đổi không lường trước), còn V3-preview là phiên bản chưa ổn định và không phù hợp để dùng trong môi trường thực tế.
🔒🛠️📘 Việc “pin” phiên bản (tức là cố định phiên bản cụ thể) bằng cách sử dụng tag cụ thể giúp kiểm soát tốt hơn quy trình triển khai và đảm bảo an toàn trong môi trường production.
Ví dụ: thay vì sử dụng mcr.microsoft.com/azure-api-management/gateway:latest, bạn nên sử dụng mcr.microsoft.com/azure-api-management/gateway:2.0.1 để đảm bảo rằng gateway luôn chạy đúng phiên bản đã kiểm thử và được phê duyệt. ✨✅📁
Để thêm partition vào một Azure Event Hub đã được tạo, bạn nên sử dụng lệnh `az eventhubs eventhub update` kết hợp với tham số `--partition-count`. Đây là cách duy nhất để mở rộng số lượng partition trên một event hub hiện có, giúp tăng khả năng xử lý dữ liệu song song. Các lựa chọn khác như `consumer-group update`, `consumer-group create`, hay `eventhub create` đều không phù hợp trong trường hợp này. Lệnh `update` cho phép bạn thay đổi cấu hình của Event Hub mà không cần tạo mới, tuy nhiên bạn chỉ có thể **tăng** số lượng partition, không thể giảm. Đây là thao tác quan trọng trong việc mở rộng quy mô hệ thống event-driven một cách linh hoạt và hiệu quả. 📈🛠️🔐*********
📦🧪📌 Ví dụ: Giả sử bạn có một event hub tên là `TelemetryHub` trong namespace `ProdNamespace` thuộc resource group `RG-Prod`. Event Hub này ban đầu được tạo với 4 partitions. Sau một thời gian sử dụng, bạn nhận thấy lượng dữ liệu gửi đến đã vượt quá khả năng xử lý hiện tại. Để mở rộng, bạn có thể chạy lệnh sau:
******
az eventhubs eventhub update \
--resource-group RG-Prod \
--namespace-name ProdNamespace \
--name TelemetryHub \
--partition-count 12
****
Lệnh trên sẽ cập nhật `TelemetryHub` từ 4 lên 12 partitions, giúp phân phối tải tốt hơn và tăng khả năng xử lý đồng thời của hệ thống. ⚡📥📶
Để mở rộng khả năng xử lý sự kiện trong một ứng dụng .NET (phiên bản 5.0 trở lên) sử dụng Azure Event Hub, lựa chọn phù hợp nhất là EventProcessorClient. Đây là client được thiết kế để hỗ trợ việc cân bằng tải (load balancing) giữa nhiều instance xử lý, giúp hệ thống hoạt động ổn định và hiệu quả hơn trong môi trường phân tán. 🚀📈🔄
📥🧩🔌 Ví dụ: Giả sử bạn có một ứng dụng .NET được triển khai trên ba instance của một dịch vụ Azure App Service. Mỗi instance sẽ khởi tạo một EventProcessorClient để đọc và xử lý dữ liệu từ cùng một Event Hub. Nhờ cơ chế load balancing tích hợp, mỗi instance sẽ tự động được chỉ định một hoặc nhiều partition để xử lý, giúp đảm bảo rằng toàn bộ dữ liệu được phân phối đều mà không bị trùng lặp hoặc thiếu sót. Điều này đặc biệt quan trọng trong các hệ thống cần khả năng mở rộng cao như xử lý dữ liệu IoT, log streaming hoặc giao dịch thời gian thực. 🔄📊✅
Trong khi đó, các lựa chọn khác như EventHubConsumerClient phù hợp với Python hoặc JavaScript, EventProcessorHost dành cho các phiên bản .NET cũ, và EventHubProducerClient chỉ dùng để gửi dữ liệu vào event hub chứ không phục vụ cho việc xử lý sự kiện. Vì vậy, nếu bạn cần triển khai một ứng dụng .NET hiện đại có khả năng mở rộng, EventProcessorClient là lựa chọn đúng đắn để đảm bảo khả năng xử lý song song và hiệu quả. 💡📘🔧
🧼📦🛠️ Để xóa một image cụ thể khỏi Azure Container Registry (ACR), bạn nên sử dụng lệnh `az acr repository delete` với tham số `--image`, ví dụ: `az acr repository delete --name devregistry --image dev/nginx:latest`. Lệnh này sẽ xóa toàn bộ image, bao gồm manifest và các layer liên quan. Trong khi đó, các lựa chọn như `--suffix` thường dùng trong các tình huống bạn chỉ có quyền truy cập hạn chế vào registry và không đủ quyền quản trị. Ngoài ra, các lệnh sử dụng `az acr manifest delete` chỉ xóa phần manifest của artifact, chứ không xóa toàn bộ image. Vì vậy, trong trường hợp bạn có toàn quyền trên ACR và muốn xóa hoàn toàn một image, `az acr repository delete --image` là lựa chọn chính xác và đầy đủ nhất. 🔒📁✅
🧾💡📉 Ví dụ: Giả sử bạn có một Azure Container Registry có tên là `prodregistry` và bạn muốn xóa image `api/backend:stable` vì phiên bản này đã lỗi thời. Bạn có thể sử dụng lệnh sau:
```
az acr repository delete \
--name prodregistry \
--image api/backend:stable
```
Lệnh này sẽ xóa toàn bộ image `api/backend:stable` bao gồm cả manifest và các layer của nó ra khỏi registry `prodregistry`, giải phóng không gian lưu trữ và đảm bảo rằng phiên bản lỗi thời không còn tồn tại trong hệ thống. 🧯🗂️🚀
🔐🌐📦 Để sử dụng chứng chỉ TLS/SSL trong mã nguồn của ứng dụng chạy trên Azure App Service sử dụng Windows custom container, bạn cần cấu hình app setting `WEBSITE_LOAD_CERTIFICATES`. Thiết lập này cho phép hệ thống mount các chứng chỉ đã được tải lên Azure App Service dưới dạng file, giúp ứng dụng truy cập chúng thông qua mã nguồn. Việc đặt `WEBSITE_LOAD_CERTIFICATES = *` sẽ cho phép tải tất cả chứng chỉ có sẵn. Trong mã C#, bạn có thể tìm chứng chỉ thông qua lớp `X509Store` bằng thumbprint. Các thiết lập khác như `WEBSITE_ROOT_CERTS_PATH` chỉ mang tính chất chỉ định đường dẫn mà không hỗ trợ nạp nhiều chứng chỉ, trong khi `WEBSITE_AUTH_TOKEN_CONTAINER_SASURL` lại được dùng cho mục đích lưu trữ token trên Azure Storage. Vì vậy, `WEBSITE_LOAD_CERTIFICATES` là app setting phù hợp và cần thiết để ứng dụng có thể sử dụng chứng chỉ bảo mật từ bên trong container. ✅🔒📥
📌 Ví dụ cụ thể: Một công ty phát triển ứng dụng web .NET Core chạy trên Azure App Service bằng Windows container. Ứng dụng này cần thiết lập kết nối HTTPS client tới một API nội bộ yêu cầu xác thực bằng chứng chỉ số. Để thực hiện, họ đầu tiên tải chứng chỉ lên mục TLS/SSL settings trong Azure App Service. Sau đó, họ cấu hình app setting `WEBSITE_LOAD_CERTIFICATES` với giá trị `*` trong phần Configuration. Trong mã C#, họ dùng đoạn sau để nạp chứng chỉ: 💻📄🔧
```
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(
X509FindType.FindByThumbprint,
"",
validOnly: false);
```
Với chứng chỉ đã được nạp, họ sử dụng `HttpClientHandler.ClientCertificates` để đính kèm chứng chỉ vào mỗi yêu cầu HTTPS đến API nội bộ, đảm bảo xác thực thành công trong môi trường bảo mật cao. 🔒🚀📡
🔁🔐⚙️ Để đảm bảo connection string không bị thay đổi khi hoán đổi giữa các deployment slot trong Azure App Service (ví dụ giữa staging và production), bạn cần đánh dấu connection string đó là một **Deployment slot setting**. Khi một setting được đánh dấu như vậy, nó sẽ "dính" với slot mà nó được cấu hình, và sẽ không bị di chuyển hay ghi đè khi thực hiện thao tác swap. Điều này đặc biệt hữu ích trong các kịch bản phân tách môi trường, nơi mỗi slot có thể kết nối với các cơ sở dữ liệu hoặc tài nguyên khác nhau. Các cấu hình khác như Deployment Center, Managed Identity hay Scale Up không ảnh hưởng đến hành vi của connection string trong quá trình swap, do đó không thể dùng để giải quyết yêu cầu này. 🧩🛡️✅
📌🔧🗂️ Ví dụ: Giả sử bạn có một ứng dụng web tên là `app1` chạy trên Azure App Service với hai deployment slot: `production` và `staging`. Mỗi slot kết nối đến một cơ sở dữ liệu SQL Server khác nhau để đảm bảo dữ liệu không bị ghi đè giữa các môi trường. Trong phần cấu hình của Azure App Service, bạn thêm một connection string có tên là `DefaultConnection`, và đánh dấu nó là **Deployment slot setting**. Điều này đảm bảo rằng connection string cho production slot sẽ luôn trỏ đến cơ sở dữ liệu production, và connection string của staging sẽ luôn dùng cơ sở dữ liệu dành cho môi trường kiểm thử — kể cả khi bạn thực hiện swap hai slot. Nếu không đánh dấu là slot setting, hai connection string sẽ bị hoán đổi cho nhau, gây nguy cơ ứng dụng kiểm thử ghi dữ liệu vào cơ sở dữ liệu production. 🚨📉🛠️
🌐🔧📥 Để cho phép một ứng dụng Azure Web App nhận các yêu cầu từ một nguồn bên ngoài như `https://myapps.com`, bạn cần cấu hình chính sách CORS (Cross-Origin Resource Sharing) bằng cách sử dụng lệnh `az webapp cors add`. Cụ thể, bạn dùng lệnh: `az webapp cors add -g MyResourceGroup -n MyWebApp --allowed-origins https://myapps.com` để cho phép origin này gửi request đến ứng dụng. Các tùy chọn khác như `identity add`, `traffic-routing set` hoặc `access-restriction add` không phù hợp trong trường hợp này vì chúng phục vụ cho các mục đích khác như gán managed identity, cấu hình phân phối traffic giữa các slot hoặc giới hạn truy cập. Do đó, sử dụng `cors add` là cách chính xác để thiết lập cho phép truy cập từ domain bên ngoài. ✅🛡️🌍
🔍 Ví dụ: Một nhóm phát triển đang xây dựng một frontend ứng dụng React được lưu trữ trên `https://myapps.com` và backend API được triển khai trên Azure Web App tên là `MyWebApp`. Khi người dùng sử dụng frontend để gửi yêu cầu đến API, trình duyệt sẽ chặn các yêu cầu CORS nếu không được cấu hình đúng. Để giải quyết điều này, nhóm phát triển sử dụng lệnh sau: 💻📡🚀
```
az webapp cors add -g MyResourceGroup -n MyWebApp --allowed-origins https://myapps.com
```
Sau khi chạy lệnh này, Azure Web App sẽ cho phép nhận các yêu cầu HTTP từ frontend tại `https://myapps.com`, đảm bảo hoạt động liền mạch giữa frontend và backend trong quá trình phát triển và triển khai. 🔄✅📶
🧭⚙️🔁 Để đảm bảo một ứng dụng client được định tuyến đến cùng một instance trong suốt thời gian phiên khi triển khai Azure App Service với nhiều instance, bạn cần bật tính năng **ARR Affinity** (Application Request Routing Affinity). Thiết lập này tạo ra một cơ chế gắn kết giữa người dùng và instance cụ thể, giúp giữ trạng thái phiên (session state) ổn định trong suốt quá trình tương tác, đặc biệt hữu ích với các ứng dụng không sử dụng cơ chế lưu trữ trạng thái phân tán. Các lựa chọn khác như **WebSocket**, **Always on** hoặc **HTTP version** không có tác dụng duy trì tính nhất quán về routing phiên. Do đó, ARR Affinity là cấu hình nền tảng phù hợp và chính xác để đáp ứng yêu cầu về định tuyến phiên trong môi trường multi-instance của Azure App Service. 🔒🧩🔄
🔍 Ví dụ: Một công ty phát triển một ứng dụng thương mại điện tử có giao diện người dùng Angular và backend .NET chạy trên Azure App Service với nhiều instance để phục vụ hàng nghìn người dùng đồng thời. Mỗi khi người dùng thêm sản phẩm vào giỏ hàng, thông tin được lưu tạm thời trong bộ nhớ phiên trên server. Để đảm bảo người dùng không bị mất giỏ hàng khi yêu cầu được gửi đến một instance khác, nhóm kỹ thuật đã bật tính năng **ARR Affinity** trong App Service. Thiết lập này đảm bảo tất cả yêu cầu từ cùng một trình duyệt sẽ được định tuyến đến cùng một instance, giữ nguyên giỏ hàng và trải nghiệm người dùng mượt mà hơn trong suốt phiên mua sắm. 🛒🔄📌
Khi bạn triển khai một ứng dụng Azure App Service tên là app1 và đăng ký nó dưới dạng multi-tenant trong Microsoft Entra ID (thuộc tenant tên là tenant1), để cấp quyền truy cập Microsoft Graph API trong tenant1, bạn cần sử dụng service principal loại application. Service principal dạng application cho phép định cấu hình quyền truy cập cho app1 từ tenant khác với tenant gốc của ứng dụng (home tenant). Các tùy chọn khác như system-assigned managed identity hoặc user-assigned managed identity chỉ hoạt động trong cùng tenant với tài nguyên Azure, và không thể áp dụng trong kịch bản multi-tenant. Vì vậy, khi cần cấp quyền cho một ứng dụng multi-tenant để gọi Microsoft Graph API từ tenant mà nó không thuộc về, application service principal là lựa chọn chính xác và duy nhất phù hợp. 🧩📎✅
🔍 Ví dụ: Một công ty phần mềm phát triển một nền tảng quản lý nhân sự được triển khai dưới dạng ứng dụng multi-tenant Azure App Service. Ứng dụng này cho phép nhiều tổ chức (khách hàng) sử dụng đồng thời bằng cách đăng ký ứng dụng trong tenant của công ty và cho phép khách hàng đăng nhập từ tenant riêng của họ. Một trong các tính năng của ứng dụng là đọc thông tin người dùng từ Microsoft Entra ID (trước đây là Azure AD) của từng khách hàng. Để làm điều đó, công ty cấu hình quyền Microsoft Graph API thông qua application service principal trong tenant của từng khách hàng (ví dụ: tenant1). Nhờ đó, ứng dụng có thể thực hiện các lệnh gọi API như GET /users để lấy danh sách người dùng trong tenant của khách hàng, với sự đồng ý (consent) của admin tenant đó. 🔄🔑📊
Khi một ứng dụng đăng ký trong Microsoft Entra ID (ví dụ: app1) cần gọi một web API, và web API đó tiếp tục gọi Microsoft Graph thay mặt người dùng đã đăng nhập, bạn cần sử dụng On-Behalf-Of flow (OBO). Đây là một luồng xác thực OAuth 2.0 được thiết kế để truyền tải danh tính và quyền của người dùng qua chuỗi yêu cầu, từ ứng dụng ban đầu đến API trung gian và đến dịch vụ đích như Microsoft Graph. Các luồng khác như Authorization Code, Client Credentials hoặc Implicit không phù hợp trong trường hợp cần đại diện danh tính người dùng qua nhiều lớp dịch vụ. Vì vậy, On-Behalf-Of flow là lựa chọn duy nhất phù hợp để duy trì ủy quyền người dùng trong các hệ thống đa tầng sử dụng Microsoft Graph. 🔁🛡️📎
🔍 Ví dụ: Một công ty phát triển một cổng thông tin nội bộ, nơi người dùng đăng nhập để tra cứu thông tin hồ sơ cá nhân. Ứng dụng frontend (app1) nhận token người dùng sau khi đăng nhập và gửi yêu cầu đến một API backend nội bộ. API này sau đó cần truy vấn dữ liệu từ Microsoft Graph, chẳng hạn như lấy thông tin về nhóm mà người dùng thuộc về (GET /me/memberOf). Thay vì yêu cầu người dùng xác thực lại, API backend sử dụng On-Behalf-Of flow để yêu cầu một access token mới từ Microsoft Entra ID, sử dụng token ban đầu của người dùng như là credential. Nhờ đó, backend có thể truy cập Microsoft Graph thay mặt người dùng một cách an toàn, đảm bảo tính liên tục và bảo mật của chuỗi xác thực. 🧾🔑🔒
Khi bạn phát triển một ứng dụng web đa tenant như App1 và đăng ký nó trong Microsoft Entra ID, ứng dụng sẽ có một application object duy nhất được tạo trong tenant gốc (home tenant). Tuy nhiên, khi ứng dụng được sử dụng bởi các tenant khác, một service principal riêng biệt sẽ được tạo trong mỗi tenant đó để đại diện cho ứng dụng. Do đó, mối quan hệ đúng là: một application object – nhiều service principal. Điều này cho phép App1 được nhận diện và cấp quyền truy cập trong từng tenant mà nó được sử dụng, mà không cần tạo lại nhiều application object. Đây là mô hình tiêu chuẩn cho các ứng dụng đa tenant trong Entra ID. 🛡️⚙️✅
🔍 Ví dụ: Một công ty phát triển một ứng dụng SaaS quản lý dự án, được đăng ký trong Microsoft Entra ID của công ty với tên App1. Ứng dụng này cung cấp dịch vụ cho nhiều doanh nghiệp khác nhau, mỗi doanh nghiệp có tenant Microsoft Entra ID riêng. Khi một khách hàng mới đăng ký sử dụng dịch vụ, họ sẽ cấp quyền truy cập cho App1 trong tenant của họ. Quá trình này tạo ra một service principal riêng biệt trong tenant của khách hàng, cho phép ứng dụng được nhận diện và sử dụng trong tenant đó. Trong khi đó, chỉ một application object duy nhất của App1 tồn tại trong tenant của nhà phát triển. Điều này giúp quản lý ứng dụng tập trung, đồng thời hỗ trợ mở rộng quy mô đến nhiều khách hàng. 🌍🔗📈
Khi bạn cần tạo một shared access signature (SAS) token để cấp quyền đọc cho blob trong Azure Storage, nhưng vẫn đảm bảo tính bảo mật cao, bạn nên sử dụng Microsoft Entra ID credentials với vai trò Contributor thay vì dùng khóa tài khoản (primary hoặc secondary). Điều này giúp tránh việc rò rỉ khóa tài khoản – vốn có thể bị khai thác nghiêm trọng nếu bị lộ. Để tạo SAS token an toàn thông qua ủy quyền người dùng (user delegation), tài khoản cần được cấp quyền Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey, quyền này thuộc các vai trò như: Contributor, Storage Account Contributor, hoặc Storage Blob Delegator. Trong khi đó, tài khoản có vai trò Reader sẽ không đủ quyền để thực hiện hành động này. Vì vậy, dùng Entra ID với vai trò Contributor là phương án an toàn và phù hợp nhất để bảo vệ token khỏi bị xâm phạm. 🔒🔑✅
🔍 Ví dụ: Một công ty tổ chức sự kiện trực tuyến muốn chia sẻ tài liệu hội thảo được lưu trữ trên Azure Blob Storage cho người tham dự thông qua một đường dẫn tạm thời. Để đảm bảo bảo mật, họ không muốn sử dụng khóa tài khoản mà thay vào đó, họ tạo một SAS token dựa trên ủy quyền người dùng (user delegation SAS). Họ sử dụng một tài khoản đã được gán vai trò Contributor trong Microsoft Entra ID để thực hiện thao tác tạo token bằng cách sử dụng SDK hoặc lệnh az storage blob generate-sas với tuỳ chọn --as-user. Kết quả là đường dẫn chứa SAS token chỉ hoạt động trong thời gian giới hạn và người dùng chỉ có thể đọc nội dung blob, đảm bảo an toàn trong chia sẻ mà không cần tiết lộ khóa truy cập chính. 📁🕒🔗
📦🔐🧠 Để tạo một Shared Access Signature (SAS) token cấp quyền **đọc (Read)** cho một blob container trong Azure Storage, bạn cần đảm bảo rằng thuộc tính `Resource` trong `BlobSasBuilder` được đặt là "c" để đại diện cho container, và phương thức `SetPermissions()` phải chỉ định `BlobContainerSasPermissions.Read`. Nếu sử dụng giá trị "b" cho `Resource` hoặc gán quyền sai như `Create`, token sẽ không cung cấp quyền truy cập phù hợp cho container. Đoạn mã đúng sẽ tạo ra một URI chứa SAS token cho phép chỉ đọc dữ liệu từ container trong một khoảng thời gian giới hạn, giúp đảm bảo tính bảo mật và kiểm soát quyền truy cập hiệu quả. 🔒⏱️📤
🔍 Ví dụ: Một công ty tổ chức cuộc thi lập trình và muốn cung cấp quyền truy cập tạm thời cho thí sinh tải xuống tài liệu hướng dẫn từ Azure Blob Storage. Tài liệu được lưu trữ trong một container và không nên bị chỉnh sửa. Để làm điều này, nhóm kỹ thuật sử dụng đoạn mã C# tạo SAS token với quyền `Read` và `Resource = "c"` như sau: 💻📚🛠️
```
BlobSasBuilder sasBuilder = new BlobSasBuilder()
{
BlobContainerName = containerClient.Name,
Resource = "c",
ExpiresOn = DateTimeOffset.UtcNow.AddHours(2)
};
sasBuilder.SetPermissions(BlobContainerSasPermissions.Read);
Uri sasUri = containerClient.GenerateSasUri(sasBuilder);
```
Sau đó, họ chia sẻ liên kết `sasUri` đến thí sinh. Liên kết này chỉ cho phép đọc nội dung blob trong vòng 2 giờ, ngăn chặn mọi chỉnh sửa hoặc ghi đè ngoài ý muốn. 🔗📄✅
|