我正在构建一个以SQL DB作为后端的WebApp。我正在Azure上部署这两个部分,作为Azure Webapp和SQL Server。
SQL服务器已使用Azure AD(AAD(进行了加密。因此,只有组中的用户才能访问数据库。
因此,我试图设置一个工作流程,让Web应用程序登录用户并收集他的访问令牌。然后使用该令牌查询SQL服务器。
我已经在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://learn.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'
使用OAuth令牌连接到SQL Server需要使用预连接属性(基本上是指向令牌字符串的指针(。odbc Github repo中有一个开放特性请求。我鼓励你们投票支持它,希望如果它足够受欢迎,它会得到实施。