зеркало из https://github.com/Azure/AzureRMR.git
Cli auth (#2)
* changes to enable auth with CLI app id * api for persistent logins * dev version number * typo * add documentation * update docs to use get_az_login * update mds * allow new login flow to use svc principal * fix delete_az_login * more fixups * fix list_az_logins * update news * update intro * add badges * az_login -> azure_login * doc fix * cleanup * document * document fixup * update tests * rationalise auth arguments: resource_host first arg, auth_type default based on pwd * fix vignette img links
This commit is contained in:
Родитель
9c90892421
Коммит
5ab610fd8e
|
@ -3,6 +3,8 @@ Title: Interface to 'Azure Resource Manager'
|
|||
Version: 1.0.0.9000
|
||||
Authors@R: c(
|
||||
person("Hong", "Ooi", , "hongooi@microsoft.com", role = c("aut", "cre")),
|
||||
person("Scott", "Holden", , role = "ctb", comment = "Advice on AAD authentication"),
|
||||
person("Chris", "Stone", , role = "ctb", comment = "Advice on AAD authentication"),
|
||||
person("Microsoft", role="cph")
|
||||
)
|
||||
Description: A lightweight but powerful R interface to the 'Azure Resource Manager' REST API. The package exposes classes and methods for 'OAuth' authentication and working with subscriptions and resource groups. It also provides functionality for creating and deleting 'Azure' resources and deploying templates. While 'AzureRMR' can be used to manage any 'Azure' service, it can also be extended by other packages to provide extra functionality for specific services.
|
||||
|
@ -16,9 +18,11 @@ Imports:
|
|||
utils,
|
||||
httr (>= 1.3),
|
||||
jsonlite,
|
||||
R6
|
||||
R6,
|
||||
rappdirs
|
||||
Suggests:
|
||||
knitr,
|
||||
testthat
|
||||
testthat,
|
||||
httpuv
|
||||
Roxygen: list(markdown=TRUE)
|
||||
RoxygenNote: 6.1.0.9000
|
||||
|
|
|
@ -8,9 +8,12 @@ export(az_subscription)
|
|||
export(az_template)
|
||||
export(call_azure_rm)
|
||||
export(call_azure_url)
|
||||
export(create_azure_login)
|
||||
export(delete_azure_login)
|
||||
export(format_auth_header)
|
||||
export(format_public_fields)
|
||||
export(format_public_methods)
|
||||
export(get_azure_login)
|
||||
export(get_azure_token)
|
||||
export(is_empty)
|
||||
export(is_resource)
|
||||
|
@ -18,5 +21,7 @@ export(is_resource_group)
|
|||
export(is_subscription)
|
||||
export(is_template)
|
||||
export(is_url)
|
||||
export(list_azure_logins)
|
||||
export(named_list)
|
||||
export(refresh_azure_logins)
|
||||
importFrom(utils,modifyList)
|
||||
|
|
6
NEWS.md
6
NEWS.md
|
@ -1,5 +1,11 @@
|
|||
# AzureRMR 1.0.0.9000
|
||||
|
||||
## Significant interface changes
|
||||
|
||||
* New `create_azure_login`, `get_azure_login` and `delete_azure_login` functions to handle ARM authentication. These will persist the login object across sessions, removing the need to re-authenticate each time. While directly calling `az_rm$new()` will still work, it's recommended to use `create_azure_login` and `get_azure_login` going forward.
|
||||
|
||||
## Other changes
|
||||
|
||||
* Don't print empty fields for ARM objects.
|
||||
* Add optional `etag` field to resource object definition.
|
||||
* Fix `AzureToken` object to never have a `NULL` password field (important to allow devicecode refreshing).
|
||||
|
|
|
@ -5,6 +5,11 @@ NULL
|
|||
{
|
||||
azure_api_version="2018-05-01"
|
||||
options(azure_api_version=azure_api_version)
|
||||
|
||||
config_dir <- config_dir()
|
||||
if(!dir.exists(config_dir))
|
||||
dir.create(config_dir, recursive=TRUE)
|
||||
|
||||
invisible(NULL)
|
||||
}
|
||||
|
||||
|
|
|
@ -115,12 +115,12 @@ private=list(
|
|||
#'
|
||||
#' This extends the OAuth functionality in httr to allow for device code authentication.
|
||||
#'
|
||||
#' @param aad_host URL for your Azure Active Directory host. For the public Azure cloud, this is `https://login.microsoftonline.com/`.
|
||||
#' @param resource_host URL for your resource host. For Resource Manager in the public Azure cloud, this is `https://management.azure.com/`.
|
||||
#' @param tenant Your tenant ID.
|
||||
#' @param app Your client/app ID which you registered in AAD.
|
||||
#' @param auth_type The authentication type, either `"client_credentials"` or `"device_code"`.
|
||||
#' @param password Your password. Required for `auth_type == "client_credentials"`, ignored for `auth_type == "device_code"`.
|
||||
#' @param resource_host URL for your resource host. For Resource Manager in the public Azure cloud, this is `https://management.azure.com/`.
|
||||
#' @param auth_type The authentication type, either `"client_credentials"` or `"device_code"`. Defaults to the latter if no password is provided, otherwise the former.
|
||||
#' @param aad_host URL for your Azure Active Directory host. For the public Azure cloud, this is `https://login.microsoftonline.com/`.
|
||||
#'
|
||||
#' @details
|
||||
#' This function does much the same thing as [httr::oauth2.0_token()], but with support for device authentication and with unnecessary options removed. Device authentication removes the need to save a password on your machine. Instead, the server provides you with a code, along with a URL. You then visit the URL in your browser and enter the code, which completes the authentication process.
|
||||
|
@ -142,10 +142,12 @@ private=list(
|
|||
#'
|
||||
#' }
|
||||
#' @export
|
||||
get_azure_token=function(aad_host, tenant, app, auth_type=c("client_credentials", "device_code"),
|
||||
password, resource_host)
|
||||
get_azure_token=function(resource_host, tenant, app, password=NULL,
|
||||
auth_type=if(is.null(password)) "device_code" else "client_credentials",
|
||||
aad_host="https://login.microsoftonline.com/")
|
||||
{
|
||||
auth_type <- match.arg(auth_type)
|
||||
tenant <- normalize_tenant(tenant)
|
||||
|
||||
base_url <- construct_path(aad_host, tenant)
|
||||
if(auth_type == "client_credentials")
|
||||
auth_with_creds(base_url, app, password, resource_host)
|
||||
|
|
15
R/az_auth.R
15
R/az_auth.R
|
@ -11,18 +11,20 @@
|
|||
#' - `get_subscription(id)`: Returns an object representing a subscription.
|
||||
#'
|
||||
#' @section Authentication:
|
||||
#' To authenticate with ARM, provide the following arguments to the `new` method:
|
||||
#' The best way to authenticate with ARM is probably via the [create_azure_login] and [get_azure_login] functions. With these, you only have to authenticate once, after which your credentials are saved and reused for subsequent sessions.
|
||||
#'
|
||||
#' To authenticate with the `az_rm` class directly, provide the following arguments to the `new` method:
|
||||
#' - `tenant`: Your tenant ID.
|
||||
#' - `app`: Your client/app ID which you registered in Azure Active Directory.
|
||||
#' - `auth_type`: Either `"client_credentials"` (the default) or `"device_code"`.
|
||||
#' - `password`: if `auth_type == "client_credentials"`, your password.
|
||||
#' - `auth_type`: Either `"client_credentials"` or `"device_code"`. Defaults to the latter if no password is provided, otherwise the former.
|
||||
#' - `host`: your ARM host. Defaults to `https://management.azure.com/`. Change this if you are using a government or private cloud.
|
||||
#' - `aad_host`: Azure Active Directory host for authentication. Defaults to `https://login.microsoftonline.com/`. Change this if you are using a government or private cloud.
|
||||
#' - `config_file`: Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI `az ad sp create-for-rbac` command.
|
||||
#' - `token`: Optionally, an OAuth 2.0 token, of class [AzureToken]. This allows you to reuse the authentication details for an existing session. If supplied, all other arguments will be ignored.
|
||||
#'
|
||||
#' @seealso
|
||||
#' [get_azure_token], [AzureToken],
|
||||
#' [create_azure_login], [get_azure_token], [AzureToken],
|
||||
#' [Azure Resource Manager overview](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview),
|
||||
#' [REST API reference](https://docs.microsoft.com/en-us/rest/api/resources/)
|
||||
#'
|
||||
|
@ -55,7 +57,8 @@ public=list(
|
|||
token=NULL,
|
||||
|
||||
# authenticate and get subscriptions
|
||||
initialize=function(tenant, app, auth_type="client_credentials", password,
|
||||
initialize=function(tenant, app, password=NULL,
|
||||
auth_type=if(is.null(password)) "device_code" else "client_credentials",
|
||||
host="https://management.azure.com/", aad_host="https://login.microsoftonline.com/",
|
||||
config_file=NULL, token=NULL)
|
||||
{
|
||||
|
@ -78,8 +81,8 @@ public=list(
|
|||
if(!is.null(conf$aad_host)) aad_host <- conf$aad_host
|
||||
}
|
||||
self$host <- host
|
||||
self$tenant <- tenant
|
||||
self$token <- get_azure_token(aad_host, tenant, app, auth_type, password, host)
|
||||
self$tenant <- normalize_tenant(tenant)
|
||||
self$token <- get_azure_token(self$host, self$tenant, app, password, auth_type, aad_host)
|
||||
NULL
|
||||
},
|
||||
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
config_dir <- function()
|
||||
{
|
||||
rappdirs::user_config_dir(appname="AzureRMR", appauthor="AzureR", roaming=FALSE)
|
||||
}
|
||||
|
||||
|
||||
#' Functions to login to Azure Resource Manager
|
||||
#'
|
||||
#' @param tenant The Azure Active Directory tenant for which to obtain a login client. Can be a name ("myaadtenant"), a fully qualified domain name ("myaadtenant.onmicrosoft.com" or "mycompanyname.com"), or a GUID.
|
||||
#' @param app The app ID to authenticate with.
|
||||
#' @param password If `auth_type == "client_credentials"`, your password.
|
||||
#' @param auth_type The type of authentication to use, either "device_code" or "client_credentials". Defaults to the latter if no password is provided, otherwise the former.
|
||||
#' @param host Your ARM host. Defaults to `https://management.azure.com/`. Change this if you are using a government or private cloud.
|
||||
#' @param aad_host Azure Active Directory host for authentication. Defaults to `https://login.microsoftonline.com/`. Change this if you are using a government or private cloud.
|
||||
#' @param config_file Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI `az ad sp create-for-rbac` command.
|
||||
#' @param refresh For `get_azure_login`, whether to refresh the authentication token on loading the client.
|
||||
#' @param confirm For `delete_azure_login`, whether to ask for confirmation before deleting.
|
||||
#' @param ... Other arguments passed to `az_rm$new()`.
|
||||
#'
|
||||
#' @details
|
||||
#' These functions allow you to authenticate with Azure Resource Manager (ARM).
|
||||
#' - `create_azure_login` creates a login client, using the supplied credentials. You only have to create a login client once per tenant; the resulting object is saved on your machine and reused automatically in subsequent R sessions.
|
||||
#' - `get_azure_login` will load a previously saved ARM client object for the given tenant. If this is the first time you are logging in for this tenant, the client object is created via `create_login_client`.
|
||||
#' - `delete_azure_login` deletes the client object for the given tenant from your machine. Note that this doesn't invalidate any client you may be using in your R session.
|
||||
#' - `list_azure_logins` lists client objects that have been previously saved.
|
||||
#' - `refresh_azure_logins` refreshes all client objects existing on your machine.
|
||||
#'
|
||||
#' `create_azure_login` is roughly equivalent to the Azure CLI command `az login` with no arguments.
|
||||
#'
|
||||
#' @return
|
||||
#' For `create_azure_login` and `get_azure_login`, an object of class `az_rm`, representing the ARM login client. For `list_azure_logins`, a list of such objects.
|
||||
#'
|
||||
#' @seealso
|
||||
#' [az_rm], [Azure CLI documentation](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest)
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#'
|
||||
#' # this will create a Resource Manager client for the AAD tenant 'microsoft.onmicrosoft.com'
|
||||
#' # only has to be run once per tenant
|
||||
#' az <- create_azure_login("microsoft", app="{app_id}", password="{password}")
|
||||
#'
|
||||
#' # you can also login using credentials in a json file
|
||||
# az <- create_azure_login(config_file="~/creds.json")
|
||||
#'
|
||||
#' # in subsequent sessions, you can retrieve the client without re-authenticating:
|
||||
#' # authentication details will automatically be refreshed
|
||||
#' az <- get_azure_login("microsoft")
|
||||
#'
|
||||
#' # refresh (renew) authentication details for clients for all tenants
|
||||
#' refresh_azure_logins()
|
||||
#'
|
||||
#' }
|
||||
#' @rdname azure_login
|
||||
#' @export
|
||||
create_azure_login <- function(tenant, app, password=NULL,
|
||||
auth_type=if(is.null(password)) "device_code" else "client_credentials",
|
||||
host="https://management.azure.com/", aad_host="https://login.microsoftonline.com/",
|
||||
config_file=NULL, ...)
|
||||
{
|
||||
if(!is.null(config_file))
|
||||
{
|
||||
conf <- jsonlite::fromJSON(config_file)
|
||||
if(!is.null(conf$tenant)) tenant <- conf$tenant
|
||||
if(!is.null(conf$app)) app <- conf$app
|
||||
if(!is.null(conf$auth_type)) auth_type <- conf$auth_type
|
||||
if(!is.null(conf$password)) password <- conf$password
|
||||
if(!is.null(conf$host)) host <- conf$host
|
||||
if(!is.null(conf$aad_host)) aad_host <- conf$aad_host
|
||||
}
|
||||
|
||||
tenant <- normalize_tenant(tenant)
|
||||
message("Creating Azure Active Directory login for tenant '", tenant, "'")
|
||||
client <- az_rm$new(tenant, app, password, auth_type, host, aad_host, config_file, ...)
|
||||
save_client(client, tenant)
|
||||
client
|
||||
}
|
||||
|
||||
|
||||
#' @rdname azure_login
|
||||
#' @export
|
||||
get_azure_login <- function(tenant, ..., refresh=TRUE)
|
||||
{
|
||||
tenant <- normalize_tenant(tenant)
|
||||
|
||||
login_exists <- file.exists(file.path(config_dir(), tenant))
|
||||
if(!login_exists)
|
||||
return(create_azure_login(tenant, ...))
|
||||
|
||||
message("Loading Azure Active Directory login for tenant '", tenant, "'")
|
||||
client <- readRDS(file.path(config_dir(), tenant))
|
||||
if(refresh)
|
||||
{
|
||||
# refresh and save
|
||||
client$token$refresh()
|
||||
save_client(client, tenant)
|
||||
}
|
||||
client
|
||||
}
|
||||
|
||||
|
||||
#' @rdname azure_login
|
||||
#' @export
|
||||
delete_azure_login <- function(tenant, confirm=TRUE)
|
||||
{
|
||||
tenant <- normalize_tenant(tenant)
|
||||
|
||||
if(confirm && interactive())
|
||||
{
|
||||
yn <- readline(
|
||||
paste0("Do you really want to delete the Azure Active Directory login for tenant ", tenant, "? (y/N) "))
|
||||
if(tolower(substr(yn, 1, 1)) != "y")
|
||||
return(invisible(NULL))
|
||||
}
|
||||
|
||||
file.remove(file.path(config_dir(), tenant))
|
||||
invisible(NULL)
|
||||
}
|
||||
|
||||
|
||||
#' @rdname azure_login
|
||||
#' @export
|
||||
list_azure_logins <- function()
|
||||
{
|
||||
tenants <- dir(config_dir(), full.names=TRUE)
|
||||
lst <- lapply(tenants, readRDS)
|
||||
names(lst) <- basename(tenants)
|
||||
lst
|
||||
}
|
||||
|
||||
|
||||
#' @rdname azure_login
|
||||
#' @export
|
||||
refresh_azure_logins <- function()
|
||||
{
|
||||
refresh_and_save <- function(tenant)
|
||||
{
|
||||
client <- readRDS(tenant)
|
||||
client$token$refresh()
|
||||
save_client(client, basename(tenant))
|
||||
}
|
||||
|
||||
lapply(dir(config_dir(), full.names=TRUE), refresh_and_save)
|
||||
invisible(NULL)
|
||||
}
|
||||
|
||||
|
||||
save_client <- function(client, tenant)
|
||||
{
|
||||
tenant <- normalize_tenant(tenant)
|
||||
|
||||
saveRDS(client, file=file.path(config_dir(), tenant))
|
||||
invisible(client)
|
||||
}
|
||||
|
||||
|
||||
normalize_tenant <- function(tenant)
|
||||
{
|
||||
# see https://docs.microsoft.com/en-us/dotnet/api/system.guid.parse
|
||||
# for possible input formats for GUIDs
|
||||
is_guid <- function(x)
|
||||
{
|
||||
grepl("^[0-9a-f]{32}$", x) ||
|
||||
grepl("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", x) ||
|
||||
grepl("^\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}$", x) ||
|
||||
grepl("^\\([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\)$", x)
|
||||
}
|
||||
|
||||
# check if supplied a guid; if not, check if a fqdn; if not, append '.onmicrosoft.com'
|
||||
if(is_guid(tenant))
|
||||
return(tenant)
|
||||
|
||||
if(!grepl("\\.", tenant))
|
||||
tenant <- paste(tenant, "onmicrosoft.com", sep=".")
|
||||
tenant
|
||||
}
|
|
@ -55,8 +55,7 @@
|
|||
#' \dontrun{
|
||||
#'
|
||||
#' # recommended way to retrieve a resource group object
|
||||
#' rg <- az_rm$
|
||||
#' new(tenant="myaadtenant.onmicrosoft.com", app="app_id", password="password")$
|
||||
#' rg <- get_azure_login("myaadtenant")$
|
||||
#' get_subscription("subscription_id")$
|
||||
#' get_resource_group("rgname")
|
||||
#'
|
||||
|
|
|
@ -26,8 +26,7 @@
|
|||
#' \dontrun{
|
||||
#'
|
||||
#' # recommended way to retrieve a subscription object
|
||||
#' sub <- az_rm$
|
||||
#' new(tenant="myaadtenant.onmicrosoft.com", app="app_id", password="password")$
|
||||
#' sub <- get_azure_login("myaadtenant")$
|
||||
#' get_subscription("subscription_id")
|
||||
#'
|
||||
#' # retrieve list of resource group objects under this subscription
|
||||
|
|
12
README.md
12
README.md
|
@ -8,6 +8,7 @@ AzureRMR is a package for interacting with Azure Resource Manager: authenticate,
|
|||
|
||||
You can install the development version from GitHub, via `devtools::install_github("cloudyr/AzureRMR")`.
|
||||
|
||||
|
||||
## Before you begin
|
||||
|
||||
To use AzureRMR, you must create and register a service principal with Azure Active Directory. This is a one-time task, and the easiest method is to use the Azure cloud shell.
|
||||
|
@ -26,12 +27,21 @@ To use AzureRMR, you must create and register a service principal with Azure Act
|
|||
|
||||
If you want to allow access at something other than subscription level, you can use the `--scopes` argument in place of `--subscription`. For example, to restrict AzureRMR to only the "AnalyticsRG" resource group: `az ad sp create-for-rbac --scopes /subscriptions/{your-subscription-ID}/resourceGroups/AnalyticsRG`.
|
||||
|
||||
|
||||
## Authentication
|
||||
|
||||
Under the hood, AzureRMR uses a similar authentication process to the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest). The first time you authenticate with a given Azure Active Directory tenant, you call `create_azure_login()` and supply your tenant, app ID and password. The resulting Resource Manager client object is saved on your machine, and can be retrieved in subsequent R sessions with `get_azure_login("{tenant}")`. AzureRMR will automatically refresh your credentials so you don't have to re-authenticate.
|
||||
|
||||
|
||||
## Sample workflow
|
||||
|
||||
```r
|
||||
library(AzureRMR)
|
||||
|
||||
az <- az_rm$new(tenant="{tenant_id}", app="{app_id}", password="{password}")
|
||||
# authenticate with Azure AD:
|
||||
# - on first login to this client, call create_azure_login(...)
|
||||
# - on subsequent logins, call get_azure_login("myaadtenant")
|
||||
az <- create_azure_login("myaadtenant.onmicrosoft.com", app="app_id", password="password")
|
||||
|
||||
# get a subscription and resource group
|
||||
sub <- az$get_subscription("{subscription_id}")
|
||||
|
|
|
@ -73,8 +73,7 @@ To create/deploy a new resource, specify any extra parameters that the provider
|
|||
\dontrun{
|
||||
|
||||
# recommended way to retrieve a resource group object
|
||||
rg <- az_rm$
|
||||
new(tenant="myaadtenant.onmicrosoft.com", app="app_id", password="password")$
|
||||
rg <- get_azure_login("myaadtenant")$
|
||||
get_subscription("subscription_id")$
|
||||
get_resource_group("rgname")
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@ Base class for interacting with Azure Resource Manager.
|
|||
|
||||
\section{Authentication}{
|
||||
|
||||
To authenticate with ARM, provide the following arguments to the \code{new} method:
|
||||
The best way to authenticate with ARM is probably via the \link{create_azure_login} and \link{get_azure_login} functions. With these, you only have to authenticate once, after which your credentials are saved and reused for subsequent sessions.
|
||||
|
||||
To authenticate with the \code{az_rm} class directly, provide the following arguments to the \code{new} method:
|
||||
\itemize{
|
||||
\item \code{tenant}: Your tenant ID.
|
||||
\item \code{app}: Your client/app ID which you registered in Azure Active Directory.
|
||||
\item \code{auth_type}: Either \code{"client_credentials"} (the default) or \code{"device_code"}.
|
||||
\item \code{password}: if \code{auth_type == "client_credentials"}, your password.
|
||||
\item \code{auth_type}: Either \code{"client_credentials"} or \code{"device_code"}. Defaults to the latter if no password is provided, otherwise the former.
|
||||
\item \code{host}: your ARM host. Defaults to \code{https://management.azure.com/}. Change this if you are using a government or private cloud.
|
||||
\item \code{aad_host}: Azure Active Directory host for authentication. Defaults to \code{https://login.microsoftonline.com/}. Change this if you are using a government or private cloud.
|
||||
\item \code{config_file}: Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI \code{az ad sp create-for-rbac} command.
|
||||
|
@ -56,7 +58,7 @@ az$get_subscription("subscription_id")
|
|||
}
|
||||
}
|
||||
\seealso{
|
||||
\link{get_azure_token}, \link{AzureToken},
|
||||
\link{create_azure_login}, \link{get_azure_token}, \link{AzureToken},
|
||||
\href{https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview}{Azure Resource Manager overview},
|
||||
\href{https://docs.microsoft.com/en-us/rest/api/resources/}{REST API reference}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ Generally, the easiest way to create a subscription object is via the \code{get_
|
|||
\dontrun{
|
||||
|
||||
# recommended way to retrieve a subscription object
|
||||
sub <- az_rm$
|
||||
new(tenant="myaadtenant.onmicrosoft.com", app="app_id", password="password")$
|
||||
sub <- get_azure_login("myaadtenant")$
|
||||
get_subscription("subscription_id")
|
||||
|
||||
# retrieve list of resource group objects under this subscription
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/az_login.R
|
||||
\name{create_azure_login}
|
||||
\alias{create_azure_login}
|
||||
\alias{get_azure_login}
|
||||
\alias{delete_azure_login}
|
||||
\alias{list_azure_logins}
|
||||
\alias{refresh_azure_logins}
|
||||
\title{Functions to login to Azure Resource Manager}
|
||||
\usage{
|
||||
create_azure_login(tenant, app, password = NULL, auth_type = if
|
||||
(is.null(password)) "device_code" else "client_credentials",
|
||||
host = "https://management.azure.com/",
|
||||
aad_host = "https://login.microsoftonline.com/", config_file = NULL,
|
||||
...)
|
||||
|
||||
get_azure_login(tenant, ..., refresh = TRUE)
|
||||
|
||||
delete_azure_login(tenant, confirm = TRUE)
|
||||
|
||||
list_azure_logins()
|
||||
|
||||
refresh_azure_logins()
|
||||
}
|
||||
\arguments{
|
||||
\item{tenant}{The Azure Active Directory tenant for which to obtain a login client. Can be a name ("myaadtenant"), a fully qualified domain name ("myaadtenant.onmicrosoft.com" or "mycompanyname.com"), or a GUID.}
|
||||
|
||||
\item{app}{The app ID to authenticate with.}
|
||||
|
||||
\item{password}{If \code{auth_type == "client_credentials"}, your password.}
|
||||
|
||||
\item{auth_type}{The type of authentication to use, either "device_code" or "client_credentials". Defaults to the latter if no password is provided, otherwise the former.}
|
||||
|
||||
\item{host}{Your ARM host. Defaults to \code{https://management.azure.com/}. Change this if you are using a government or private cloud.}
|
||||
|
||||
\item{aad_host}{Azure Active Directory host for authentication. Defaults to \code{https://login.microsoftonline.com/}. Change this if you are using a government or private cloud.}
|
||||
|
||||
\item{config_file}{Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI \code{az ad sp create-for-rbac} command.}
|
||||
|
||||
\item{...}{Other arguments passed to \code{az_rm$new()}.}
|
||||
|
||||
\item{refresh}{For \code{get_azure_login}, whether to refresh the authentication token on loading the client.}
|
||||
|
||||
\item{confirm}{For \code{delete_azure_login}, whether to ask for confirmation before deleting.}
|
||||
}
|
||||
\value{
|
||||
For \code{create_azure_login} and \code{get_azure_login}, an object of class \code{az_rm}, representing the ARM login client. For \code{list_azure_logins}, a list of such objects.
|
||||
}
|
||||
\description{
|
||||
Functions to login to Azure Resource Manager
|
||||
}
|
||||
\details{
|
||||
These functions allow you to authenticate with Azure Resource Manager (ARM).
|
||||
\itemize{
|
||||
\item \code{create_azure_login} creates a login client, using the supplied credentials. You only have to create a login client once per tenant; the resulting object is saved on your machine and reused automatically in subsequent R sessions.
|
||||
\item \code{get_azure_login} will load a previously saved ARM client object for the given tenant. If this is the first time you are logging in for this tenant, the client object is created via \code{create_login_client}.
|
||||
\item \code{delete_azure_login} deletes the client object for the given tenant from your machine. Note that this doesn't invalidate any client you may be using in your R session.
|
||||
\item \code{list_azure_logins} lists client objects that have been previously saved.
|
||||
\item \code{refresh_azure_logins} refreshes all client objects existing on your machine.
|
||||
}
|
||||
|
||||
\code{create_azure_login} is roughly equivalent to the Azure CLI command \code{az login} with no arguments.
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
|
||||
# this will create a Resource Manager client for the AAD tenant 'microsoft.onmicrosoft.com'
|
||||
# only has to be run once per tenant
|
||||
az <- create_azure_login("microsoft", app="{app_id}", password="{password}")
|
||||
|
||||
# you can also login using credentials in a json file
|
||||
|
||||
# in subsequent sessions, you can retrieve the client without re-authenticating:
|
||||
# authentication details will automatically be refreshed
|
||||
az <- get_azure_login("microsoft")
|
||||
|
||||
# refresh (renew) authentication details for clients for all tenants
|
||||
refresh_azure_logins()
|
||||
|
||||
}
|
||||
}
|
||||
\seealso{
|
||||
\link{az_rm}, \href{https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest}{Azure CLI documentation}
|
||||
}
|
|
@ -4,22 +4,22 @@
|
|||
\alias{get_azure_token}
|
||||
\title{Generate an Azure OAuth token}
|
||||
\usage{
|
||||
get_azure_token(aad_host, tenant, app,
|
||||
auth_type = c("client_credentials", "device_code"), password,
|
||||
resource_host)
|
||||
get_azure_token(resource_host, tenant, app, password = NULL,
|
||||
auth_type = if (is.null(password)) "device_code" else
|
||||
"client_credentials", aad_host = "https://login.microsoftonline.com/")
|
||||
}
|
||||
\arguments{
|
||||
\item{aad_host}{URL for your Azure Active Directory host. For the public Azure cloud, this is \code{https://login.microsoftonline.com/}.}
|
||||
\item{resource_host}{URL for your resource host. For Resource Manager in the public Azure cloud, this is \code{https://management.azure.com/}.}
|
||||
|
||||
\item{tenant}{Your tenant ID.}
|
||||
|
||||
\item{app}{Your client/app ID which you registered in AAD.}
|
||||
|
||||
\item{auth_type}{The authentication type, either \code{"client_credentials"} or \code{"device_code"}.}
|
||||
|
||||
\item{password}{Your password. Required for \code{auth_type == "client_credentials"}, ignored for \code{auth_type == "device_code"}.}
|
||||
|
||||
\item{resource_host}{URL for your resource host. For Resource Manager in the public Azure cloud, this is \code{https://management.azure.com/}.}
|
||||
\item{auth_type}{The authentication type, either \code{"client_credentials"} or \code{"device_code"}. Defaults to the latter if no password is provided, otherwise the former.}
|
||||
|
||||
\item{aad_host}{URL for your Azure Active Directory host. For the public Azure cloud, this is \code{https://login.microsoftonline.com/}.}
|
||||
}
|
||||
\description{
|
||||
This extends the OAuth functionality in httr to allow for device code authentication.
|
||||
|
|
|
@ -28,3 +28,32 @@ test_that("Authentication works",
|
|||
expect_is(az3, "az_rm")
|
||||
expect_true(is_azure_token(az3$token))
|
||||
})
|
||||
|
||||
|
||||
test_that("Persistent authentication works",
|
||||
{
|
||||
expect_true(is.null(delete_azure_login(tenant, confirm=FALSE)))
|
||||
expect_true(all(names(list_azure_logins()) != tenant))
|
||||
|
||||
login_dirs <- rappdirs::user_config_dir("AzureRMR", "AzureR", roaming=FALSE)
|
||||
expect_true(all(dir(login_dirs) != tenant))
|
||||
|
||||
az <- create_azure_login(tenant=tenant, app=app, password=password)
|
||||
expect_is(az, "az_rm")
|
||||
expect_true(length(dir(login_dirs, pattern=tenant)) == 1)
|
||||
|
||||
expect_true(is.null(delete_azure_login(tenant, confirm=FALSE)))
|
||||
expect_true(all(names(list_azure_logins()) != tenant))
|
||||
|
||||
creds <- tempfile(fileext=".json")
|
||||
writeLines(jsonlite::toJSON(list(tenant=tenant, app=app, password=password)), creds)
|
||||
|
||||
az2 <- create_azure_login(tenant=tenant, app=app, password=password)
|
||||
expect_is(az2, "az_rm")
|
||||
expect_true(length(dir(login_dirs, pattern=tenant)) == 1)
|
||||
|
||||
expect_true(az$tenant == az2$tenant && az$tenant == tenant)
|
||||
|
||||
az3 <- get_azure_login(tenant)
|
||||
expect_true(az$tenant == az3$tenant)
|
||||
})
|
||||
|
|
|
@ -22,7 +22,7 @@ As a general-purpose interface to Azure Resource Manager (ARM), you can use Azur
|
|||
|
||||
## Before you begin
|
||||
|
||||
To use AzureRMR, you must create and register a _service principal_ with Azure Active Directory. This is a one-time task, and the easiest method is to use the Azure cloud shell.
|
||||
To use AzureRMR, you must create and register a service principal with Azure Active Directory. This is a one-time task, and the easiest method is to use the Azure cloud shell.
|
||||
|
||||
- In the Azure Portal (https://portal.azure.com/), click on the Cloud Shell icon:
|
||||
|
||||
|
@ -36,42 +36,39 @@ To use AzureRMR, you must create and register a _service principal_ with Azure A
|
|||
|
||||
- Record your tenant ID, app ID, and password.
|
||||
|
||||
This will authorise your service principal to work with objects within a single subscription. If you want to add more subscriptions, you can do so via the Portal. Go to the Subscriptions pane, click on the subscription you want to add, then under "Access Control (IAM)", fill in the details for your service principal and the type of access it to have (typically "Contributor" is good enough).
|
||||
|
||||
If you want to allow access at something other than subscription level, you can use the `--scopes` argument in place of `--subscription`. For example, to restrict AzureRMR to only the "AnalyticsRG" resource group: `az ad sp create-for-rbac --scopes /subscriptions/{your-subscription-ID}/resourceGroups/AnalyticsRG`.
|
||||
|
||||
|
||||
## Logging in
|
||||
## Authentication
|
||||
|
||||
Let's look at a sample workflow involving AzureRMR. The first thing to do is authenticate with Azure. AzureRMR supports various ways of authenticating. You can supply a password (which is the default), or if your service principal requires it, you can use the [device code flow](https://www.oauth.com/oauth2-servers/device-flow/token-request/). With the latter, AzureRMR will display a code, and prompt you to visit a login site in your browser. You then enter the code on the site, which completes the process.
|
||||
Let's look at a sample workflow involving AzureRMR.
|
||||
|
||||
Finally, any authentication arguments can also be supplied in a JSON file, specified via the `config_file` argument. In particular, the output from the cloud shell command used to create the service principal can be used here.
|
||||
Under the hood, AzureRMR uses a similar authentication process to the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest). The first time you authenticate with a given Azure Active Directory tenant, you call `create_azure_login()` and supply your tenant, app ID and password. The resulting Resource Manager client object is saved on your machine, and can be retrieved in subsequent R sessions with `get_azure_login("{tenant}")`. AzureRMR will automatically refresh your credentials so you don't have to re-authenticate.
|
||||
|
||||
```{r, eval=FALSE}
|
||||
# authenticate with a password
|
||||
az <- az_rm$new(tenant="xxx-xxx-xxx",
|
||||
app="yyy-yyy-yyy",
|
||||
password="{your-password}")
|
||||
library(AzureRMR)
|
||||
|
||||
# authenticate with device code: R will display a code to enter in your browser
|
||||
az2 <- az_rm$new(tenant="xxx-xxx-xxx",
|
||||
app="zzz-zzz-zzz",
|
||||
auth_type="device")
|
||||
# if this is the first time you're logging in to this tenant
|
||||
az <- create_azure_login("myaadtenant.onmicrosoft.com", app="app_id", password="password")
|
||||
|
||||
# authenticate with credentials stored in a JSON file
|
||||
az3 <- az_rm$new(config_file="creds.json")
|
||||
# for subsequent sessions
|
||||
az <- get_azure_login("myaadtenant")
|
||||
|
||||
# you can also list the tenants that you've previously authenticated with
|
||||
list_azure_logins()
|
||||
```
|
||||
|
||||
|
||||
## Subscriptions and resource groups
|
||||
|
||||
AzureRMR allows you to work with your subscriptions and resource groups. Note that if you created your service principal via the cloud shell, as described in this vignette, you probably only have access to one subscription. Regardless, you can list all subscriptions that you can work with:
|
||||
|
||||
```{r, eval=FALSE}
|
||||
# all subscriptions associated with this app
|
||||
# all subscriptions
|
||||
az$list_subscriptions()
|
||||
#$`5710aa44-281f-49fe-bfa6-69e66bb55b11`
|
||||
#<Azure subscription 5710aa44-281f-49fe-bfa6-69e66bb55b11>
|
||||
# authorization_source: Legacy
|
||||
# authorization_source: RoleBased
|
||||
# name: Visual Studio Ultimate with MSDN
|
||||
# policies: list(locationPlacementId, quotaId, spendingLimit)
|
||||
# state: Enabled
|
||||
|
@ -99,7 +96,7 @@ Notice that AzureRMR is based on R6 classes, where methods are part of the objec
|
|||
The `list_subscriptions()` call returns a list of subscription objects. You can retrieve the details for a single subscription with `get_subscription`:
|
||||
|
||||
```{r, eval=FALSE}
|
||||
# get a subscription and resource group
|
||||
# get a subscription
|
||||
(sub1 <- az$get_subscription("5710aa44-281f-49fe-bfa6-69e66bb55b11"))
|
||||
#<Azure subscription 5710aa44-281f-49fe-bfa6-69e66bb55b11>
|
||||
# authorization_source: Legacy
|
||||
|
@ -119,9 +116,7 @@ A subscription object in turn has methods to get, create and delete resource gro
|
|||
#<Azure resource group rdev1>
|
||||
# id: /subscriptions/5710aa44-281f-49fe-bfa6-69e66bb55b11/resourceGroups/rdev1
|
||||
# location: australiaeast
|
||||
# managed_by: NULL
|
||||
# properties: list(provisioningState)
|
||||
# tags: NULL
|
||||
#---
|
||||
# Methods:
|
||||
# check, create_resource, delete, delete_resource, delete_template, deploy_template, get_resource,
|
||||
|
@ -140,12 +135,9 @@ Methods for working with resources and templates are exposed as part of the `az_
|
|||
(stor <- rg$get_resource(type="Microsoft.Storage/storageServices", name="rdevstor1"))
|
||||
#<Azure resource Microsoft.Storage/storageAccounts/rdevstor1>
|
||||
# id: /subscriptions/5710aa44-281f-49fe-bfa6-69e66bb55b11/resourceGroups/rdev1/providers/Microsoft.Sto ...
|
||||
# identity: NULL
|
||||
# is_synced: TRUE
|
||||
# kind: Storage
|
||||
# location: australiasoutheast
|
||||
# managed_by: NULL
|
||||
# plan: NULL
|
||||
# properties: list(networkAcls, trustedDirectories, supportsHttpsTrafficOnly, encryption,
|
||||
# provisioningState, creationTime, primaryEndpoints, primaryLocation, statusOfPrimary)
|
||||
# sku: list(name, tier)
|
||||
|
|
Загрузка…
Ссылка в новой задаче