Contrôle d’accès dans l’API SQL Azure Cosmos DB

Azure Cosmos DB est un service de base de données NoSQL complètement managé pour le développement d’applications modernes. Cet article traite de l’API SQL pour Azure Cosmos DB. L’accès aux ressources dans l’API SQL est régi par un jeton de clé principale ou un jeton de ressource. Pour accéder à une ressource, le jeton sélectionné est inclus dans l’en-tête d’autorisation REST, dans le cadre de la chaîne d’autorisation.

Jetons de clé principale

Le jeton de clé master est le jeton de clé d’accès qui permet aux utilisateurs d’avoir un contrôle total des ressources Cosmos DB dans un compte particulier. La clé principale est créée lors de la création d'un compte. Il existe deux jeux de clés principales : la clé primaire et la clé secondaire. L'administrateur du compte peut ensuite opérer une rotation de clés à l'aide de la clé secondaire. De plus, l'administrateur du compte peut regénérer les clés si nécessaire. Pour obtenir des instructions sur la régénération et les clés propagées, consultez Sécuriser l’accès aux données dans Azure Cosmos DB.

Jetons de ressource

Les jetons de ressource sont créés lorsque les utilisateurs d’une base de données sont configurés avec des autorisations d’accès pour un contrôle d’accès précis sur une ressource, également appelée ressource d’autorisation. Une ressource d’autorisation contient un jeton de ressource de hachage construit avec les informations relatives au chemin d’accès à la ressource et au type d’accès auquel un utilisateur a accès. Le jeton de ressource d'autorisation est limité dans le temps et la période de validité peut être modifiée. Quand une action (POST, GET, PUT) est appliquée à une ressource d'autorisation, un nouveau jeton de ressource est généré. Pour plus d’informations sur les autorisations et les jetons de ressources, consultez Opérations sur les autorisations Cosmos DB.

En-tête d’autorisation.

Toutes les opérations REST, que vous utilisiez un jeton de clé master ou un jeton de ressource, doivent inclure l’en-tête d’autorisation avec la chaîne d’autorisation pour interagir avec une ressource. Le format de la chaîne d'autorisation est le suivant :

type={typeoftoken}&ver={tokenversion}&sig={hashsignature}  

Une chaîne d’autorisation ressemble à cet exemple :

type=master&ver=1.0&sig=5mDuQBYA0kb70WDJoTUzSBMTG3owkC0/cEN4fqa18/s=  

Les éléments entre crochets sont les suivants :

  • {typeoftoken} désigne le type de jeton : master, ressource ou aad(si vous utilisez RBAC Azure Cosmos DB).

  • {tokenversion} désigne la version du jeton, actuellement 1.0.

  • {hashsignature} désigne la signature de jeton hachée ou le jeton oauth si vous utilisez le RBAC Azure Cosmos DB.

La chaîne d'autorisation doit être codée avant de l'ajouter à la demande REST pour garantir qu'elle ne contient aucun caractère non valide. Vérifiez qu’il est encodé en Base64 à l’aide de MIME RFC2045. En outre, la clé master utilisée dans la signature de hachage doit être décodée à l’aide de MIME RFC2045, car elle est encodée en Base64. Si vous rencontrez des problèmes d’autorisation, découvrez comment diagnostiquer et résoudre les exceptions non autorisées.

Construction de la signature de jeton haché pour un jeton master

La signature de hachage pour le jeton de clé master peut être construite à partir des paramètres suivants : Verb, ResourceType, ResourceLink et Date.

  1. Le verbe représente le verbe HTTP de votre requête. Les valeurs possibles sont : get, post, put, patch, delete

Remarque : les valeurs doivent être en minuscules.

  1. La partie ResourceType de la chaîne identifie le type de ressource pour lequel la requête est destinée. Les valeurs possibles sont les suivantes :
    • Opérations de base de données : dbs
    • Opérations de conteneur : colls
    • Procédures stockées : sprocs
    • Fonctions définies par l’utilisateur : udfs
    • Déclenche: triggers
    • Utilisateurs: users
    • Autorisations: permissions
    • Opérations au niveau de l’élément : docs

Note: Les valeurs respectent la casse et doivent être en minuscules.

  1. La partie ResourceLink de la chaîne est la propriété identity de la ressource vers laquelle la requête est dirigée. La valeur ResourceLink dépend de l’opération que vous essayez d’exécuter. Chaque opération aura son propre ResourceLink correspondant suivant cette convention :
    • Si l’opération est effectuée sur une ressource spécifique, la valeur est le lien vers cette ressource. Exemples :

      • Pour Obtenir la base de données, utilisez : dbs/{databaseId}
      • Pour Obtenir un document, utilisez : dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • Si l’opération est effectuée sur un ensemble de ressources (List, Create, Query), la valeur est le lien de la ressource parente. Exemples :

      • Pour Créer un document, utilisez : dbs/{databaseId}/colls/{containerId}
      • Pour Créer une procédure stockée, utilisez : dbs/{databaseId}/colls/{containerId}
      • Pour Créer un conteneur, utilisez : dbs/{databaseId}
      • Pour Créer une base de données, utilisez : « » -> chaîne vide, car les bases de données n’ont pas de ressource parente

Note: Les noms de ressources référencés dans le cadre de la valeur ResourceLink respectent la casse et doivent correspondre à la casse de la façon dont ils ont été déclarés dans la base de données. Les autres composants doivent être en minuscules.

  1. La partie Date de la chaîne correspond à la date et à l’heure UTC d’envoi du message (au format « HTTP-date » tel que défini par les formats de date/heure RFC 7231), par exemple, « Mar, 01 Nov 1994 08:12:31 GMT ».

    En C#, vous pouvez l’obtenir à l’aide du spécificateur de format « R » sur la DateTime.UtcNow valeur.

    Cette même date (dans le même format) doit également être passée en tant qu’en-tête x-ms-date dans la demande.

Note: La valeur respecte la casse et doit être en minuscules.

Pour calculer la signature, nous utilisons la fonction HMAC (Hash-based Message Authentication Code) basée sur sha256 avec la clé CosmosDB comme secret.

La charge utile pour la fonction de hachage est basée sur les 4 composants présentés ci-dessus au format suivant : "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (notez la nouvelle ligne supplémentaire à la fin de la charge utile).

Le résultat encodé en Base64 de la fonction sera utilisé comme signature lors de la construction de l’en-tête d’autorisation pour l’appel.

Exemple [C#] pour un en-tête d’autorisation valide :

    httpClient.DefaultRequestHeaders.Clear();
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("authorization", auth); //generated using method below
    httpClient.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2018-12-31");

Exemple de méthode [C#] pour générer une signature d’autorisation valide :

Pour voir des exemples complets pour l’API REST Cosmos DB, consultez le dépôt Exemples d’API REST Cosmos DB sur GitHub

  
string GenerateMasterKeyAuthorizationSignature(HttpMethod verb, ResourceType resourceType, string resourceLink, string date, string key)
{
    var keyType = "master";
    var tokenVersion = "1.0";
    var payload = $"{verb.ToString().ToLowerInvariant()}\n{resourceType.ToString().ToLowerInvariant()}\n{resourceLink}\n{date.ToLowerInvariant()}\n\n";

    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
    var hashPayload = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payload));
    var signature = Convert.ToBase64String(hashPayload);
    var authSet = WebUtility.UrlEncode($"type={keyType}&ver={tokenVersion}&sig={signature}");

    return authSet;
}
  

Exemple [Node.js] :

  
var crypto = require("crypto");  
  
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceId, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  
  
    var text = (verb || "").toLowerCase() + "\n" +   
               (resourceType || "").toLowerCase() + "\n" +   
               (resourceId || "") + "\n" +   
               date.toLowerCase() + "\n" +   
               "" + "\n";  
  
    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  
  
    var MasterToken = "master";  
  
    var TokenVersion = "1.0";  
  
    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}  
  

Exemple d’encodage :

Argument Valeur
Verbe GET
Type de ressource « dbs »
Lien de ressource « dbs/ToDoList »
Date Jeu, 27 avr 2017 00:51:12 GMT
Clé : dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
Type de clé master
Version du jeton 1.0
Chaîne d’autorisation de sortie type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

Construction de la signature de hachage pour un jeton de ressource

Les jetons de ressource doivent être générés par un serveur intermédiaire. Le serveur sert de gardien de clé master et génère des jetons limités dans le temps pour les clients non approuvés, tels que les navigateurs web.

Ce serveur effectue les étapes suivantes :

  1. Gère les demandes de clients entrantes pour les nouveaux jetons.

  2. Vérifie l’identité du client d’une manière spécifique à l’application.

  3. Si le client s’authentifie correctement, il utilise les interfaces Cosmos DB (SDK ou REST) pour générer un nouveau jeton limité dans le temps et le retourne au client.

Voir aussi