对 SQL Server on Spark 框架的 JavaKerberos 身份验证

JavaKerberos authentication to SQL Server on Spark framework

我正在尝试使用带有 Microsoft 的 JDBC 驱动程序 (v7.0.0) 的 JavaKerberos 将 spark 集群写入 SQL 服务器(即,我在连接中指定 integratedSecurity=true;authenticationScheme=JavaKerberos string) 和在 keyTab 文件中指定的凭据,但我没有取得太大的成功(如果我在连接字符串中指定凭据,问题是一样的)。

我正在将作业提交到集群(4 节点 YARN 模式 v 2.3.0):

spark-submit --driver-class-path mssql-jdbc-7.0.0.jre8.jar \
--jars /path/to/mssql-jdbc-7.0.0.jre8.jar \
--conf spark.executor.extraClassPath=/path/to/mssql-jdbc-7.0.0.jre8.jar \
--conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=/path/to/SQLJDBCDriver.conf" \
--conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=/path/to/SQLJDBCDriver.conf" \
application.jar

部分工作:spark 驱动程序正确验证并创建 table,但是当任何执行程序写入 table 时,它们会失败并出现异常:

java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)

观察:

经过大量 logging/debugging spark 驱动程序和执行程序行为的差异之后,似乎归结为执行程序尝试使用错误的凭据,即使指定的选项 应该 让它使用 keytab 文件中指定的那些,因为它对 spark 驱动程序成功。 (这就是为什么它会生成那个特定的异常,如果我故意尝试不正确的凭据,它就会这样做。)

奇怪的是,我可以在调试输出中看到 JDBC 驱动程序找到并读取了 SQLJDBCDriver.conf 文件并且密钥表必须显示(否则我得到文件未找到失败)但它很快忽略它们并尝试使用默认 behaviour/local 用户凭据。

任何人都可以帮助我了解如何强制执行者使用 keytab 中提供的凭据或以其他方式获得 JavaKerberos/SQL 服务器身份验证以使用 Spark?

显然 JDBC 根据这里 https://issues.apache.org/jira/browse/SPARK-12312 的旧 JIRA,Kerberos 身份验证目前在执行程序上是不可能的。根据 spark 用户列表和我的测试,行为与版本 2.3.2 相同。

解决方法

  1. 使用 kinit,然后将缓存的 TGT 分发给执行程序,详见此处:https://github.com/LucaCanali/Miscellaneous/blob/master/Spark_Notes/Spark_Executors_Kerberos_HowTo.md。我 认为 此技术仅适用于 spark 执行程序 运行 下的用户。至少我无法让它为我的用例工作。
  2. 用处理身份验证的自定义版本包装 jdbc 驱动程序,然后调用和 returns 来自真实 MS JDBC 驱动程序的连接。详情在这里:https://datamountaineer.com/2016/01/15/spark-jdbc-sql-server-kerberos/ and the associated repo here: https://github.com/nabacg/krb5sqljdb。尽管我必须为我的案例修改身份验证代码,但我还是让这项技术起作用了。

我刚刚关闭了 https://issues.apache.org/jira/browse/SPARK-12312 and now it's possible to do Kerberos authentication with built-in JDBC connection providers. There are many providers added and one of them is MS SQL. Please read the documentation how to use it: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html

,只是为了提供最新情况

请注意,Spark 3.1 尚未发布,因此新添加的 2 个配置参数(keytabprincipal)需要一些时间才能出现在页面上。我认为文档更新将在 1-2 周内发生。

集成身份验证不适用于具有 AD 集成的安全集群中的 MS SQLServer JDBC 驱动程序,因为容器将没有上下文,因为映射器生成时 Kerberos 令牌丢失(当 YARN 将作业转移到其内部安全子系统时)。

这是我的存储库,它被用作获得 Kerberos/AD 身份验证的解决方法 https://github.com/chandanbalu/mssql-jdbc-krb5 解决方案实现了一个驱动程序,该驱动程序覆盖了最新 MS 的连接方法 SQL JDBC驱动程序 (mssql-jdbc-9.2.1.jre8.jar),并将获得密钥表 file/principal 的票证,并返回此连接。

您可以从发布文件夹中获取此自定义驱动程序的最新版本 here

使用 JARS

启动 spark-shell
spark-shell --jars /efs/home/c795701/.ivy2/jars/mssql-jdbc-9.2.1.jre8.jar,/efs/home/c795701/mssql-jdbc-krb5/target/scala-2.10/mssql-jdbc-krb5_2.10-1.0.jar

斯卡拉

scala>val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:krb5ss://<SERVER_NAME>:1433;databasename=<DATABASE_NAME>;integratedSecurity=true;authenticationScheme=JavaKerberos;krb5Principal=c795701@NA.DOMAIN.COM;krb5Keytab=/efs/home/c795701/c795701.keytab").option("driver","hadoop.sqlserver.jdbc.krb5.SQLServ, "dbo.table_name").load()

scala>jdbcDF.count()
scala>jdbcDF.show(10)

spark 提交 命令

com.spark.SparkJDBCIngestion - Spark JDBC 数据帧操作

ingestionframework-1.0-SNAPSHOT.jar - 你的项目构建 JAR

spark-submit \
--master yarn \
--deploy-mode cluster \
--jars "/efs/home/c795701/mssql-jdbc-krb5/target/scala-2.10/mssql-jdbc-krb5_2.10-1.0.jar,/efs/home/c795701/.ivy2/jars/scala-library-2.11.1.jar"
--files /efs/home/c795701/c795701.keytab
--class com.spark.SparkJDBCIngestion \
/efs/home/c795701/ingestionframework/target/ingestionframework-1.0-SNAPSHOT.jar