R: Azure Сбой запроса объекта таблицы через вызов REST - PullRequest
0 голосов
/ 10 февраля 2020

Я работаю с Azure, Databricks и R. Я пытаюсь вызвать Azure Табличные хранилища из ячейки R в записной книжке Databricks через ATS REST API . Я могу создавать / удалять таблицы, а также я могу вставлять новые сущности в существующие таблицы. Однако, если я пытаюсь запросить объекты, я всегда получаю ошибку 403. Вот мой код, который пытается отфильтровать по «RowKey = 1» и выбрать свойство «Имя».

 library(httr)

 key <- "myStorageKey"

 url <- "https://myAccount.table.core.windows.net/myTable()?$filter=(RowKey%20eq%20'1')?$select=Name"

 canonResource <- paste0("/", account, "/myTable()?$filter=(RowKey%20eq%20'1')?$select=Name")

Теперь я использую аутентификацию SharedKeyLite, как описано здесь

 requestdate <- format(Sys.time(),"%a, %d %b %Y %H:%M:%S %Z", tz="GMT")    

 signStr <- paste(requestdate, canonResource, sep = "\n") 


  auth <- paste0("SharedKeyLite myAccount:",
             RCurl::base64(digest::hmac(key = RCurl::base64Decode(key, mode = "raw"),
                                        object = enc2utf8(signStr),
                                        algo = "sha256", raw = TRUE)))

Теперь, в соответствии с описанием сущностей , мне нужно сформировать такой заголовок:

   header <- httr::add_headers(#`x-ms-version` = "2015-12-11 ",
                                `x-ms-date` = requestdate,  
                                 Authorization = auth,
                                #Accept = "application/json;odata=nometadata",
                                #`Accept-Charset` = "UTF-8",
                                 DataServiceVersion = "3.0;NetFx",
                                #Date = requestdate,
                                 MaxDataServiceVersion = "3.0;NetFx")

Однако вызов

 httr::GET(url = url, config = header, verbose())

дает меня

  HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

Кто-нибудь видит, что я пропускаю или делаю неправильно? Я поиграл с заголовком, отменяющим / комментирующим несколько необязательных, но он все равно не работает. Как уже говорилось, другие звонки по этому API работают для меня. Что меня несколько смущает, так это то, что в документации о вызове запроса я должен указать заголовок (Max) DataServiceVersion, даже если это необязательный заголовок!

1 Ответ

0 голосов
/ 10 февраля 2020

Проблема была в том, как вы создаете canonResource.

На основе documentation:

Общий ключ Формат сервиса Lite и Table для 2009-09-19 и более поздних версий

Этот формат поддерживает Shared Key и Shared Key Lite для всех версий сервиса Table и Shared Key Lite для версии 2009-09-19 и более поздние версии сервисов BLOB-объектов и очередей, а также версия 2014-02-14 и более поздние версии файлового сервиса. Этот формат идентичен тому, который использовался в предыдущих версиях сервисов хранения. Создайте строку CanonicalizedResource в этом формате следующим образом:

Начиная с пустой строки (""), добавьте forward sla sh (/), за которым следует имя учетной записи, которой принадлежит доступ к ресурсу. .

Добавить кодированный путь ресурса URI. Если URI запроса обращается к компоненту ресурса, добавьте соответствующую строку запроса. Строка запроса должна включать знак вопроса и параметр comp (например,? Comp = metadata). Никакие другие параметры не должны быть включены в строку запроса.

Исходя из этого, ваш canonResource должен быть

canonResource <- paste0("/", account, "/myTable()")

Вот полный код, который я использовал:

library(httr)
library(RCurl)
library(digest)

key <- "<account-key>"

    account <- "<account-name>"

    url <- "https://<account-name>.table.core.windows.net/myTable()?$filter=RowKey%20eq%20'1'&$select=Name"

    canonResource <- paste0("/", account, "/myTable()")

    print(canonResource)

    requestdate <- format(Sys.time(),"%a, %d %b %Y %H:%M:%S %Z", tz="GMT")

    print(requestdate)

    signStr <- paste(requestdate, canonResource, sep = "\n") 

    print(signStr)

    auth <- paste0("SharedKeyLite ", account, ":",
                 RCurl::base64(digest::hmac(key = RCurl::base64Decode(key, mode = "raw"),
                                            object = enc2utf8(signStr),
                                            algo = "sha256", raw = TRUE)))

    print(auth)

    header <- httr::add_headers(`x-ms-version` = "2015-12-11 ",
                                    `x-ms-date` = requestdate,  
                                     Authorization = auth,
                                    Accept = "application/json;odata=nometadata",
                                    #`Accept-Charset` = "UTF-8",
                                     DataServiceVersion = "3.0;NetFx",
                                    #Date = requestdate,
                                     MaxDataServiceVersion = "3.0;NetFx")

    print(header)

    httr::GET(url = url, config = header, verbose())
...