将 KeycloakOIDCFilter 与 Spark UI 结合使用 - 无法配置

Using KeycloakOIDCFilter with Spark UI - cannot configure

我们正在尝试使用 KeycloakOIDCFilter 作为我们的 Apache Spark UI 过滤器。但是,我们正在努力配置 KeycloakOIDCFilter 本身。

我们有,在 spark-defaults.conf:

spark.ui.filters=org.keycloak.adapters.servlet.KeycloakOIDCFilter

已成功提取,Spark 主日志显示此过滤器已应用于所有 URL 路由。

我们在 Keycloak 管理控制台中生成了一个客户端配置文件,它输出了 keycloak-oidc.json.

但是我们如何告诉KeycloakOIDCFilter这些信息

来自火花docs

Filter parameters can also be specified in the configuration, by setting config entries of the form spark.<class name of filter>.param.<param name>=<value> For example:

spark.ui.filters=com.test.filter1
spark.com.test.filter1.param.name1=foo
spark.com.test.filter1.param.name2=bar

在我们的例子中似乎是:

spark.org.keycloak.adapters.servlet.KeycloakOIDCFilter.param.<name>=<value>

然而,KeycloakOIDCFilter Java class 只有两个构造函数。一个根本不带参数,一个带 KeycloakConfigResolver.

Keycloak Java servlet filter adapter 文档仅讨论 web.xml 这不适用于配置 Spark 的情况。

那么我们怎样才能正确地configure/point为KeycloakOIDCFilter servlet过滤器设置参数呢?


更新:我们已经确定 spark.org.keycloak.adapters.servlet.KeycloakOIDCFilter.param.keycloak.config.file 可用于指向配置文件,但似乎 Spark does not use SessionManager 会导致单独的错误,该错误可能无法解决。

我还没有测试该解决方案,但是根据您引用的 Keycloak 和 Spark 文档以及 KeycloakOIDCFilter 的源代码,假设您使用的是文件系统中的文件,则以下配置可能有效:

spark.ui.filters=org.keycloak.adapters.servlet.KeycloakOIDCFilter
spark.org.keycloak.adapters.servlet.KeycloakOIDCFilter.param.keycloak.config.file=/path/to/keycloak-oidc.json

或者另一个,如果您的配置可以通过 getServletContext().getResourceAsStream(...) 而不是文件作为 Web 应用程序资源访问:

spark.ui.filters=org.keycloak.adapters.servlet.KeycloakOIDCFilter
spark.org.keycloak.adapters.servlet.KeycloakOIDCFilter.param.keycloak.config.path=/WEB-INF/keycloak-oidc.json

请注意,它们表明过滤器参数也可以在配置中指定:afaik,这并不意味着过滤器应该有任何特殊的构造函数或类似的东西。

此配置由addFilters执行:

/**
  * Add filters, if any, to the given ServletContextHandlers. Always adds a filter at the end
  * of the chain to perform security-related functions.
  */
private def addFilters(handler: ServletContextHandler, securityMgr: SecurityManager): Unit = {
  conf.get(UI_FILTERS).foreach { filter =>
    logInfo(s"Adding filter to ${handler.getContextPath()}: $filter")
    val oldParams = conf.getOption(s"spark.$filter.params").toSeq
      .flatMap(Utils.stringToSeq)
      .flatMap { param =>
        val parts = param.split("=")
        if (parts.length == 2) Some(parts(0) -> parts(1)) else None
      }
      .toMap


    val newParams = conf.getAllWithPrefix(s"spark.$filter.param.").toMap


    JettyUtils.addFilter(handler, filter, oldParams ++ newParams)
}

addFilter

def addFilter(
      handler: ServletContextHandler,
      filter: String,
      params: Map[String, String]): Unit = {
    val holder = new FilterHolder()
    holder.setClassName(filter)
    params.foreach { case (k, v) => holder.setInitParameter(k, v) }
    handler.addFilter(holder, "/*", EnumSet.allOf(classOf[DispatcherType]))
}

Spark UI.

源代码中JettyUtilsclass中的方法