Controle de acesso na API de SQL do Azure Cosmos DB

O Azure Cosmos DB é um banco de dados NoSQL totalmente gerenciado para o desenvolvimento de aplicativos modernos. Este artigo cobre a API do SQL do Azure Cosmos DB. O acesso a recursos na API do SQL é regido por um token de chave mestra ou um token de recurso. Para acessar um recurso, o token selecionado é incluído no cabeçalho de autorização REST como parte da cadeia de caracteres de autorização.

Tokens de chave mestra

O token de chave master é o token de chave de acesso all que permite que os usuários tenham controle total dos recursos do Cosmos DB em uma conta específica. A chave mestra é criada durante a criação de uma conta. Há dois conjuntos de chaves mestras, a chave primária e secundária. O administrador da conta, em seguida, pode exercer a rotação de chaves usando a chave secundária. Além disso, o administrador da conta também pode regenerar as chaves conforme necessário. Para obter instruções sobre regeneração e rolagem de chaves, consulte Proteger o acesso aos dados no Azure Cosmos DB.

Tokens de recurso

Os tokens de recurso são criados quando os usuários em um banco de dados são configurados com permissões de acesso para controle de acesso preciso em um recurso, também conhecido como um recurso de permissão. Um recurso de permissão contém um token de recurso de hash construído com as informações sobre o caminho do recurso e o tipo de acesso ao qual um usuário tem acesso. O token de recurso de permissão é o limite de tempo e o período de validade pode ser substituído. Quando um recurso de permissão é tratado em (POST, GET, PUT), um novo token de recurso é gerado. Para obter informações sobre permissões e tokens de recurso, consulte Operações em permissões do Cosmos DB.

Cabeçalho de autorização

Todas as operações REST, quer você esteja usando um token de chave master ou um token de recurso, devem incluir o cabeçalho de autorização com a cadeia de caracteres de autorização para interagir com um recurso. A cadeia de caracteres de autorização tem o seguinte formato:

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

Uma cadeia de caracteres de autorização é semelhante a este exemplo:

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

As partes entre colchetes são as seguintes:

  • {typeoftoken} indica o tipo de token: master, recurso ou aad(se você estiver usando o RBAC do Azure Cosmos DB).

  • {tokenversion} indica a versão do token, atualmente 1.0.

  • {hashsignature} indica a assinatura de token com hash ou o token oauth se você estiver usando o RBAC do Azure Cosmos DB.

A cadeia de caracteres de autorização deve ser codificada antes de adicioná-la à solicitação REST, para garantir que ela não contenha caracteres inválidos. Verifique se ele é codificado em Base64 usando MIME RFC2045. Além disso, a chave de master usada na hashsignature deve ser decodificada usando MIME RFC2045, pois ela é codificada em Base64. Se você vir problemas com a autorização, confira como Diagnosticar e solucionar problemas de exceções não autorizadas.

Construindo a assinatura de token com hash para um token de master

A assinatura de hash para o token de chave master pode ser construída com base nos seguintes parâmetros: Verb, ResourceType, ResourceLink e Date.

  1. O verbo representa o verbo HTTP da sua solicitação. Os valores possíveis são: get, post, put, patch, delete

Observação:: os valores devem ser minúsculos.

  1. A parte ResourceType da cadeia de caracteres identifica o tipo de recurso para o qual a solicitação é. Os valores possíveis são:
    • Operações de banco de dados: dbs
    • Operações de contêiner: colls
    • Procedimentos armazenados: sprocs
    • Funções definidas pelo usuário: udfs
    • Gatilhos: triggers
    • Usuários: users
    • Permissões: permissions
    • Operações de nível de item: docs

Nota: Os valores diferenciam maiúsculas de minúsculas e devem ser minúsculos.

  1. A parte ResourceLink da cadeia de caracteres é a propriedade de identidade do recurso para o qual a solicitação é direcionada. O valor ResourceLink depende da operação que você está tentando executar. Cada operação terá seu próprio ResourceLink correspondente seguindo esta convenção:
    • Se a operação for executada em um recurso específico, o valor será o link para esse recurso. Exemplos:

      • Para obter o uso do banco de dados: dbs/{databaseId}
      • Para obter o uso do documento: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • Se a operação for executada em um conjunto de recursos (Listar, Criar, Consulta), o valor será o link do recurso pai. Exemplos:

      • Para criar documento, use: dbs/{databaseId}/colls/{containerId}
      • Para criar procedimento armazenado, use: dbs/{databaseId}/colls/{containerId}
      • Para Criar um contêiner, use: dbs/{databaseId}
      • Para Criar Banco de Dados, use: "" –> uma cadeia de caracteres vazia, pois os bancos de dados não têm um recurso pai

Nota: Os nomes de recursos que estão sendo referenciados como parte do valor ResourceLink diferenciam maiúsculas de minúsculas e devem corresponder ao uso de maiúsculas e minúsculas de como foram declarados no banco de dados. Os outros componentes devem estar em minúsculas.

  1. A parte Data da cadeia de caracteres é a data e hora UTC em que a mensagem foi enviada (no formato "DATA HTTP", conforme definido pelos Formatos de Data/Hora RFC 7231), por exemplo, "Ter, 01 Nov 1994 08:12:31 GMT".

    Em C#, ele pode ser obtido usando o especificador de formato "R" no DateTime.UtcNow valor .

    Essa mesma data (no mesmo formato) também precisa ser passada como x-ms-date cabeçalho na solicitação.

Nota: O valor diferencia maiúsculas de minúsculas e deve ser todo minúsculo.

Para calcular a assinatura, usamos a função HMAC (Código de Autenticação de Mensagem baseado em Hash) baseada em SHA256 com a Chave do CosmosDB como o segredo.

O conteúdo da função de hash baseia-se nos quatro componentes apresentados acima usando o seguinte formato: "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (observe a nova linha extra no final do conteúdo).

O resultado codificado em Base64 da função será usado como a assinatura ao construir o cabeçalho Authorization para a chamada.

Exemplo [C#] para um cabeçalho de autorização válido:

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

Exemplo de método [C#] para gerar uma assinatura de autorização válida:

Para ver exemplos completos da API REST do Cosmos DB, visite o repositório De exemplos da API REST do Cosmos DB no 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;
}
  

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

Codificação de exemplo:

Argumento Valor
Verbo GET
Tipo de recurso "dbs"
Link do Recurso "dbs/ToDoList"
Data Qui, 27 Abr 2017 00:51:12 GMT
Chave dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
Tipo de Chave master
Versão do token 1.0
Cadeia de caracteres de autorização de saída type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

Construindo a assinatura de hash para um token de recurso

Os tokens de recurso devem ser gerados por um servidor intermediário. O servidor serve como o guardião de chave master e gera tokens com restrição de tempo para clientes não confiáveis, como navegadores da Web.

Este servidor executa as seguintes etapas:

  1. Lida com solicitações de cliente de entrada para novos tokens.

  2. Verifica a identidade do cliente de uma maneira específica do aplicativo.

  3. Se o cliente for autenticado com êxito, ele usará as interfaces do Cosmos DB (SDK ou REST) para gerar um novo token limitado por tempo e o retornará ao cliente.

Consulte Também