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.