#python #azure #api #azure-cosmosdb #unauthorized
#python #azure #API #azure-cosmosdb #несанкционированный
Вопрос:
Согласно документации для Cosmos DB REST API, при каждом вызове API должен быть установлен заголовок авторизации. Значение для этого создается, как описано здесь: https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources
Я реализую это в Python следующим образом:
def get_authorisation_token(verb, resource_type, resource_id, date, master_key):
key = base64.b64decode(master_key)
text = f"""{verb.lower()}n{resource_type.lower()}n{resource_id.lower()}n{date.lower()}nn"""
text_encoded = text.encode('utf-8')
signature_hash = hmac.new(key, text_encoded, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(signature_hash).decode()
key_type = 'master'
version = '1.0'
uri = f'type={key_type}amp;ver={version}amp;sig={signature}'
uri_encoded = urllib.parse.quote(uri)
return uri_encoded
Поскольку это отправляется при каждом вызове, токен аутентификации необходимо создать заново, чтобы он соответствовал URL-адресу запроса. Так, например, чтобы получить список баз данных, необходимо указать тип ресурса, dbs
а ссылка / идентификатор ресурса — пустую строку с URL-адресом: https://{databaseaccount}.documents.azure.com/dbs/
Часть, которую я не могу понять, — это правильная комбинация типа ресурса и идентификатора ресурса / ссылки для получения всех пользователей из определенной базы данных. Документацию можно найти здесь: https://learn.microsoft.com/en-us/rest/api/cosmos-db/list-users
Я пробовал некоторые комбинации, но ничего не возвращает пользователям, я просто получаю 401:
{
"code": "Unauthorized",
"message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'getnusersndbs/<db_name>nmon, 09 nov 2020 23:37:24 gmtnn'rnActivityId: 697a4159-f160-4aab-ae90-6cb5eaadb710, Microsoft.Azure.Documents.Common/2.11.0"
}
Комментарии:
1. тип ресурса должен быть
users
, а ссылка на ресурс должна бытьdbs/{<db name>}
2. Я попробовал указать тип ресурса
users
и ссылкуdbs/db_name
, но это все равно не сработало. Возвращается та же ошибка, что и выше3. ОК. Я понимаю. Я проведу тест.
Ответ №1:
Что касается проблемы, пожалуйста, обратитесь к следующему коду
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import base64
from urllib.parse import quote
import hmac
from hashlib import sha256
import requests
from azure.cosmos.auth import GetAuthorizationHeader
from azure.cosmos.cosmos_client import CosmosClientConnection
master_key = ''
database_name = ''
key = base64.b64decode(master_key)
verb = 'GET'
resource_type = 'users'
resource_id = f'dbs/{database_name}'
now = datetime.now()
stamp = mktime(now.timetuple())
date = format_date_time(stamp)
print(date)
text = "{verb}n{resource_type}n{resource_id}n{date}n{other}n".format(
verb=(verb.lower() or ''),
resource_type=(resource_type.lower() or ""),
resource_id=(resource_id or ""),
date=date.lower(),
other="".lower())
body = text.encode("utf-8")
digest = hmac.new(key, body, sha256).digest()
signature = base64.encodebytes(digest).decode("utf-8")
key_type = 'master'
version = '1.0'
uri = f'type={key_type}amp;ver={version}amp;sig={signature[:-1]}'
uri_encoded = quote(uri)
url = "https://<>.documents.azure.com:443/dbs/<>/users"
payload = {}
headers = {
'Authorization': uri_encoded,
'x-ms-date': date,
'x-ms-version': '2018-12-31'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
Комментарии:
1. Если это полезно для вас, не могли бы вы принять это как ответ ?
2. Спасибо @Jim за помощь, это действительно решило проблему. В моем коде были неверны ResourceType и resourceId.