HardТеория2 min

Blob Storage для разработчиков

Типы блобов, уровни доступа, lifecycle management, SAS-токены, C# SDK

Blob Storage -- основное хранилище неструктурированных данных в Azure. На экзамене AZ-204 проверяют знание SDK, SAS-токенов и lifecycle management.

Работа с Blob Storage в C#

Подключение через SDK

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Identity;

// Рекомендуемый способ -- через DefaultAzureCredential (без ключей!)
var blobServiceClient = new BlobServiceClient(
    new Uri("https://mystorageaccount.blob.core.windows.net"),
    new DefaultAzureCredential());

// Альтернатива: connection string (для dev/test)
var blobServiceClient = new BlobServiceClient(connectionString);

// Получение контейнера
var containerClient = blobServiceClient.GetBlobContainerClient("orders");

// Создание контейнера (если не существует)
await containerClient.CreateIfNotExistsAsync(PublicAccessType.None);

CRUD-операции

// Upload: загрузка файла
var blobClient = containerClient.GetBlobClient("order-123.json");
await blobClient.UploadAsync(stream, new BlobHttpHeaders
{
    ContentType = "application/json"
});

// Upload из строки
var data = BinaryData.FromString(JsonSerializer.Serialize(order));
await blobClient.UploadAsync(data, overwrite: true);

// Download: скачивание файла
BlobDownloadInfo download = await blobClient.DownloadAsync();
using var reader = new StreamReader(download.Content);
string content = await reader.ReadToEndAsync();

// List: листинг блобов
await foreach (var blob in containerClient.GetBlobsAsync())
{
    Console.WriteLine($"{blob.Name} - {blob.Properties.ContentLength} bytes");
}

// Delete: удаление
await blobClient.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);

Метаданные и свойства

// Установка метаданных
var metadata = new Dictionary<string, string>
{
    { "orderId", "123" },
    { "customerId", "cust-001" }
};
await blobClient.SetMetadataAsync(metadata);

// Чтение свойств
var properties = await blobClient.GetPropertiesAsync();
Console.WriteLine($"Size: {properties.Value.ContentLength}");
Console.WriteLine($"Tier: {properties.Value.AccessTier}");

Lifecycle Management

Автоматическое перемещение блобов между уровнями доступа и удаление старых данных:

{
  "rules": [
    {
      "name": "move-to-cool-and-archive",
      "type": "Lifecycle",
      "definition": {
        "actions": {
          "baseBlob": {
            "tierToCool": { "daysAfterModificationGreaterThan": 30 },
            "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
            "delete": { "daysAfterModificationGreaterThan": 365 }
          },
          "snapshot": {
            "delete": { "daysAfterCreationGreaterThan": 90 }
          }
        },
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["orders/", "reports/"]
        }
      }
    }
  ]
}

Политика выше делает следующее:

  • Через 30 дней: перемещает блобы из Hot в Cool
  • Через 90 дней: перемещает из Cool в Archive
  • Через 365 дней: удаляет блоб
  • Снимки (snapshots) удаляются через 90 дней
  • Действует только на блобы с префиксом "orders/" и "reports/"

SAS Tokens (Shared Access Signature)

SAS-токен предоставляет временный ограниченный доступ к ресурсам хранилища без раскрытия ключа аккаунта.

Типы SAS

Тип Область Описание
Service SAS Один сервис (Blob/Queue/Table/File) Доступ к конкретному контейнеру или блобу
Account SAS Весь Storage Account Доступ к нескольким сервисам
User Delegation SAS Blob и Data Lake Подписан учетными данными Entra ID (рекомендуется!)

Генерация SAS в C#

// Service SAS
var sasBuilder = new BlobSasBuilder
{
    BlobContainerName = "orders",
    BlobName = "order-123.json",
    Resource = "b",  // "b" = blob, "c" = container
    ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);

var sasUri = blobClient.GenerateSasUri(sasBuilder);
// Результат: https://...blob.core.windows.net/orders/order-123.json?sv=...&sig=...

User Delegation SAS (рекомендуемый)

// User Delegation SAS -- подписан через Entra ID, без ключа аккаунта
var userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync(
    DateTimeOffset.UtcNow,
    DateTimeOffset.UtcNow.AddHours(1));

var sasBuilder = new BlobSasBuilder
{
    BlobContainerName = "orders",
    BlobName = "order-123.json",
    Resource = "b",
    ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);

var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
{
    Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName)
};

var sasUri = blobUriBuilder.ToUri();

Stored Access Policy

Stored Access Policy позволяет управлять несколькими SAS-токенами. Если нужно отозвать доступ, достаточно изменить или удалить политику -- все связанные SAS станут недействительными.

Конкурентный доступ

Blob Storage поддерживает оптимистичную конкуренцию через ETag:

var properties = await blobClient.GetPropertiesAsync();
var conditions = new BlobRequestConditions
{
    IfMatch = properties.Value.ETag // Update only if not changed
};

try
{
    await blobClient.UploadAsync(newData, conditions: conditions);
}
catch (RequestFailedException ex) when (ex.Status == 412)
{
    // Blob was modified by another process
    Console.WriteLine("Conflict: blob was modified");
}

Проверь себя

Какой тип SAS рекомендуется использовать как наиболее безопасный?

Lifecycle Management может автоматически перемещать блобы между уровнями. В каком порядке происходит перемещение?

Что означает параметр Resource = 'b' в BlobSasBuilder?

Как отозвать доступ у всех SAS-токенов, созданных через Stored Access Policy?