0

I am working on Azure Databricks in an R notebook and in order to write meta data generated by my R code, I try to connect/read/write to/from/to Azure Table Storage Service.

Here I learned how to access and read a table (named "myTable), which with some modifications works fine. Here is what I did:

 key <- <myKey>
 account <- <myAccount>

 url <- paste0("https://", account, ".table.core.windows.net/myTable()")
 requestdate <- format(Sys.time(),"%a, %d %b %Y %H:%M:%S %Z", tz="GMT")
 #content_length <- 0

 signature_string <- paste0("GET", "\n",            # HTTP Verb
                       "\n",                   # Content-MD5
                       "text/plain", "\n",     # Content-Type
                       requestdate, "\n",                   # Date
                       # Here comes the Canonicalized Resource
                       "/",account, "/","myTable()" )

 header <- add_headers(Authorization=paste0("SharedKey ",account,":", 
                                            RCurl::base64(digest::hmac(key = 
                                                                         RCurl::base64Decode(key, mode = "raw"),
                                                                       object = enc2utf8(signature_string),
                                                                       algo = "sha256", raw = TRUE))),
                       `x-ms-date`= requestdate,
                       `x-ms-version`= "2015-02-21",
                       `Content-Type`="text/plain")

 GET(url, config = header, verbose()) -> res

Now, I would like to create another table as well as to add new entities to existing tables. I adopted above approach and modified it to

 url <- paste0("https://", account, ".table.core.windows.net/TABLES")
 requestdate <- format(Sys.time(),"%a, %d %b %Y %H:%M:%S %Z", tz="GMT")

 signature_string <- paste0("POST", "\n",            # HTTP Verb
                       "\n",                   # Content-Encoding  
                       "\n",                   # Content-Language
                       content_length, "\n",   # Content-Length
                       "\n",                   # Content-MD5
                       "application/json", "\n",     # Content-Type
                       "\n",                   # Date
                       "\n",                   # If-Modified-Since
                       "\n",                   # If-Match  
                       "\n",                   # If-None-Match
                       "\n",                   # If-Unmodified-Since
                       "\n",                   # Range
                       # Here comes the Canonicalized Headers
                       # "x-ms-blob-type:BlockBlob","\n",
                       "x-ms-date:",requestdate,"\n",
                       #"x-ms-version:2015-02-21","\n",
                       # Here comes the Canonicalized Resource
                       "/",account, "/","TABLES")

 header <- add_headers(Authorization=paste0("SharedKey ",account,":", 
                                            RCurl::base64(digest::hmac(key = 
                                                                         RCurl::base64Decode(key, mode = "raw"),
                                                                       object = enc2utf8(signature_string),
                                                                       algo = "sha256", raw = TRUE))),
                       `x-ms-date`= requestdate,
                      # `x-ms-version`= "2015-02-21",
                       `Content-Type`="application/json",
                       `Content-Length`=100)

 body <- paste0("{", "\n",
                       "'TableName':'newTable'",  "\n",                          
           "}")

 POST(url = url, config = header, body = body, encode = "json", handle = NULL) -> res

Running that gives me status 403. The exact message is:

  Response [https://myAccount.table.core.windows.net/TABLES]
  Date: 2020-01-31 18:47
  Status: 403
  Content-Type: application/json
  Size: 437 B

 AuthenticationFailed Server failed to authenticate the request. Make s... RequestId:9bc35a5f-c002-1666-d88043000000 Time:2020-01-31T18:47:36.6598228Z

I played around with the inputs to the signature_string for hours without success. Also I tried different body definitions as e.g.

 request_body <- data.frame(TableName = "access")
 body <- jsonlite::toJSON(request_body, auto_unbox = T)

I am not sure about the following inputs: Content-Length, Content-Type, x-ms-version, request-body and whether I miss anything else.

Could someone give me advise how to write a correct header to create new tables and to add new entities. If there is a more elegant way, this would be also highly appreciated.

K.O.T.
  • 111
  • 10
  • Please see `Table service (Shared Key Authorization)` section here: https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key and create your signatureString accordingly. – Gaurav Mantri Feb 01 '20 at 07:47
  • I noticed that you duplicated `x-ms-date` and missed `x-ms-version` in the header. – Tony Ju Feb 03 '20 at 03:16
  • I switched to SharedKeyLite authentication, which makes things way easier. With that I managed to create, deleted, tables. However, what is still failing all the time is to query tables with select and filter statements. Any idea/suggestion on that? – K.O.T. Feb 07 '20 at 17:24

0 Answers0