Modifier

Modèle de clé de valet

Azure
Stockage Azure

Utilisez un jeton qui fournit aux clients un accès direct limité à une ressource spécifique, afin de décharger le transfert de données depuis l’application. Cela est particulièrement utile dans les applications qui utilisent des files d’attente ou des systèmes de stockage hébergés sur le cloud, et permet de réduire les coûts et d’optimiser l’extensibilité et les performances.

Contexte et problème

Les navigateurs web et les programmes clients ont souvent besoin de fichiers de lecture et d’écriture ou de flux de données en provenance ou à destination du stockage d’une application. En règle générale, l’application traitera le déplacement des données soit en les extrayant du stockage et en les transmettant au client, soit en lisant le flux chargé depuis le client et en le stockant dans le magasin de données. Toutefois, cette approche consomme des ressources précieuses comme des ressources de calcul, de la mémoire et de la bande passante.

Les magasins de données ont la possibilité de gérer directement le chargement et le téléchargement des données sans que l’application ait besoin d’effectuer de traitement particulier pour déplacer ces données. Toutefois, cela requiert généralement que le client ait accès aux informations d’identification de sécurité du magasin. Cette technique peut être utile pour réduire les coûts inhérents au transfert de données et la nécessité d’augmenter la taille des instances de l’application, ainsi que pour accroître les performances. Cela signifie néanmoins que l’application n’est plus en mesure de gérer la sécurité des données. Une fois que le client dispose d’une connexion au magasin de données pour l’accès direct, l’application ne peut pas agir en tant qu’opérateur de contrôle. Elle ne contrôle plus le processus et ne peut pas empêcher les chargements et téléchargements suivants depuis le magasin de données.

Cette approche n’est pas réaliste dans des systèmes distribués devant traiter des clients non approuvés. Au lieu de cela, les applications doivent être en mesure de contrôler en toute sécurité l’accès aux données de façon précise tout en réduisant la charge sur le serveur en configurant cette connexion, puis en autorisant le client à communiquer directement avec le magasin de données pour effectuer les opérations de lecture ou d’écriture requises.

Solution

Vous devez résoudre le problème de contrôle d’accès à un magasin de données quand le magasin ne peut pas gérer l’authentification et l’autorisation des clients. Une solution classique consiste à limiter l’accès à la connexion publique du magasin de données et à fournir au client une clé ou un jeton que le magasin de données peut valider.

Cette clé ou ce jeton est généralement appelé clé de valet. Il fournit un accès limité dans le temps à des ressources spécifiques et autorise uniquement des opérations prédéfinies telles que la lecture et l’écriture dans le stockage ou les files d’attente, ou le chargement et le téléchargement dans un navigateur web. Les applications peuvent rapidement et facilement créer et émettre des clés de valet pour les appareils clients et les navigateurs web, ce qui permet aux clients d’effectuer les opérations requises sans que l’application ait besoin de traiter directement le transfert de données. Cela supprime la surcharge de traitement, ainsi que l’impact sur les performances et l’extensibilité, de l’application et du serveur.

Le client utilise ce jeton pour accéder à une ressource spécifique du magasin de données pour une période particulière uniquement et avec certaines restrictions sur les autorisations d’accès, comme indiqué dans la figure. Après la période spécifiée, la clé n’est plus valide et ne permettra pas d’accéder à la ressource.

Figure 1 - Vue d’ensemble du modèle

Vous avez également la possibilité de configurer une clé possédant d’autres dépendances, comme l’étendue des données. Par exemple, selon les fonctionnalités du magasin de données, la clé peut spécifier une table complète dans un magasin de données ou uniquement des lignes spécifiques d’une table. Dans les systèmes de stockage cloud, la clé peut spécifier un conteneur, ou simplement un élément particulier d’un conteneur.

La clé peut également être rendue. non valide par l’application. Cette approche se révèle utile si le client informe le serveur de la fin de l’opération de transfert de données. Le serveur peut alors rendre cette clé non valide pour empêcher tout accès ultérieur.

L’utilisation de ce modèle peut simplifier la gestion de l’accès aux ressources, car vous n’avez plus de besoin de créer et d’authentifier un utilisateur, d’accorder des autorisations, puis de supprimer à nouveau l’utilisateur. Cela permet également de limiter l’emplacement, l’autorisation et la période de validité, le tout en générant simplement une clé lors de l’exécution. Les facteurs importants consistent à limiter autant que possible la période de validité, et particulièrement l’emplacement de la ressource, pour que le destinataire puisse uniquement utiliser la clé pour le but prévu.

Problèmes et considérations

Prenez en compte les points suivants lorsque vous choisissez comment implémenter ce modèle :

Gestion de l’état et de la période de validité de la clé. En cas de divulgation ou de compromission, la clé déverrouille l’élément cible et celui-ci peut faire l’objet d’utilisations malveillantes pendant la période de validité. Une clé peut généralement être révoquée ou désactivée, selon la façon dont elle a été émise. Les stratégies côté serveur peuvent être modifiées, ou la clé du serveur avec laquelle la connexion a été effectuée peut être rendue non valide. Spécifiez une période de validité courte pour réduire le risque que des opérations non autorisées se produisent sur le magasin de données. Toutefois, si la période de validité est trop courte, le client peut ne pas être en mesure de terminer l’opération avant l’expiration de la clé. Permettez aux utilisateurs autorisés de renouveler la clé avant l’expiration de la période de validité si plusieurs accès à la ressource protégée sont requis.

Contrôle du niveau d’accès fourni par la clé. En règle générale, la clé doit autoriser l’utilisateur à effectuer uniquement les actions nécessaires pour terminer l’opération, telles que l’accès en lecture seule si le client ne doit pas être en mesure de charger des données dans le magasin de données. Pour les chargements de fichiers, il est courant de spécifier une clé qui fournit une autorisation en écriture seule, ainsi que l’emplacement et la période de validité. Il est essentiel de spécifier précisément la ressource ou l’ensemble de ressources auxquels s’applique la clé.

Détermination de la façon de contrôler le comportement des utilisateurs. Implémenter ce modèle signifie que vous perdrez un certain degré de contrôle sur les ressources auxquelles les utilisateurs ont le droit d’accéder. Le niveau de contrôle pouvant être exercé est limité par les capacités des stratégies et des autorisations disponibles pour le service ou le magasin de données cible. Par exemple, il est généralement impossible de créer une clé qui limite la taille des données à écrire dans le stockage ou le nombre de fois où la clé peut être utilisée pour accéder à un fichier. Cela peut entraîner des coûts imprévus considérables pour le transfert de données, même en cas d’utilisation par le client prévu et peut être dû à une erreur dans le code qui provoque un chargement ou un téléchargement répétés. Pour limiter le nombre de fois où un fichier peut être chargé, lorsque cela est possible, forcez le client à informer l’application lorsqu’une opération est terminée. Par exemple, certains magasins de données déclenchent des événements que le code d’application peut utiliser pour surveiller les opérations et contrôler le comportement de l’utilisateur. Cependant, il est difficile d’imposer des quotas pour les utilisateurs individuels dans un scénario multi-locataire où la même clé est utilisée par tous les utilisateurs d’un même locataire.

Validation (et assainissement éventuel) de toutes les données chargées. Un utilisateur malveillant qui accède à la clé peut charger des données conçues pour compromettre le système. Des utilisateurs autorisés peuvent également charger des données non valides qui, une fois traitées, peuvent entraîner une erreur ou une panne dans le système. Pour vous protéger contre cela, assurez-vous que toutes les données chargées sont validées et qu’elles ne contiennent pas de contenus malveillants avant des utiliser.

Audit de toutes les opérations. De nombreux mécanismes basés sur une clé peuvent journaliser des opérations comme des chargements, des téléchargements et des échecs. Ces journaux d’activité peuvent généralement être intégrés à un processus d’audit et utilisés pour la facturation si l’utilisateur est facturé en fonction du volume de données ou de la taille de fichiers. Utilisez les journaux d’activité pour détecter des échecs d’authentification qui peuvent être dus à des problèmes avec le fournisseur de clés ou une suppression accidentelle d’une stratégie d’accès stockée.

Distribution sécurisée de la clé. Elle peut être incorporée dans une URL que l’utilisateur active sur une page web, ou elle peut être utilisée dans une opération de redirection du serveur afin que le téléchargement se produise automatiquement. Utilisez toujours le protocole HTTPS pour distribuer la clé sur un canal sécurisé.

Protection des données sensibles en transit. Les données sensibles distribuées via l’application le seront généralement à l’aide de TLS, et cela doit être appliqué pour les clients qui accèdent directement au magasin de données.

Les autres problèmes à connaître lors de l’implémentation de ce modèle sont :

  • Si le client n’informe pas, ou ne peut pas informer, le serveur de la fin de l’opération et que la seule limite est la période d’expiration de la clé, l’application ne sera pas en mesure d’effectuer des opérations d’audit comme compter le nombre de chargements ou téléchargements ou empêcher plusieurs chargements ou téléchargements.

  • La flexibilité des stratégies de clé pouvant être générées peut se trouver limitée. Par exemple, certains mécanismes autorisent uniquement l’utilisation d’une période d’expiration horodatée. D’autres ne sont pas en mesure de spécifier une granularité suffisante pour les autorisations de lecture/d’écriture.

  • Si l’heure de début de la période de validité du jeton ou de la clé est spécifiée, vérifiez qu’elle est légèrement antérieure à l’heure actuelle du serveur pour que les clients dont les horloges sont légèrement en dehors de la synchronisation puissent quand même utiliser le jeton ou la clé. La valeur par défaut, si elle n’est pas spécifiée, est généralement l’heure actuelle du serveur.

  • L’URL qui contient la clé sera enregistrée dans les fichiers journaux du serveur. Alors que la clé aura généralement expiré avant que les fichiers journaux soient utilisés pour l’analyse, assurez-vous de limiter l’accès à ces derniers. Si les données du journal sont transmises à un système de surveillance ou stockées dans un autre emplacement, envisagez d’implémenter un délai pour éviter toute divulgation de clés après l’expiration de la période de validité.

  • Si le code du client s’exécute dans un navigateur web, le navigateur peut devoir prendre en charge le partage des ressources cross-origin (CORS) pour permettre au code qui s’exécute dans le navigateur web d’accéder aux données dans un domaine différent de celui qui a traité la page. Certains navigateurs plus anciens et magasins de données ne prennent pas en charge le CORS, et le code qui s’exécute dans ces navigateurs peut ne pas être en mesure d’utiliser une clé de valet pour fournir un accès aux données dans un domaine différent, tel qu’un compte de stockage cloud.

Quand utiliser ce modèle

Ce modèle est utile dans les situations suivantes :

  • Pour réduire le chargement des ressources et optimiser les performances et l’extensibilité. L’utilisation d’une clé de valet ne nécessite pas que la ressource soit verrouillée, que d’appel soit passé au serveur distant, n’implique pas de limite en termes de nombre de clés de valet pouvant être émises, et permet d’éviter qu’un point de défaillance unique résultant de l’exécution du transfert de données via le code d’application. La création d’une clé de valet est généralement une simple opération de chiffrement de signature d’une chaîne avec une clé.

  • Pour réduire les coûts d’exploitation. Activer l’accès direct aux magasins et files d’attente permet d’économiser de l’argent et des ressources, peut réduire les allers-retours réseau et permettre de diminuer le nombre de ressources de calcul nécessaires.

  • Lorsque des clients chargent ou téléchargent régulièrement des données, notamment en cas de volume important ou quand chaque opération implique de gros fichiers.

  • Lorsque l’application a des ressources de calcul disponibles limitées, en raison de limitations d’hébergement ou de considérations en termes de coûts. Dans ce scénario, le modèle est encore plus utile s’il existe plusieurs chargements ou téléchargements de données simultanés, car il libère l’application de la gestion du transfert de données.

  • Lorsque les données sont stockées dans un magasin de données distant ou dans un autre centre de données. Si vous avez demandé à l’application d’agir en tant qu’opérateur de contrôle, des coûts peuvent s’appliquer pour la bande passante supplémentaire liée au transfert de données entre les centres de données, ou sur des réseaux publics ou privés entre le client et l’application, puis entre l’application et le magasin de données.

Ce modèle peut s’avérer inutile dans les situations suivantes :

  • Si l’application doit effectuer certaines tâches sur les données avant leur stockage ou leur envoi au client. Par exemple, si l’application doit effectuer des opérations de validation, d’accès au journal ou d’exécution d’une transformation sur les données. Toutefois, certains magasins de données et clients sont en mesure de négocier et d’effectuer des transformations simples telles que la compression et la décompression (par exemple, un navigateur web peut généralement traiter les formats gzip).

  • Si la conception d’une application existante complique l’incorporation du modèle. L’utilisation de ce modèle nécessite généralement une approche architecturale distincte pour transmettre et recevoir des données.

  • S’il est nécessaire de conserver les journaux d’audit ou de contrôler le nombre de fois où une opération de transfert de données est exécutée, et si le mécanisme de clé de valet utilisé ne prend pas en charge les notifications que le serveur peut utiliser pour gérer ces opérations.

  • S’il est nécessaire de limiter la taille des données, en particulier au cours des opérations de chargement. La seule solution à ce problème consiste à ce que l’application vérifie la taille des données une fois l’opération terminée, ou qu’elle vérifie la taille des chargements après une période spécifiée ou selon une planification.

Conception de la charge de travail

Un architecte devrait évaluer comment le modèle de Valet Key (clé de valet) peut être utilisé dans la conception de sa charge de travail pour répondre aux objectifs et principes couverts par les piliers d’Azure Well-Architected Framework. Par exemple :

Pilier Comment ce modèle soutient les objectifs des piliers.
Les décisions relatives à la conception de la sécurité permettent de garantir la confidentialité, l’intégrité et la disponibilité des données et des systèmes de votre charge de travail. Ce modèle permet à un client d’accéder directement à une ressource sans avoir besoin de justificatifs d’identité permanents ou de longue durée. Toutes les demandes d’accès commencent par une transaction qui peut-être auditée. L’accès accordé est ensuite limité en portée et en durée. Ce modèle facilite également la révocation de l’accès accordé.

- SE:05 Gestion de l’identité et des accès
L’optimisation des coûts est axée sur le maintien et l’amélioration du retour sur investissement de votre charge de travail. Cette conception décharge le traitement comme une relation exclusive entre le client et la ressource sans ajouter de composant pour gérer directement toutes les demandes des clients. L’avantage encore plus spectaculaire lorsque les demandes des clients sont fréquentes ou suffisamment importantes pour nécessiter des ressources de proxy significatives.

- CO :09 Coûts des flux
L’efficacité des performances permet à votre charge de travail de répondre efficacement aux demandes grâce à des optimisations de la mise à l’échelle, des données, du code. Ne pas utiliser une ressource intermédiaire pour rediriger via proxy l’accès décharge le traitement comme une relation exclusive entre le client et la ressource sans nécessiter un composant ambassadeur qui doit gérer toutes les demandes des clients de manière performante. L’avantage d’utiliser ce modèle est le plus significatif lorsque le proxy n’ajoute pas de valeur à la transaction.

- PE :07 Code et infrastructure

Comme pour toute autre décision de conception, il convient de prendre en compte les compromis par rapport aux objectifs des autres piliers qui pourraient être introduits avec ce modèle.

Exemple

Azure prend en charge des signatures d’accès partagé sur le stockage Azure pour le contrôle d’accès granulaire aux données dans les objets blob, tables et files d’attente et pour les rubriques et files d’attente Service Bus. Un jeton de signature d’accès partagé peut être configuré pour fournir des droits d’accès spécifiques telles que la lecture, l’écriture, la mise à jour et la suppression d’une table spécifique ; un groupe de clés dans une table ; une file d’attente ; un objet blob ; ou un conteneur d’objets blob. La validité peut être une période spécifiée. Cette fonctionnalité convient bien pour utiliser une clé valet pour l’accès.

Considérez une charge de travail qui a des centaines de clients mobiles ou de bureau téléchargeant fréquemment de gros binaires. Sans ce modèle, la charge de travail a essentiellement deux options. La première est de fournir un accès permanent et une configuration à tous les clients pour effectuer des téléchargements directs vers un compte de stockage. L’autre est d’implémenter le modèle de Routage Gateway pour mettre en place un point de terminaison où les clients utilisent un accès avec une redirection par proxy au stockage, mais cela pourrait ne pas ajouter de valeur supplémentaire à la transaction. Les deux approches souffrent de problèmes abordés dans le contexte du modèle :

  • Secrets partagés durables. Peu de moyens potentiels de fournir différentes clés à différents clients.
  • Coût supplémentaire pour l’exécution d’un service de calcul qui dispose de ressources suffisantes pour traiter actuellement de gros fichiers.
  • Ralentissement potentiel des interactions clients en ajoutant une couche supplémentaire de calcul et de saut réseau au processus de téléchargement.

L’utilisation du modèle de Clé de Valet (Valet Key) règle les problèmes de sécurité, d’optimisation des coûts et de performance.

Diagramme montrant un client accédant à un compte de stockage après avoir d’abord obtenu un jeton d’accès d’une API.

  1. Les clients, au dernier moment responsable, s’authentifient à une API hébergée par Azure Function légère, évolutive à zéro pour demander l’accès.

  2. L’API valide la demande puis obtient et retourne un jeton SaS limité dans le temps & la portée.

    Le jeton généré par l’API limite le client aux limitations suivantes :

    • Quel compte de stockage utiliser. Cela signifie que le client n’a pas besoin de connaître cette information à l’avance.
    • Un conteneur et un nom de fichier spécifiques à utiliser ; assurant que le jeton peut être utilisé avec, au plus, un fichier.
    • Une courte fenêtre d’opération, comme trois minutes. Cette courte période assure que les jetons ont un TTL qui ne dépasse pas leur utilité.
    • Permissions de seulement créer un blob ; pas de télécharger, mettre à jour, ou supprimer.
  3. Ce jeton est ensuite utilisé par le client, dans la fenêtre de temps étroite, pour télécharger le fichier directement sur le compte de stockage.

L’API génère ces jetons pour les clients autorisés en utilisant une clé de délégation d’utilisateur basée sur l’identité gérée Microsoft Entra ID propre à l’API. La journalisation est activée à la fois sur les comptes de stockage et sur l’API de génération de tokens, permettant de corréler les demandes de tokens et leur utilisation. L’API peut utiliser les informations d’authentification du client ou d’autres données disponibles pour décider quel compte de stockage ou quel conteneur utiliser, comme dans une situation multi-locataire.

Un exemple complet est disponible sur GitHub avec cet Exemple de modèle de clé de valet. Les extraits de code suivants sont adaptés de cet exemple. Le premier montre comment la Fonction Azure (trouvée dans ValetKey.Web) génère un token de signature d’accès partagé délégué par l’utilisateur en utilisant l’identité gérée propre de la Fonction 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();
  };
}

L’extrait suivant est l’objet de transfert de données (DTO) utilisé à la fois par l’API et le client.

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

Le client (trouvé dans ValetKey.Client) utilise ensuite l’URI et le token renvoyés par l’API pour effectuer le téléversement sans nécessiter de ressources supplémentaires et avec la pleine performance de transfert client-vers-stockage.

...

// 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);
}

...

Étapes suivantes

Les recommandations suivantes peuvent s’avérer utiles pendant l’implémentation de ce modèle :

Les modèles suivants peuvent également être pertinents lors de l’implémentation de ce modèle :

  • Modèle d’opérateur de contrôle. Ce modèle peut être utilisé avec le modèle de clé de valet pour protéger les applications et services à l’aide d’une instance d’hôte dédiée qui agit comme un répartiteur entre les clients et l’application ou le service. L’opérateur de contrôle valide et assainit les requêtes, et transmet les requêtes et les données entre le client et l’application. Il peut fournir une couche supplémentaire de sécurité et réduire la surface d’attaque du système.
  • Modèle d’hébergement de contenu statique. Décrit comment déployer des ressources statiques dans un service de stockage cloud qui peut fournir ces ressources directement au client afin de réduire le besoin d’instances de calcul coûteuses. Lorsque les ressources ne sont pas destinées à être publiquement disponibles, le modèle de clé de valet peut être utilisé afin de les sécuriser.