From ece2b28e081faad318b5132b9e6cd59dc1873612 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:01:56 +0200 Subject: [PATCH 01/17] feat: add aad token key_type --- R/endpoint.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/endpoint.R b/R/endpoint.R index 7fc9007..91e8c7b 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -52,7 +52,7 @@ #' } #' @rdname cosmos_endpoint #' @export -cosmos_endpoint <- function(host, key, key_type=c("master", "resource"), +cosmos_endpoint <- function(host, key, key_type=c("master", "resource", "aadToken"), api_version=getOption("azure_cosmosdb_api_version")) { obj <- list( From 4005025d39584a3320d968103f3889f69fc3463c Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:02:35 +0200 Subject: [PATCH 02/17] feat: update signing for aad tokens --- R/sign_request.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/sign_request.R b/R/sign_request.R index 96a831a..204138d 100644 --- a/R/sign_request.R +++ b/R/sign_request.R @@ -5,7 +5,7 @@ sign_sha256 <- function(string, key) sign_cosmos_request <- function(key, verb, resource_type, resource_link, date) { - if(key$type == "resource") + if(key$type == "resource" || key$type == "aadToken") return(curl::curl_escape(key$value)) if(inherits(date, "POSIXt")) From 62c1bc34d48e62c6fb31642027120e35fb9853aa Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:11:22 +0200 Subject: [PATCH 03/17] Update DESCRIPTION --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 19ec0c7..f45535d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,4 +1,4 @@ -Package: AzureCosmosR +Package: BAzureCosmosR Title: Interface to the 'Azure Cosmos DB' 'NoSQL' Database Service Version: 1.0.0 Authors@R: c( From 21296a04a3f38c632aa27d42cc8740ad0755a67c Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:06:26 +0200 Subject: [PATCH 04/17] feat: add more cosmos endpoint info --- R/endpoint.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/endpoint.R b/R/endpoint.R index 91e8c7b..b18851d 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -69,6 +69,8 @@ print.cosmos_endpoint <- function(x, ...) { cat("Cosmos DB SQL endpoint\n") cat("Host:", httr::build_url(x$host), "\n") + cat("Key type:", key_type, "\n") + cat("Api version:", api_version) invisible(x) } From efbe053d8473dd33f727b2ea3b86b41b0eaf835d Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:28:01 +0200 Subject: [PATCH 05/17] feat: implement aad auth request signing --- R/sign_request.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/sign_request.R b/R/sign_request.R index 204138d..153b110 100644 --- a/R/sign_request.R +++ b/R/sign_request.R @@ -5,7 +5,10 @@ sign_sha256 <- function(string, key) sign_cosmos_request <- function(key, verb, resource_type, resource_link, date) { - if(key$type == "resource" || key$type == "aadToken") + if(key$type == "aadToken") + return(curl::curl_escape(sprintf("type=%s&ver=1.0&sig=%s", key$type, key$value))) + + if(key$type == "resource") return(curl::curl_escape(key$value)) if(inherits(date, "POSIXt")) @@ -20,6 +23,7 @@ sign_cosmos_request <- function(key, verb, resource_type, resource_link, date) sep="\n" ) sig <- sign_sha256(string_to_sign, key$value) + curl::curl_escape(sprintf("type=%s&ver=1.0&sig=%s", key$type, sig)) } From b20b66560cefae5850e71eb5262ca53cf7533859 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:29:39 +0200 Subject: [PATCH 06/17] build: bump version --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index f45535d..380b132 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: BAzureCosmosR Title: Interface to the 'Azure Cosmos DB' 'NoSQL' Database Service -Version: 1.0.0 +Version: 1.1.0 Authors@R: c( person("Hong", "Ooi", , "hongooi73@gmail.com", role=c("aut", "cre")), person("Andrew", "Liu", role="ctb", comment="Assistance with Cosmos DB"), From 0950cde4732395e63f77fe9290ce6834a2ae9fe6 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:32:02 +0200 Subject: [PATCH 07/17] fix: print of cosmos_endpoint --- R/endpoint.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/endpoint.R b/R/endpoint.R index b18851d..0f91d40 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -69,8 +69,8 @@ print.cosmos_endpoint <- function(x, ...) { cat("Cosmos DB SQL endpoint\n") cat("Host:", httr::build_url(x$host), "\n") - cat("Key type:", key_type, "\n") - cat("Api version:", api_version) + cat("Key type:", x$key_type, "\n") + cat("Api version:", x$api_version) invisible(x) } From 83d7d58c605364147b98f8ed021d691b66ad2e45 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:33:18 +0200 Subject: [PATCH 08/17] fix: --- R/endpoint.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/endpoint.R b/R/endpoint.R index 0f91d40..32f8087 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -69,7 +69,7 @@ print.cosmos_endpoint <- function(x, ...) { cat("Cosmos DB SQL endpoint\n") cat("Host:", httr::build_url(x$host), "\n") - cat("Key type:", x$key_type, "\n") + cat("Key type:", x$key$type, "\n") cat("Api version:", x$api_version) invisible(x) } From c778d5ecb4135053dbf293514ec7a3ca65a15021 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:43:06 +0200 Subject: [PATCH 09/17] fix: more debug --- R/endpoint.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/endpoint.R b/R/endpoint.R index 32f8087..cd1988f 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -67,7 +67,7 @@ cosmos_endpoint <- function(host, key, key_type=c("master", "resource", "aadToke #' @export print.cosmos_endpoint <- function(x, ...) { - cat("Cosmos DB SQL endpoint\n") + cat("The Cosmos DB SQL endpoint is\n") cat("Host:", httr::build_url(x$host), "\n") cat("Key type:", x$key$type, "\n") cat("Api version:", x$api_version) From 88937a8572740d2fa7d4095db2961d5487761c4a Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:47:04 +0200 Subject: [PATCH 10/17] fix: more debug --- R/endpoint.R | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/R/endpoint.R b/R/endpoint.R index cd1988f..0a2f64a 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -131,6 +131,13 @@ do_request <- function(url, key, resource_type, resource_link, headers=list(), b resource_link, now ) + + # Debugging information + cat("HTTP Verb:", http_verb, "\n") + cat("URL:", httr::build_url(url), "\n") + cat("x-ms-date:", headers$`x-ms-date`, "\n") + cat("Authorization:", headers$Authorization, "\n") + response <- tryCatch(httr::VERB(http_verb, url, do.call(httr::add_headers, headers), body=body, encode=encode, ...), error=function(e) e) From 96009986c48d9eaa9608adc9b8db18f676d08aaf Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:24:55 +0200 Subject: [PATCH 11/17] fix: aad key_type --- R/endpoint.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/endpoint.R b/R/endpoint.R index 0a2f64a..edb6d6d 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -52,7 +52,7 @@ #' } #' @rdname cosmos_endpoint #' @export -cosmos_endpoint <- function(host, key, key_type=c("master", "resource", "aadToken"), +cosmos_endpoint <- function(host, key, key_type=c("master", "resource", "aad"), api_version=getOption("azure_cosmosdb_api_version")) { obj <- list( From 0bef218f354e56ea56cd93dfedc5934538233af5 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:29:02 +0200 Subject: [PATCH 12/17] fix: aad request sign --- R/sign_request.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/sign_request.R b/R/sign_request.R index 153b110..0997a86 100644 --- a/R/sign_request.R +++ b/R/sign_request.R @@ -5,7 +5,7 @@ sign_sha256 <- function(string, key) sign_cosmos_request <- function(key, verb, resource_type, resource_link, date) { - if(key$type == "aadToken") + if(key$type == "aad") return(curl::curl_escape(sprintf("type=%s&ver=1.0&sig=%s", key$type, key$value))) if(key$type == "resource") From ca9ad11cd2b8669867a69cd80fb3bebc976b03c6 Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:45:23 +0200 Subject: [PATCH 13/17] build: rename package, add author --- DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 380b132..7205be3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,8 @@ -Package: BAzureCosmosR +Package: AzureCosmosR Title: Interface to the 'Azure Cosmos DB' 'NoSQL' Database Service Version: 1.1.0 Authors@R: c( + person("Nicolae", "Cudlenco", , "cudlenco.n@buchi.com", role=c("author", "contributor")), person("Hong", "Ooi", , "hongooi73@gmail.com", role=c("aut", "cre")), person("Andrew", "Liu", role="ctb", comment="Assistance with Cosmos DB"), person("Microsoft", role="cph") From 2b01f454fb9c74a09ee0fff31c20a772b30b875e Mon Sep 17 00:00:00 2001 From: Nicolae Cudlenco <146981376+ncudlenco@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:48:04 +0200 Subject: [PATCH 14/17] docs: update cosmos_endpoint arguments docs, remove extra debugging info --- R/endpoint.R | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/R/endpoint.R b/R/endpoint.R index edb6d6d..08e0fb0 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -1,8 +1,8 @@ #' Client endpoint for Azure Cosmos DB core API #' #' @param host For `cosmos_endpoint`, the host URL for the endpoint. Typically of the form `https://{account-name}.documents.azure.com:443/` (note the port number). -#' @param key For `cosmos_endpoint`, a string containing the password for the endpoint. This can be either a master key or a resource token. -#' @param key_type For `cosmos_endpoint`, the type of the key, either "master" or "resource". +#' @param key For `cosmos_endpoint`, a string containing the password for the endpoint. This can be either a master key, a resource token, or an AAD token. +#' @param key_type For `cosmos_endpoint`, the type of the key, either "master" or "resource" or "aad". #' @param api_version For `cosmos_endpoint`, the API version to use. #' @param endpoint For `call_cosmos_endpoint`, a Cosmos DB endpoint object, as returned by `cosmos_endpoint`. #' @param path For `call_cosmos_endpoint`, the path in the URL for the endpoint call. @@ -131,13 +131,7 @@ do_request <- function(url, key, resource_type, resource_link, headers=list(), b resource_link, now ) - - # Debugging information - cat("HTTP Verb:", http_verb, "\n") - cat("URL:", httr::build_url(url), "\n") - cat("x-ms-date:", headers$`x-ms-date`, "\n") - cat("Authorization:", headers$Authorization, "\n") - + response <- tryCatch(httr::VERB(http_verb, url, do.call(httr::add_headers, headers), body=body, encode=encode, ...), error=function(e) e) From 6da8dda11fb0cce4c4358b261643948c7266c9c1 Mon Sep 17 00:00:00 2001 From: Cudlenco Nicolae Date: Tue, 8 Oct 2024 13:57:55 +0200 Subject: [PATCH 15/17] docs: update docs for cosmos_endpoint --- man/cosmos_endpoint.Rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/cosmos_endpoint.Rd b/man/cosmos_endpoint.Rd index 4289e9d..ee66c3e 100644 --- a/man/cosmos_endpoint.Rd +++ b/man/cosmos_endpoint.Rd @@ -11,7 +11,7 @@ cosmos_endpoint( host, key, - key_type = c("master", "resource"), + key_type = c("master", "resource", "aad"), api_version = getOption("azure_cosmosdb_api_version") ) @@ -51,9 +51,9 @@ process_cosmos_response(response, ...) \arguments{ \item{host}{For \code{cosmos_endpoint}, the host URL for the endpoint. Typically of the form \verb{https://\{account-name\}.documents.azure.com:443/} (note the port number).} -\item{key}{For \code{cosmos_endpoint}, a string containing the password for the endpoint. This can be either a master key or a resource token.} +\item{key}{For \code{cosmos_endpoint}, a string containing the password for the endpoint. This can be either a master key, a resource token, or an AAD token.} -\item{key_type}{For \code{cosmos_endpoint}, the type of the key, either "master" or "resource".} +\item{key_type}{For \code{cosmos_endpoint}, the type of the key, either "master" or "resource" or "aad".} \item{api_version}{For \code{cosmos_endpoint}, the API version to use.} From 22b2659e242edb93fcf62decda05a25aeacbde0b Mon Sep 17 00:00:00 2001 From: Cudlenco Nicolae Date: Tue, 8 Oct 2024 15:05:40 +0200 Subject: [PATCH 16/17] fix: print.cosmos_endpoint formatting --- R/endpoint.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/endpoint.R b/R/endpoint.R index 08e0fb0..63b9f6a 100644 --- a/R/endpoint.R +++ b/R/endpoint.R @@ -67,10 +67,10 @@ cosmos_endpoint <- function(host, key, key_type=c("master", "resource", "aad"), #' @export print.cosmos_endpoint <- function(x, ...) { - cat("The Cosmos DB SQL endpoint is\n") + cat("Cosmos DB SQL endpoint\n") cat("Host:", httr::build_url(x$host), "\n") cat("Key type:", x$key$type, "\n") - cat("Api version:", x$api_version) + cat("Api version:", x$api_version, "\n") invisible(x) } From 55d223bf72c476e10e1979ea72a7084c047b2561 Mon Sep 17 00:00:00 2001 From: Cudlenco Nicolae Date: Tue, 8 Oct 2024 15:14:58 +0200 Subject: [PATCH 17/17] docs: add example for AAD based authentication --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 9efc19f..0ea2017 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,27 @@ The primary repo for this package is at https://github.com/Azure/AzureCosmosR; p ## SQL interface +### AAD authentication + +According to the latest security guides for Azure Cosmos DB, role-based access control is suggested in favor over key-based and resource owner password credentials-based authentication: https://learn.microsoft.com/en-us/azure/cosmos-db/table/security/. + +Below, we provide an example of how AAD token-based authentication can be done. +```r +library(AzureAuth) +library(AzureCosmosR) + +token <- AzureAuth::get_managed_token("https://cosmos.azure.com") +endpoint <- AzureCosmosR::cosmos_endpoint("https://myaccount.documents.azure.com:443/", key = token, key_type = "aad") + +list_cosmos_databases(endpoint) + +db <- get_cosmos_database(endpoint, "mydatabase") + +#... other operations +``` + +### Key based authentication + AzureCosmosR provides a suite of methods to work with databases, containers (tables) and documents (rows) using the SQL API. ```r