получение ошибки при подключении Databricks к базе данных Azure SQL с помощью ActiveDirectoryPassword

Я пытаюсь подключить Azure sql db из Databricks с помощью AAD — аутентификация пароля. Я импортировал azure sql db и adal4j libs. но все еще получаю ошибку ниже

java.lang.NoClassDefFoundError: com/nimbusds/oauth2/sdk/AuthorizationGrant

трассировки стека:

    at com.microsoft.sqlserver.jdbc.SQLServerADAL4JUtils.getSqlFedAuthToken(SQLServerADAL4JUtils.java:24)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.getFedAuthToken(SQLServerConnection.java:3609)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.onFedAuthInfo(SQLServerConnection.java:3580)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.processFedAuthInfo(SQLServerConnection.java:3548)
    at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onFedAuthInfo(tdsparser.java:261)
    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:103)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.sendLogon(SQLServerConnection.java:4290)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:3157)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.access$100(SQLServerConnection.java:82)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:3121)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2026)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1687)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1528)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:866)
    at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:569)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$createConnectionFactory$1.apply(JdbcUtils.scala:63)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$createConnectionFactory$1.apply(JdbcUtils.scala:54)
    at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$.resolveTable(JDBCRDD.scala:56)
    at org.apache.spark.sql.execution.datasources.jdbc.JDBCRelation.<init>(JDBCRelation.scala:115)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcRelationProvider.createRelation(JdbcRelationProvider.scala:5
at com.databricks.backend.daemon.driver.DriverWrapper.tryExecutingCommand(DriverWrapper.scala:590)
    at com.databricks.backend.daemon.driver.DriverWrapper.getCommandOutputAndError(DriverWrapper.scala:474)
    at com.databricks.backend.daemon.driver.DriverWrapper.executeCommand(DriverWrapper.scala:548)
    at com.databricks.backend.daemon.driver.DriverWrapper.runInnerLoop(DriverWrapper.scala:380)
    at com.databricks.backend.daemon.driver.DriverWrapper.runInner(DriverWrapper.scala:327)
    at com.databricks.backend.daemon.driver.DriverWrapper.run(DriverWrapper.scala:215)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: com.nimbusds.oauth2.sdk.AuthorizationGrant
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

импортировал библиотеку nimbusds в свою рабочую область.

вот конфиг

import com.microsoft.azure.sqldb.spark.config.Config
import com.microsoft.azure.sqldb.spark.connect._
import org.apache.spark.sql.SparkSession

val spark: SparkSession = SparkSession.builder().getOrCreate()

    val config = Config(Map(

      "url"            -> "ServerName.database.windows.net",
      "databaseName"   -> "dbname",
      "dbTable"        -> "dbo.test",
      "user"           -> "[email protected]",
      "password"       -> "pwd",
      "authentication" -> "ActiveDirectoryPassword",
      "encrypt"        -> "true",
      "trustServerCertificate"->"false",
      "hostNameInCertificate"->"*.database.windows.net"
    ))

    val collection = spark.read.sqlDB(config)
    collection.show()

пожалуйста, помогите мне, если кто-то решил эту проблему.

введите здесь описание изображения


person Ramana    schedule 13.10.2018    source источник
comment
Вам не хватает библиотеки в вашем пути к классам (той, которая содержит класс com.nimbusds.oauth2.sdk.AuthorizationGrant)   -  person Mark Rotteveel    schedule 13.10.2018
comment
Связанный, возможно дублирующийся: stackoverflow.com/questions/45006441/ и stackoverflow.com/questions/29380910/, см. также stackoverflow.com/questions/1457863/   -  person Mark Rotteveel    schedule 13.10.2018
comment
спасибо Марк за ответ. Я импортировал oauth2-oidc-sdk-3.0.jar в свою рабочую область и подключил к кластеру. нужно ли где-то регистрировать. также загруженный фрагмент   -  person Ramana    schedule 13.10.2018


Ответы (2)


Нажмите здесь скачать рабочий блокнот.

Создание кластера Databricks

Известная рабочая конфигурация — Databricks Runtime 5.2 (включая Apache Spark 2.4.0, Scala 2.11)

Установите соединитель Spark для базы данных Microsoft Azure SQL и SQL Server.

  1. Перейдите в раздел Кластер > Библиотека > Установить новый > Maven > Поиск пакетов.
  2. Переключитесь на Maven Central
  3. Найдите azure-sqldb-spark (com.microsoft.azure:azure-sqldb-spark).
  4. Нажмите Выбрать.
  5. Нажмите Установить.

Известная рабочая версия — com.microsoft.azure:azure-sqldb-spark:1.0.2.

Обновить переменные

Обновите значения переменных (custerName, server, database, table, username, password)

Запустите команду инициализации (ТОЛЬКО ОДИН РАЗ)

Это сделает следующее:

  1. Создайте папку с именем init в папке dbfs:/databricks/init/
  2. Создайте подпапку с именем кластера Databricks.
  3. Создайте сценарий bash для каждой зависимости

Команды сценария Bash: * wget: получить содержимое с веб-сервера * --quit: отключить вывод wget * -O: вывод

Зависимости:

Перезапустите кластер Databricks.

Это необходимо для выполнения скрипта инициализации.

Запустите последнюю ячейку в этом блокноте

Это проверит возможность подключения к базе данных SQL Azure с помощью проверки подлинности Active Directory.

Команда инициализации

// Initialisation
// This code block only needs to be run once to create the init script for the cluster (file remains on restart)

// Get the cluster name
var clusterName = dbutils.widgets.get("cluster")

// Create dbfs:/databricks/init/ if it doesn’t exist.
dbutils.fs.mkdirs("dbfs:/databricks/init/")

// Create a directory named (clusterName) using Databricks File System - DBFS.
dbutils.fs.mkdirs(s"dbfs:/databricks/init/$clusterName/")

// Create the adal4j script.
dbutils.fs.put(s"/databricks/init/$clusterName/adal4j-install.sh","""
#!/bin/bash
wget --quiet -O /mnt/driver-daemon/jars/adal4j-1.6.0.jar http://central.maven.org/maven2/com/microsoft/azure/adal4j/1.6.0/adal4j-1.6.0.jar
wget --quiet -O /mnt/jars/driver-daemon/adal4j-1.6.0.jar http://central.maven.org/maven2/com/microsoft/azure/adal4j/1.6.0/adal4j-1.6.0.jar""", true)

// Create the oauth2 script.
dbutils.fs.put(s"/databricks/init/$clusterName/oauth2-install.sh","""
#!/bin/bash
wget --quiet -O /mnt/driver-daemon/jars/oauth2-oidc-sdk-5.24.1.jar http://central.maven.org/maven2/com/nimbusds/oauth2-oidc-sdk/5.24.1/oauth2-oidc-sdk-5.24.1.jar
wget --quiet -O /mnt/jars/driver-daemon/oauth2-oidc-sdk-5.24.1.jar http://central.maven.org/maven2/com/nimbusds/oauth2-oidc-sdk/5.24.1/oauth2-oidc-sdk-5.24.1.jar""", true)

// Create the json script.
dbutils.fs.put(s"/databricks/init/$clusterName/json-smart-install.sh","""
#!/bin/bash
wget --quiet -O /mnt/driver-daemon/jars/json-smart-1.1.1.jar http://central.maven.org/maven2/net/minidev/json-smart/1.1.1/json-smart-1.1.1.jar
wget --quiet -O /mnt/jars/driver-daemon/json-smart-1.1.1.jar http://central.maven.org/maven2/net/minidev/json-smart/1.1.1/json-smart-1.1.1.jar""", true)

// Create the jwt script.
dbutils.fs.put(s"/databricks/init/$clusterName/jwt-install.sh","""
#!/bin/bash
wget --quiet -O /mnt/driver-daemon/jars/nimbus-jose-jwt-7.0.1.jar http://central.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.0.1/nimbus-jose-jwt-7.0.1.jar
wget --quiet -O /mnt/jars/driver-daemon/nimbus-jose-jwt-7.0.1.jar http://central.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.0.1/nimbus-jose-jwt-7.0.1.jar""", true)

// Check that the cluster-specific init script exists.
display(dbutils.fs.ls(s"dbfs:/databricks/init/$clusterName/"))

Тестовая команда

// Connect to Azure SQL Database via Active Directory Password Authentication
import com.microsoft.azure.sqldb.spark.config.Config
import com.microsoft.azure.sqldb.spark.connect._

// Get Widget Values
var server = dbutils.widgets.get("server")
var database = dbutils.widgets.get("database")
var table = dbutils.widgets.get("table")
var username = dbutils.widgets.get("user")
var password = dbutils.widgets.get("password")

val config = Config(Map(
  "url"                    -> s"$server.database.windows.net",
  "databaseName"           -> s"$database",
  "dbTable"                -> s"$table",
  "user"                   -> s"$username",
  "password"               -> s"$password",
  "authentication"         -> "ActiveDirectoryPassword",
  "encrypt"                -> "true",
  "ServerCertificate"      -> "false",
  "hostNameInCertificate"  -> "*.database.windows.net"
))

val collection = sqlContext.read.sqlDB(config)
collection.show()
person taygan    schedule 16.05.2019
comment
Я понял, что это зависит от среды выполнения Databricks. Все, что ниже Spark 3.0, работает, однако новые среды выполнения с ним не работают. Знаете ли вы, что нужно обновить, чтобы это также работало в новых средах выполнения Databricks? - person Mimi Müller; 16.07.2021

В качестве обновления 2020 года:

Я выполнил сценарии инициализации кластера, как описано, но, в конце концов, моя рабочая установка, похоже, не требовала этого.

В итоге я использовал scala 2.11 (примечание 2.11) и эти библиотеки, установленные через пользовательский интерфейс: com.microsoft.azure:azure-sqldb-spark:1.0.2 и mssql_jdbc_8

import msal

TenantId = "...guid..."
authority = "https://login.microsoftonline.com/" + TenantId
scope = "https://database.windows.net//.default"  #???? yes, with double "//"
ServicePrincipalId = "...guid..."
ServicePrincipalPwd = "secret"

app = msal.ConfidentialClientApplication(client_id=ServicePrincipalId, authority=authority, client_credential=ServicePrincipalPwd, )

result = None
result = app.acquire_token_silent(scopes=[scope], account=None)

if not result:
    result = app.acquire_token_for_client(scope)

if "access_token" in result:
    sqlAzureAccessToken = result["access_token"]
2_jre8.jar (примечание jre8). Также мне пришлось явно указать класс драйвера в конфиге:

import com.microsoft.azure.sqldb.spark.config.Config
import com.microsoft.azure.sqldb.spark.connect._

val config = Config(Map(
   "url"            -> "....database.windows.net",
   "databaseName"   -> "...",
   "dbTable"        -> "...",
   "accessToken"           -> "...",
   "hostNameInCertificate" -> "*.database.windows.net",
   "encrypt"               -> "true",
   "ServerCertificate"      -> "false",
   "driver"                 -> "com.microsoft.sqlserver.jdbc.SQLServerDriver"
))

val collection = spark.read.sqlDB(config)
collection.show()

Получение токена было выполнено с помощью msal (python):

import msal

TenantId = "...guid..."
authority = "https://login.microsoftonline.com/" + TenantId
scope = "https://database.windows.net//.default"  #???? yes, with double "//"
ServicePrincipalId = "...guid..."
ServicePrincipalPwd = "secret"

app = msal.ConfidentialClientApplication(client_id=ServicePrincipalId, authority=authority, client_credential=ServicePrincipalPwd, )

result = None
result = app.acquire_token_silent(scopes=[scope], account=None)

if not result:
    result = app.acquire_token_for_client(scope)

if "access_token" in result:
    sqlAzureAccessToken = result["access_token"]
person burma    schedule 27.03.2020