Zugriffssteuerung in der Azure Cosmos DB-SQL-API

Azure Cosmos DB ist ein vollständig verwalteter NoSQL-Datenbankdienst für die moderne App-Entwicklung. Dieser Artikel enthält Informationen zur SQL-API für Azure Cosmos DB. Der Zugriff auf Ressourcen in der SQL-API wird von einem Hauptschlüsseltoken oder einem Ressourcentoken gesteuert. Für den Zugriff auf eine Ressource wird das ausgewählte Token als Teil der Autorisierungszeichenfolge in den REST-Autorisierungsheader eingefügt.

Masterschlüsseltoken

Das master Schlüsseltokens ist das All-Access-Schlüsseltoken, mit dem Benutzer die vollständige Kontrolle über Cosmos DB-Ressourcen in einem bestimmten Konto haben können. Der Hauptschlüssel wird während der Erstellung eines Kontos erstellt. Es gibt zwei Sätze von Hauptschlüsseln, den Primärschlüssel und den sekundären Schlüssel. Der Administrator des Kontos kann dann eine Schlüsselrotation mit dem sekundären Schlüssel durchführen. Der Kontoadministrator kann darüber hinaus auch die Schlüssel nach Bedarf neu generieren. Anweisungen zum Erneuten Generieren und Rollen von Schlüsseln finden Sie unter Sichern des Zugriffs auf Daten in Azure Cosmos DB.

Ressourcentoken

Ressourcentoken werden erstellt, wenn Benutzer in einer Datenbank mit Zugriffsberechtigungen für eine präzise Zugriffssteuerung für eine Ressource eingerichtet werden, die auch als Berechtigungsressource bezeichnet wird. Eine Berechtigungsressource enthält ein Hashressourcentoken, das mit den Informationen zum Ressourcenpfad und Zugriffstyp erstellt wurde, auf die ein Benutzer Zugriff hat. Das Berechtigungsressourcentoken ist zeitlich begrenzt, und die Gültigkeitsdauer kann überschrieben werden. Wenn eine Berechtigungsressource bearbeitet wird (POST, GET, PUT), wird ein neues Ressourcentoken generiert. Informationen zu Berechtigungen und Ressourcentoken finden Sie unter Vorgänge für Cosmos DB-Berechtigungen.

Authorization header (Autorisierungsheader)

Alle REST-Vorgänge, unabhängig davon, ob Sie ein master Schlüsseltoken oder Ressourcentoken verwenden, müssen den Autorisierungsheader mit der Autorisierungszeichenfolge enthalten, um mit einer Ressource zu interagieren. Die Autorisierungszeichenfolge weist das folgende Format auf:

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

Eine Autorisierungszeichenfolge sieht wie in diesem Beispiel aus:

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

Die Teile in Klammern bedeuten Folgendes:

  • {typeoftoken} gibt den Typ des Tokens an: master, Ressource oder aad (bei Verwendung von Azure Cosmos DB RBAC).

  • {tokenversion} gibt die Version des Tokens an, derzeit 1.0.

  • {hashsignature} gibt die Signatur des Hashtokens oder das oauth-Token an, wenn Sie azure Cosmos DB RBAC verwenden.

Vor dem Hinzufügen der Autorisierungszeichenfolge zur REST-Anforderung sollte sie codiert werden, um sicherzustellen, dass sie keine ungültigen Zeichen enthält. Stellen Sie sicher, dass sie mit MIME RFC2045 base64-codiert ist. Außerdem sollte der in der Hashsignatur verwendete master Schlüssel mit MIME RFC2045 decodiert werden, da er Base64-codiert ist. Wenn Probleme mit der Autorisierung auftreten, lesen Sie Diagnose und Problembehandlung für nicht autorisierte Ausnahmen.

Erstellen der Hashtokensignatur für ein master Token

Die Hashsignatur für das master Schlüsseltoken kann aus den folgenden Parametern erstellt werden: Verb, ResourceType, ResourceLink und Date.

  1. Das Verb stellt das HTTP-Verb Ihrer Anforderung dar. Mögliche Werte sind: get, post, put, patch, delete

Hinweis: Die Werte müssen kleingeschrieben sein.

  1. Der ResourceType-Teil der Zeichenfolge gibt den Ressourcentyp an, für den die Anforderung gilt. Mögliche Werte:
    • Datenbankvorgänge: dbs
    • Containervorgänge: colls
    • Gespeicherte Prozeduren: sprocs
    • Benutzerdefinierte Funktionen: udfs
    • Trigger: triggers
    • Benutzer: users
    • Berechtigungen: permissions
    • Vorgänge auf Elementebene: docs

Hinweis: Bei den Werten wird die Groß-/Kleinschreibung beachtet.

  1. Der ResourceLink-Teil der Zeichenfolge ist die Identitätseigenschaft der Ressource, an die die Anforderung gerichtet ist. Der ResourceLink-Wert ist abhängig von dem Vorgang, den Sie ausführen möchten. Jeder Vorgang verfügt gemäß dieser Konvention über einen eigenen entsprechenden ResourceLink:
    • Wenn der Vorgang für eine bestimmte Ressource ausgeführt wird, ist der Wert der Link zu dieser Ressource. Beispiele:

      • Für die Verwendung von Get Database: dbs/{databaseId}
      • Für die Verwendung von Dokumenten abrufen: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • Wenn der Vorgang für eine Gruppe von Ressourcen (Liste, Erstellen, Abfrage) ausgeführt wird, ist der Wert der Link der übergeordneten Ressource. Beispiele:

      • Für die Verwendung von Dokument erstellen: dbs/{databaseId}/colls/{containerId}
      • Verwenden Sie für "Gespeicherte Prozedur erstellen": dbs/{databaseId}/colls/{containerId}
      • Verwenden Sie zum Erstellen eines Containers Folgendes: dbs/{databaseId}
      • Verwenden Sie für "Datenbank erstellen": "" –> eine leere Zeichenfolge, da Datenbanken keine übergeordnete Ressource haben.

Hinweis: Bei den Ressourcennamen, auf die im Rahmen des ResourceLink-Werts verwiesen wird, wird die Groß-/Kleinschreibung beachtet und muss mit der Groß- und Kleinschreibung übereinstimmen, wie sie in der Datenbank deklariert wurden. Die anderen Komponenten müssen kleingeschrieben sein.

  1. Der Datumsteil der Zeichenfolge ist das UTC-Datum und die Uhrzeit, zu der die Nachricht gesendet wurde (im Format "HTTP-datum", wie in RFC 7231 Datums-/Uhrzeitformate definiert), z. B. "Tue, 01 Nov 1994 08:12:31 GMT".

    In C# kann sie mithilfe des Formatbezeichners "R" für den DateTime.UtcNow Wert abgerufen werden.

    Dasselbe Datum (im selben Format) muss auch als x-ms-date Header in der Anforderung übergeben werden.

Hinweis: Bei dem Wert wird die Groß-/Kleinschreibung beachtet.

Zum Berechnen der Signatur verwenden wir die SHA256-basierte HMAC-Funktion (Hash-Based Message Authentication Code) mit dem CosmosDB-Schlüssel als Geheimnis.

Die Nutzlast für die Hashfunktion basiert auf den vier oben dargestellten Komponenten im folgenden Format: "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (beachten Sie die zusätzliche neue Zeile am Ende der Nutzlast).

Das Base64-codierte Ergebnis der Funktion wird als Signatur verwendet, wenn der Autorisierungsheader für den Aufruf erstellt wird.

Beispiel [C#] für einen gültigen Autorisierungsheader:

    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");

Beispiel für die [C#]-Methode zum Generieren einer gültigen Autorisierungssignatur:

Vollständige Beispiele für die Cosmos DB-REST-API finden Sie unter Repository für Cosmos DB-REST-API-Beispiele auf 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;
}
  

Beispiel [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);  
}  
  

Beispielcodierung:

Argument Wert
Verb GET
Ressourcentyp "dbs"
Ressourcenlink "dbs/ToDoList"
Date Do, 27 Apr 2017 00:51:12 GMT
Schlüssel dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw.
Schlüsseltyp master
Tokenversion 1.0
Ausgabeautorisierungszeichenfolge type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

Erstellen der Hashsignatur für ein Ressourcentoken

Ressourcentoken müssen von einem Zwischenserver generiert werden. Der Server fungiert als master Schlüsselwächter und generiert zeitbeschränkte Token für nicht vertrauenswürdige Clients, z. B. Webbrowser.

Dieser Server führt die folgenden Schritte aus:

  1. Verarbeitet eingehende Clientanforderungen für neue Token.

  2. Überprüft die Clientidentität auf anwendungsspezifische Weise.

  3. Wenn sich der Client erfolgreich authentifiziert, verwendet er die Cosmos DB-Schnittstellen (SDK oder REST), um ein neues zeitlich begrenztes Token zu generieren und es an den Client zurückgibt.

Weitere Informationen