Шаблон ключа камердинера

Azure
Хранилище Azure

Используйте токен, который предоставляет клиентам ограниченный прямой доступ к определенному ресурсу, чтобы разгрузить передачу данных из приложения. Это особенно полезно в приложениях, которые используют системы облачных хранилищ или очередей и могут снизить затраты до минимума, а также повысить масштабируемость и производительность до максимума.

Контекст и проблема

Клиентские программы и веб-браузеры часто должны читать и записывать файлы или потоки данных в хранилище приложения и из нее. Как правило, приложение будет обрабатывать перемещение данных— либо извлекая его из хранилища и потоковой передачи его клиенту, либо считывая переданный поток из клиента и сохраняя его в хранилище данных. Однако при этом подходе поглощаются ценные ресурсы, такие как вычисления, память и пропускная способность.

Хранилища данных имеют возможность обрабатывать отправленные и скачанные данные напрямую, не требуя, чтобы приложение выполняло какую-либо обработку для перемещения этих данных. Однако для этого обычно требуется, чтобы клиент имел доступ к учетным данным безопасности хранилища. Это может быть полезным методом, позволяющим минимизировать затраты на передачу данных и требования по горизонтальному увеличению масштаба, а также повысить производительность приложения. Однако это означает, что приложение больше не будет управлять безопасностью данных. После того как у клиента появилось подключение к хранилищу данных для прямого доступа, приложение не может выступать в роли привратника. Оно больше не контролирует процесс и не может предотвратить последующие отправки или скачивания из хранилища данных.

Это не реалистичный подход в распределенных системах, которым необходимо обслуживать ненадежных клиентов. Вместо этого приложения должны иметь возможность безопасно и точно управлять доступом, но при этом уменьшать нагрузку на сервер, настраивая это подключение и позволяя клиенту напрямую связываться с хранилищем данных для выполнения необходимых операций чтения или записи.

Решение

Необходимо решить проблему управления доступом к хранилищу данных, в котором хранилище не может управлять проверкой подлинности и авторизацией клиентов. Одним из типичных решений является ограничение доступа к общедоступному подключению к хранилищу данных и предоставление клиенту ключа или маркера, который может проверить хранилище данных.

Этот ключ или токен обычно называют ключом камердинера. Он обеспечивает ограниченный по времени доступ к определенным ресурсам и позволяет выполнять только предопределенные операции, такие как чтение и запись в хранилище или очереди, а также отправку и скачивание в веб-браузере. Приложения могут быстро и легко создавать и выдавать ключи камердинера клиентским устройствам и веб-браузерам, что позволяет клиентам выполнять требуемые операции, не требуя от приложения напрямую обрабатывать передачу данных. Это убирает дополнительные нагрузки, а также влияние на производительность и масштабируемость приложения и сервера.

Клиент использует этот токен для доступа к определенному ресурсу в хранилище данных только на определенный период и с конкретными ограничениями на разрешения доступа, как показано на рисунке. По истечении указанного периода ключ становится недействительным и больше не предоставляет доступ к ресурсу.

Рисунок 1. Общие сведения о шаблоне

Кроме того, можно настроить ключ с другими зависимостями, например область данных. Например, в зависимости от возможностей хранилища данных ключ может указывать полную таблицу в хранилище данных или только определенные строки в таблице. В облачных системах хранения ключ может указывать контейнер или только определенный элемент в контейнере.

Ключ также может стать недействительным для приложения. Это удобный подход, если клиент уведомляет сервер о завершении операции передачи данных. Затем сервер может сделать недействительным этот ключ, чтобы предотвратить дальнейший доступ.

Использование этого шаблона может упростить управление доступом к ресурсам, так как не нужно создавать пользователя и проверять его подлинность, предоставлять разрешения, а затем снова удалять пользователя. Кроме того, это упрощает ограничение расположения, разрешения и срока действия— все путем простого создания ключа во время выполнения. Важными факторами являются максимальное ограничение срока действия и в особенности расположения ресурса, чтобы получатель мог использовать его только по назначению.

Проблемы и рекомендации

При принятии решения о реализации этого шаблона необходимо учитывать следующие моменты.

Управляйте состоянием допустимости и периодом действия ключа. При утечке или нарушении безопасности ключ эффективно разблокирует целевой элемент и сделает его доступным для использования злоумышленником в течение срока действия. Ключ обычно можно отозвать или отключить, в зависимости от того, как он был выдан. Политики на стороне сервера могут быть изменены или ключ сервера, с помощью которого они были подписаны, может быть аннулирован. Укажите короткий срок действия, чтобы свести к минимуму риск несанкционированных операций в хранилище данных. Однако, если период действия слишком короткий, клиент может не успеть завершить операцию до истечения срока действия ключа. Разрешите авторизованным пользователям обновлять ключ до истечения срока действия, если требуется несколько обращений к защищенному ресурсу.

Управляйте уровнем доступа, который предоставляет ключ. Как правило, ключ должен позволять пользователю выполнять только действия, необходимые для завершения операции, такие как доступ только для чтения, если клиент не должен иметь возможности отправлять данные в хранилище данных. Для отправки файлов обычно указывается ключ, предоставляющий разрешение только на запись, а также расположение и срок действия. Очень важно точно указать ресурс или набор ресурсов, к которым применяется ключ.

Рассмотрим, как управлять поведением пользователей. Реализация этого шаблона означает некоторую потерю контроля над ресурсами, к которым предоставляется доступ пользователям. Уровень контроля, который может быть применен, ограничен возможностями политик и разрешений, доступных для службы или целевого хранилища данных. Например, обычно невозможно создать ключ, ограничивающий размер данных, записываемых в хранилище, или то, сколько раз ключ может использоваться для доступа к файлу. Это может привести к огромным непредвиденным расходам на передачу данных даже при использовании предполагаемым клиентом и может быть вызвано ошибкой в ​​коде, вызывающей повторную отправку или скачивание. Чтобы ограничить количество отправок файла, по возможности настройте клиент для принудительного уведомления приложения после завершения одной операции. Например, некоторые хранилища данных вызывают события, которые код приложения может использовать для мониторинга операций и управления поведением пользователя. Однако трудно применить квоты для отдельных пользователей в мультитенантном сценарии, где один и тот же ключ используется всеми пользователями из одного клиента.

Проверяйте и при необходимости очищайте все отправленные данные. Злоумышленник, который получает доступ к ключу, может отправлять данные, предназначенные для компрометации системы. Кроме того, авторизованные пользователи могут отправлять недопустимые данные, которые при обработке могут привести к ошибке или сбою системы. Чтобы избежать этого перед использованием, убедитесь, что все отправленные данные проверены на наличие вредоносного содержимого.

Выполняйте аудит всех операций. Многие механизмы, основанные на использовании ключей, могут записывать в журналы операции, такие как отправка и скачивание, а также сбои. Эти журналы обычно можно включить в процесс аудита, а также использовать для выставления счетов, если плата взимается с пользователя на основе размера файлов и объема данных. Используйте журналы для обнаружения ошибок проверки подлинности, которые могут быть вызваны проблемами с поставщиком ключей или случайным удалением хранимой политики доступа.

Доставляйте ключи безопасным образом. Ключ может быть встроен в URL-адрес, который пользователь активирует на веб-странице, или использоваться в операции перенаправления на сервере для автоматического скачивания. Всегда используйте HTTPS для доставки ключа по безопасному каналу.

Защищайте конфиденциальные данные во время передачи. Конфиденциальные данные, доставленные через приложение, обычно происходят с помощью TLS, и это должно быть применено для клиентов, обращаюющихся к хранилищу данных напрямую.

Ниже приведены другие проблемы, которые необходимо учитывать при реализации данного шаблона:

  • Если клиент не уведомляет или не может уведомить сервер о завершении операции, а единственным ограничением является срок действия ключа, приложение не сможет выполнять операции аудита, такие как подсчет операций отправки или скачивания, или предотвращать множественные отправки или скачивания.

  • Гибкость основных политик, которые могут быть созданы, может быть ограничена. Например, некоторые механизмы разрешают использование только временного периода истечения срока действия, а другие не могут задать достаточную степень детализации разрешений на чтение или запись.

  • Если указано время начала периода действия ключа или токена, убедитесь, что оно немного предшествует текущему времени сервера, позволяя работать часам клиента, которые могут быть немного рассинхронизированы. По умолчанию, если не задано, обычно это текущее время сервера.

  • URL-адрес, содержащий ключ, записывается в файлы журналов сервера. Хотя срок действия ключа, как правило, истекает, прежде чем файлы журнала будут использованы для анализа, ограничьте доступ к ним. Если данные журнала передаются в систему мониторинга или хранятся в другом расположении, рассмотрите возможность применения задержки во избежание утечки ключей до истечения срока их действия.

  • Если код клиента выполняется в веб-браузере, браузер может поддержать общий доступ к ресурсам независимо от источника (CORS), чтобы включить код, который выполняется в веб-браузере, и получить доступ к данным в другом домене из того, который обслуживал страницу. Некоторые старые браузеры и некоторые хранилища данных не поддерживают CORS, а код, который выполняется в этих браузерах, может не использовать ключ valet для предоставления доступа к данным в другом домене, например облачной учетной записи хранения.

Когда следует использовать этот шаблон

Этот шаблон будет полезен в следующих сценариях:

  • Чтобы свести к минимуму нагрузку ресурсов и обеспечить максимальную производительность и масштабируемость. Использование ключа камердинера не требует блокировки ресурса или удаленного вызова сервера, нет ограничений на количество выдаваемых ключей камердинера. Это позволяет избежать единой точки отказа, возникающей из-за передачи данных через код приложения. Создание ключа камердинера — это обычно простая криптографическая операция подписи строки с ключом.

  • Чтобы свести к минимуму операционные расходы. Включение прямого доступа к хранилищам и очередям — выгодный в отношении ресурсов и экономически обоснованный подход, который может уменьшить количество круговых путей в сети, а также сократить количество требуемых вычислительных ресурсов.

  • Когда клиенты регулярно отправляют или скачивают большие объемы данных или когда в каждой операции используются большие файлы.

  • Когда в приложении ограничены вычислительные ресурсы, либо из-за ограничений узла, либо из соображений стоимости. В этом сценарии шаблон будет еще более полезен, если есть много параллельных отправок или скачиваний данных, так как он освобождает приложение от обработки передачи данных.

  • Когда данные хранятся в удаленном хранилище данных или в другом центре данных. Если приложение должно было выступать в качестве привратника, за передачу данных между центрами обработки данных или между общедоступными и частными сетями, между клиентом и приложением, а затем между приложением и хранилищем данных может взиматься дополнительная плата за использование пропускной способности.

Этот шаблон неприменим в следующих случаях:

  • Если приложение должно выполнить некоторую задачу на основе данных перед ее сохранением или до ее отправки клиенту. Например, если приложение должно выполнить проверку, успешно получить доступ к журналу или выполнить преобразование данных. Однако некоторые хранилища данных и клиенты могут согласовывать и выполнять простые преобразования, такие как сжатие и декомпрессия (например, веб-браузер может обрабатывать форматы gzip).

  • Если структура имеющегося приложения затрудняет внедрение шаблона. Использование этого шаблона обычно требует другого архитектурного подхода к доставке и приему данных.

  • Если необходимо обслуживать журнал аудита или управлять количеством выполнений операции передачи данных, а используемый механизм ключа камердинера не поддерживает уведомления, которые сервер может использовать для управления этими операциями.

  • При необходимости ограничьте объем данных, особенно во время операций отправки. Единственным решением является проверка в приложении размера данных после завершения операции или проверка размера отправок через определенный период или по расписанию.

Проектирование рабочей нагрузки

Архитектор должен оценить, как шаблон ключа valet можно использовать в проектировании рабочей нагрузки для решения целей и принципов, описанных в основных принципах платформы Azure Well-Architected Framework. Например:

Принцип Как этот шаблон поддерживает цели основных компонентов
Решения по проектированию безопасности помогают обеспечить конфиденциальность, целостность и доступность данных и систем рабочей нагрузки. Этот шаблон позволяет клиенту напрямую обращаться к ресурсу, не требуя длительных или постоянных учетных данных. Все запросы доступа начинаются с проверяемой транзакции. Затем предоставленный доступ ограничен как в область, так и в течение. Этот шаблон также упрощает отмену предоставленного доступа.

- SE:05 Управление удостоверениями и доступом
Оптимизация затрат ориентирована на поддержание и улучшение рентабельности инвестиций рабочей нагрузки. Эта конструкция выгружает обработку как монопольную связь между клиентом и ресурсом без добавления компонента для непосредственной обработки всех клиентских запросов. Преимущество является наиболее драматическим, если клиентские запросы являются достаточно частыми или достаточно большими, чтобы требовать значительных ресурсов прокси-сервера.

- Затраты на co:09 Flow
Эффективность производительности помогает рабочей нагрузке эффективно соответствовать требованиям путем оптимизации масштабирования, данных, кода. Не используя промежуточный ресурс для прокси-сервера разгрузки доступа, обрабатывая как монопольную связь между клиентом и ресурсом, не требуя компонента посла, который должен обрабатывать все запросы клиентов путем выполнения. Преимущество использования этого шаблона наиболее важно, если прокси-сервер не добавляет значение в транзакцию.

- Pe:07 Code и инфраструктура

Как и любое решение по проектированию, рассмотрите любые компромиссы по целям других столпов, которые могут быть представлены с этим шаблоном.

Пример

Azure поддерживает подписанный URL-адрес в службе хранилища Azure для детального контроля доступа к данным в больших двоичных объектах, таблицах и очередях, а также для очередей и разделов служебной шины. Маркер подписанного URL-адреса можно настроить, чтобы предоставлять определенные права доступа, такие как чтение, запись, обновление и удаление в конкретной таблице; диапазон ключей внутри таблицы; очередь; большой двоичный объект; контейнер большого двоичного объекта. Срок действия может быть заданным периодом времени. Эта функция хорошо подходит для использования ключа валета для доступа.

Рассмотрим рабочую нагрузку, которая содержит сотни мобильных или классических клиентов, часто отправляющих большие двоичные файлы. Без этого шаблона рабочая нагрузка имеет по сути два варианта. Первое — предоставить постоянный доступ и конфигурацию всем клиентам для выполнения отправки непосредственно в учетную запись хранения. Другой — реализовать шаблон маршрутизации шлюза, чтобы настроить конечную точку, в которой клиенты используют прокси-доступ к хранилищу, но это может не добавлять дополнительное значение в транзакцию. Оба подхода страдают от проблем, связанных с контекстом шаблона:

  • Долгое время жизни, предварительные секреты. Потенциально без большого количества способов предоставления разных ключей разным клиентам.
  • Добавлены расходы на запуск вычислительной службы, которая имеет достаточные ресурсы для работы с текущим получением больших файлов.
  • Потенциально замедление взаимодействия с клиентом путем добавления дополнительного уровня вычислительных ресурсов и сетевого прыжка в процесс отправки.

Использование шаблона ключа valet устраняет проблемы безопасности, оптимизации затрат и производительности.

Схема, на которой показан доступ клиента к учетной записи хранения после первого получения маркера доступа из API.

  1. Клиенты, прошедшие последний ответственный момент, проходят проверку подлинности в легком весе, масштабируемом и нулевом api-интерфейсе функции Azure для запроса доступа.

  2. API проверяет запрос, а затем получает и возвращает время и область ограниченный токен SaS.

    Маркер, созданный API, ограничивает клиента следующими ограничениями:

    • Какую учетную запись хранения следует использовать. Это означает, что клиенту не нужно знать эту информацию заранее.
    • Используемый контейнер и имя файла; убедитесь, что маркер можно использовать, по крайней мере, с одним файлом.
    • Короткое окно операции, например три минуты. Этот короткий период времени гарантирует, что маркеры имеют TTL, которые не расширяются после его служебной программы.
    • Разрешения только для создания большого двоичного объекта, а не скачивания, обновления или удаления.
  3. Затем этот маркер используется клиентом в течение узкого периода времени для отправки файла непосредственно в учетную запись хранения.

API создает эти маркеры авторизованным клиентам с помощью ключа делегирования пользователей на основе управляемого удостоверения Microsoft Entra ID API. Ведение журнала включается как в учетных записях хранения, так и в API создания маркеров, разрешают корреляцию между запросами маркеров и использованием маркеров. API может использовать сведения о проверке подлинности клиента или другие данные, доступные для него, чтобы решить, какую учетную запись хранения или контейнер использовать, например в мультитенантной ситуации.

Полный пример доступен на сайте GitHub в примере шаблона Valet Key. Приведенные ниже фрагменты кода адаптированы из этого примера. В первом примере показано, как функция Azure (найденная в ValetKey.Web) создает маркер подписи подписанного пользователем общего доступа с помощью собственного управляемого удостоверения функции Azure.

[Function("FileServices")]
public async Task<StorageEntitySas> GenerateTokenAsync([HttpTrigger(...)] HttpRequestData req, ..., 
                                                        CancellationToken cancellationToken)
{
  // Authorize the caller, select a blob storage account, container, and file name.
  // Authenticate to the storage account with the Azure Function's managed identity.
  ...

  return await GetSharedAccessReferenceForUploadAsync(blobContainerClient, blobName, cancellationToken);
}

/// <summary>
/// Return an access key that allows the caller to upload a blob to this
/// specific destination for about three minutes.
/// </summary>
private async Task<StorageEntitySas> GetSharedAccessReferenceForUploadAsync(BlobContainerClient blobContainerClient, 
                                                                            string blobName,
                                                                            CancellationToken cancellationToken)
{
  var blobServiceClient = blobContainerClient.GetParentBlobServiceClient();
  var blobClient = blobContainerClient.GetBlockBlobClient(blobName);

  // Allows generating a SaS token that is evaluated as the union of the RBAC permissions on the managed identity
  // (for example, Blob Data Contributor) and then narrowed further by the specific permissions in the SaS token.
  var userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow.AddMinutes(-3),
                                                                            DateTimeOffset.UtcNow.AddMinutes(3),
                                                                            cancellationToken);

  // Limit the scope of this SaS token to the following:
  var blobSasBuilder = new BlobSasBuilder
  {
      BlobContainerName = blobContainerClient.Name,     // - Specific container
      BlobName = blobClient.Name,                       // - Specific filename
      Resource = "b",                                   // - Blob only
      StartsOn = DateTimeOffset.UtcNow.AddMinutes(-3),  // - For about three minutes (+/- for clock drift)
      ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(3),  // - For about three minutes (+/- for clock drift)
      Protocol = SasProtocol.Https                      // - Over HTTPS
  };
  blobSasBuilder.SetPermissions(BlobSasPermissions.Create);

  return new StorageEntitySas
  {
      BlobUri = blobClient.Uri,
      Signature = blobSasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName).ToString();
  };
}

Следующий фрагмент кода — это объект передачи данных (DTO), используемый КАК API, так и клиентом.

public class StorageEntitySas
{
  public Uri? BlobUri { get; internal set; }
  public string? Signature { get; internal set; }
}

Затем клиент (найденный в ValetKey.Client) использует URI и маркер, возвращенный API, для выполнения отправки без необходимости дополнительных ресурсов и полной производительности клиента к хранилищу.

...

// Get the SaS token (valet key)
var blobSas = await httpClient.GetFromJsonAsync<StorageEntitySas>(tokenServiceEndpoint);
var sasUri = new UriBuilder(blobSas.BlobUri)
{
    Query = blobSas.Signature
};

// Create a blob client using the SaS token as credentials
var blob = new BlobClient(sasUri.Uri);

// Upload the file directly to blob storage
using (var stream = await GetFileToUploadAsync(cancellationToken))
{
    await blob.UploadAsync(stream, cancellationToken);
}

...

Следующие шаги

При реализации этого шаблона может потребоваться следующее руководство.

При реализации этого шаблона могут быть также важны следующие шаблоны:

  • Шаблон привратника. Этот шаблон можно использовать в сочетании с шаблоном ключа камердинера для защиты приложений и служб с помощью выделенного экземпляра узла, который выполняет роль брокера между клиентами и приложением или службой. Привратник проверяет и очищает запросы, а также передает запросы и данные между клиентом и приложением. Обеспечивает дополнительный уровень защиты и уменьшает степень влияния атаки на систему.
  • Шаблон размещения статического содержимого. Здесь описано, как развертывать статические ресурсы в облачной службе хранения, которая может доставлять эти ресурсы непосредственно клиенту, чтобы уменьшить потребность в дорогостоящих экземплярах вычислений. Если ресурсы не предназначены для публичного доступа, шаблон ключа камердинера можно использовать для их защиты.