【问题标题】:Shiny Azure WebApp Authenticate as user to Azure SQL Server闪亮的 Azure WebApp 以用户身份向 Azure SQL Server 进行身份验证
【发布时间】:2021-05-17 13:17:13
【问题描述】:

我正在构建一个以 SQL DB 作为后端的 WebApp。我在 Azure 上部署这两个部分,作为 Azure Webapp 和 SQL Server。

SQL 服务器使用 Azure AD (AAD) 进行保护。因此,只有组中的用户才能访问数据库。

所以我正在尝试设置 Webapp 登录用户并收集他的访问令牌的工作流程。然后使用token查询SQL server。

我已在 AAD 中注册了该应用程序,它被授权读取用户 ID 并冒充用户。

我有以下在本地工作的代码。但我无法让它在本地部署在 Docker 映像中工作。

# app file
library(shiny)
library(tidyverse)
library(shinyjs)
library(AzureAuth)

db <- "Azure"
config <- config::get(config = db)

redirect <- 'http://localhost:1410/app/'

ui_func <- function(req) {
  useShinyjs()
  opts <- parseQueryString(req$QUERY_STRING)
  if( is.null(opts$code) ) {
    auth_uri <- build_authorization_uri(
                  resource = config$resource, 
                  tenant = config$tenant, 
                  app = config$app, 
                  redirect_uri = redirect, 
                  # version = 2, 
                  prompt = 'login')
    redir_js <- sprintf('location.replace(\"%s\");', auth_uri)
    tags$script(HTML(redir_js))
  } else {
    fluidPage(
        verbatimTextOutput('token1'), 
        verbatimTextOutput('token2'),
        verbatimTextOutput('token_list'),
        verbatimTextOutput('path'),
        tableOutput('files'),
        tableOutput("db_tables")
        )
  }
}

server <- function(input, output, session) {


  opts <- parseQueryString(isolate(session$clientData$url_search))
  if(is.null(opts$code))
    return()
  #get_azure_token(
  #            config$resource, 
  #            config$tenant, 
  #            config$app,
  #            #pssw,
  #            # version = 2,
  #            auth_type = 'authorization_code', 
  #            use_cache = FALSE, 
  #            auth_code = opts$code) -> 
  tok1 <- NULL
  get_azure_token(
                  config$resource2, 
                  config$tenant, 
                  config$app, 
                  password = config$secret, 
                  auth_type = 'authorization_code', 
                  use_cache = FALSE, 
                  # auth_type='on_behalf_of', 
                  # on_behalf_of = tok1,
                  auth_code = opts$code
                  ) -> 
  tok2
  output$token <- renderPrint(tok1)
  output$token2 <- renderPrint(tok2)
  renderText({
    rappdirs::user_data_dir() %>% 
      fs::dir_ls() }) -> 
  output$path
  renderText({
    list_azure_tokens() 
  }) ->
  output$token_list

  renderTable({
    rappdirs::user_data_dir() %>% 
      fs::path(., 'AzureR') %>%
      fs::dir_ls(., all = TRUE) %>% 
      tibble::as_tibble()
  }) ->
  output$files
  
  pool <- NULL
  if(!is.null(tok2)) {
    if(db == "Azure") {
      pool::dbPool(
            drv = odbc::odbc(), 
            Driver = config$driver, 
            Server = config$server, 
            Database = config$database, 
            Port = config$port,
            Encrypt = config$encrypt,
            TrustServerCertificate = config$trustservercertificate,
            ConnectionTimeout = config$connectiontimeout,
            Authentication = config$authentication
            ) -> 
      pool
    } 
    if(db == "PCI") {
      pool::dbPool(
            odbc::odbc(),
            drv = odbc::odbc(), 
            Driver = config$driver, 
            Server = config$server, 
            Database = config$database, 
            TrustedConnection = config$trustedconnection
            ) -> 
      pool
    }
  }
  onStop(function() {
           pool::poolClose(pool)})
  reactive({
    dat <- NULL
    if(!is.null(pool)) {
      pool %>% 
        DBI::dbListTables(.) %>% 
        dplyr::as_tibble() -> 
      dat}
    return(dat)
  }) -> 
  db_tables
  output$db_tables <- renderTable({
    db_tables()})
}
shinyApp(ui_func, server)

Dockerfile

# Dockerfile to test azure
ARG SHINY_PORT=1410
ARG SHINY_HOST="127.0.0.1"
ARG DOCKER_DEPLOY="local"
FROM rocker/shiny-verse:4.0.5
ARG SHINY_PORT
ARG SHINY_HOST
ARG DOCKER_DEPLOY 

RUN apt-get update -y \
  && apt-get install -y \
    curl \
    gnupg

# See about installing ODBC drivers here: https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-2017
# Note that the driver version installed needs to match the version used in the code
# In this case for Ubuntu 18.04: ODBC SQL driver 17
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -

RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list

RUN apt-get update -y
RUN ACCEPT_EULA=Y apt-get install -y msodbcsql17
RUN ACCEPT_EULA=Y apt-get install -y mssql-tools
RUN apt-get install -y unixodbc-dev


RUN echo "\noptions(shiny.port=${SHINY_PORT}, shiny.host='${SHINY_HOST}')\n" >> /usr/local/lib/R/etc/Rprofile.site

## add any R 
RUN R -e 'install.packages(c("fs", "pkgload", "remotes", "tibble", "lubridate","shiny", "shinyjs", "shinythemes", "hms", "tidyverse", "magrittr", "AzureAuth"), dependencies = TRUE)'
RUN R -e 'install.packages(c("DT", "odbc", "rmarkdown","janitor", "reactable", "pool", "config","RODBC","DBI", "httpuv"), dependencies = TRUE )'

RUN mkdir /srv/shiny-server/app \
  && chown -R shiny:shiny /srv/shiny-server/app
COPY . /srv/shiny-server/app/

# setup shiny server. Create nessesarry dirs for server
COPY ./shiny-server.sh /usr/bin/shiny-server.sh
RUN chmod +x /usr/bin/shiny-server.sh
COPY ./shiny-server.conf /etc/shiny-server/shiny-server.conf

EXPOSE 1410 

# start server. Use sh from rocker project
CMD ["/usr/bin/shiny-server.sh"]
# config file for app
default:
  resource: 'https://graph.microsoft.com/'
  # resource: 'https://management.azure.com' 
  # resource: 
  #   - 'https://graph.microsoft.com/.default'
  #   - 'openid'
  #   - 'profile'
  #   - 'email'
  #   - 'offline_access'
  #   # - 'User.Read'
  resource2: 'https://database.windows.net/'
  tenant: 'xxxxxxx'
  app: 'xxxxxxx'
  secret: 'xxxxxxxxx'
  driver: 'ODBC Driver 17 for SQL Server'

PCI:
  inherits: default
  server: 'xxxxxx'
  # port: 'xxxxx'
  database: 'xxxxx'
  trustedconnection: 'xxxx'

Azure:
  inherits: default
  server: 'xxxxx'
  port: 'xxxxxx'
  database: 'xxxxxx'
  encrypt: 'yes'
  trustservercertificate: 'no'
  connectiontimeout: '30'
  # authentication: 'ActiveDirectoryPassword'
  authentication: 'ActiveDirectoryIntegrated'

【问题讨论】:

    标签: r sql-server azure shiny


    【解决方案1】:

    使用 OAuth 令牌连接到 SQL Server 需要使用 pre-connection attribute(基本上是指向令牌字符串的指针)。在 odbc Github 存储库中有一个 open feature request 用于此目的。我鼓励您投票支持它,希望如果它足够受欢迎,它将得到实施。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-18
      • 1970-01-01
      • 2019-07-16
      • 2017-10-30
      • 1970-01-01
      • 2013-03-31
      • 2016-06-04
      • 2013-09-13
      相关资源
      最近更新 更多