Toegangsbeheer in de SQL-API van Azure Cosmos DB

Azure Cosmos DB is een volledig beheerde NoSQL-databaseservice voor het ontwikkelen van moderne apps. Dit artikel heeft betrekking op de SQL-API voor Azure Cosmos DB. Toegang tot resources in de SQL-API wordt beheerd via een hoofdsleuteltoken of een resourcetoken. Voor toegang tot een resource wordt het geselecteerde token opgenomen in de REST-autorisatie-header als onderdeel van de autorisatietekenreeks.

Hoofdsleuteltokens

Het hoofdsleuteltoken is het token met alle toegangssleutels waarmee gebruikers volledig beheer kunnen hebben over Cosmos DB-resources in een bepaald account. De hoofdsleutel wordt gemaakt tijdens het maken van een account. Er zijn twee sets hoofdsleutels, de primaire sleutel en de secundaire sleutel. De beheerder van het account kan vervolgens sleutelrotatie uitvoeren met behulp van de secundaire sleutel. Bovendien kan de accountbeheerder de sleutels indien nodig opnieuw genereren. Zie Beveiligde toegang tot gegevens in Azure Cosmos DB voor instructies over het opnieuw genereren en rollen van sleutels.

Resourcetokens

Resourcetokens worden gemaakt wanneer gebruikers in een database zijn ingesteld met toegangsmachtigingen voor nauwkeurig toegangsbeheer voor een resource, ook wel een machtigingsresource genoemd. Een machtigingsresource bevat een hash-resourcetoken dat is samengesteld met de informatie over het resourcepad en het toegangstype waar een gebruiker toegang toe heeft. Het token van de machtigingsresource is tijdgebonden en de geldigheidsperiode kan worden overschreven. Wanneer een machtigingsresource wordt uitgevoerd op (POST, GET, PUT), wordt er een nieuw resourcetoken gegenereerd. Zie Bewerkingen op Cosmos DB-machtigingen voor meer informatie over machtigingen en resourcetokens.

Autorisatieheader

Alle REST-bewerkingen, ongeacht of u een token voor de hoofdsleutel of een resourcetoken gebruikt, moeten de autorisatieheader met de autorisatietekenreeks bevatten om met een resource te kunnen werken. De autorisatiereeks heeft de volgende indeling:

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

Een autorisatietekenreeks ziet er als volgt uit:

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

De tussen haakjes geplaatste onderdelen zijn als volgt:

  • {typeoftoken} geeft het type token aan: master, resource of aad (als u Azure Cosmos DB RBAC gebruikt).

  • {tokenversion} geeft de versie van het token aan, momenteel 1.0.

  • {hashsignature} geeft de handtekening van het gehashte token of het oauth-token aan als u Azure Cosmos DB RBAC gebruikt.

De autorisatiereeks moet worden gecodeerd voordat u deze toevoegt aan de REST-aanvraag om ervoor te zorgen dat deze geen ongeldige tekens bevat. Zorg ervoor dat deze Base64-codering heeft met MIME RFC2045. De hoofdsleutel die in de hashsignature wordt gebruikt, moet ook worden gedecodeerd met MIME RFC2045, omdat deze base64-codering heeft. Als u problemen met autorisatie ziet, raadpleegt u Problemen met niet-geautoriseerde uitzonderingen vaststellen en oplossen.

De gehashte tokenhandtekening voor een hoofdtoken maken

De hashhandtekening voor het hoofdsleuteltoken kan worden samengesteld op basis van de volgende parameters: Verb, ResourceType, ResourceLink en Date.

  1. Het werkwoord vertegenwoordigt het HTTP-werkwoord van uw aanvraag. Mogelijke waarden zijn: get, post, put, patch, delete

Opmerking:: de waarden moeten kleine letters zijn.

  1. Het gedeelte ResourceType van de tekenreeks geeft het type resource aan waarvoor de aanvraag is bedoeld. Mogelijke waarden zijn:
    • Databasebewerkingen: dbs
    • Containerbewerkingen: colls
    • Opgeslagen procedures: sprocs
    • Door de gebruiker gedefinieerde functies: udfs
    • Triggers: triggers
    • Gebruikers: users
    • Machtigingen: permissions
    • Bewerkingen op itemniveau: docs

Opmerking: De waarden zijn hoofdlettergevoelig en moeten kleine letters bevatten.

  1. Het ResourceLink-gedeelte van de tekenreeks is de identiteitseigenschap van de resource waarop de aanvraag is gericht. De waarde van ResourceLink is afhankelijk van de bewerking die u probeert uit te voeren. Elke bewerking heeft een eigen overeenkomstige ResourceLink volgens deze conventie:
    • Als de bewerking wordt uitgevoerd op een specifieke resource, is de waarde de koppeling naar die resource. Voorbeelden:

      • Gebruik voor Get Database: dbs/{databaseId}
      • Gebruik voor Document ophalen: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • Als de bewerking wordt uitgevoerd op een set resources (Lijst, Maken, Query), is de waarde de koppeling van de bovenliggende resource. Voorbeelden:

      • Gebruik voor Document maken: dbs/{databaseId}/colls/{containerId}
      • Gebruik voor Opgeslagen procedure maken: dbs/{databaseId}/colls/{containerId}
      • Voor Een container maken gebruikt u het volgende: dbs/{databaseId}
      • Gebruik voor Database maken: "" -> een lege tekenreeks omdat databases geen bovenliggende resource hebben

Opmerking: De resourcenamen waarnaar wordt verwezen als onderdeel van de ResourceLink-waarde zijn hoofdlettergevoelig en moeten overeenkomen met de hoofdletters van hoe ze zijn gedeclareerd in de database. De andere onderdelen moeten uit kleine letters bestaan.

  1. Het datumgedeelte van de tekenreeks is de UTC-datum en -tijd waarop het bericht is verzonden (in http-datumnotatie zoals gedefinieerd door RFC 7231 datum-/tijdnotaties), bijvoorbeeld 'Tue, 01 Nov 1994 08:12:31 GMT'.

    In C# kan deze worden verkregen met behulp van de R-indelingsaanduiding voor de DateTime.UtcNow waarde.

    Dezelfde datum (in dezelfde indeling) moet ook worden doorgegeven als x-ms-date header in de aanvraag.

Opmerking: De waarde is hoofdlettergevoelig en moet alleen kleine letters bevatten.

Voor het berekenen van de handtekening gebruiken we de op SHA256 gebaseerde HMAC-functie (Hash-based Message Authentication Code) met de CosmosDB-sleutel als geheim.

De nettolading voor de hashing-functie is gebaseerd op de vier hierboven weergegeven onderdelen met de volgende indeling: "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (let op de extra nieuwe regel aan het einde van de nettolading).

Het met Base64 gecodeerde resultaat van de functie wordt gebruikt als handtekening bij het maken van de autorisatieheader voor de aanroep.

Voorbeeld [C#] voor een geldige autorisatieheader:

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

Voorbeeldmethode [C#] voor het genereren van een geldige autorisatiehandtekening:

Als u volledige voorbeelden voor Cosmos DB REST API wilt zien, gaat u naar de opslagplaats Cosmos DB REST API-voorbeelden op 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;
}
  

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

Voorbeeld van codering:

Argument Waarde
Verb GET
Resourcetype "dbs"
Resourcekoppeling "dbs/ToDoList"
Date Do, 27 Apr 2017 00:51:12 GMT
Sleutel dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
Sleuteltype model
Tokenversie 1.0
Uitvoerautorisatietekenreeks type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

De hashhandtekening voor een resourcetoken maken

Resourcetokens moeten worden gegenereerd door een tussenliggende server. De server fungeert als de master-key guardian en genereert tijdgebonden tokens voor niet-vertrouwde clients, zoals webbrowsers.

Deze server voert de volgende stappen uit:

  1. Verwerkt binnenkomende clientaanvragen voor nieuwe tokens.

  2. Controleert de clientidentiteit op een toepassingsspecifieke manier.

  3. Als de client wordt geverifieerd, worden de Cosmos DB-interfaces (SDK of REST) gebruikt om een nieuw token met tijdslimiet te genereren en wordt dit naar de client geretourneerd.

Zie ook