Skip to content

[KYUUBI #6927] add spnego ui with session manager. add spnego end-to-end ui rest#17

Open
paradoxfm wants to merge 4 commits into1.10.1-developfrom
feature/ADH-7478
Open

[KYUUBI #6927] add spnego ui with session manager. add spnego end-to-end ui rest#17
paradoxfm wants to merge 4 commits into1.10.1-developfrom
feature/ADH-7478

Conversation

@paradoxfm
Copy link
Copy Markdown

Add spnego ui with session manager. add spnego end-to-end ui rest

Fix bug apache#6927

add conf parameter kyuubi.frontend.rest.ui.spnego.enabled
this functional also use spnego rest config

server.addHandler(authenticationFactory.httpHandlerWrapperFactory.wrapHandler(proxyHandler))
if (conf.get(FRONTEND_REST_UI_ENABLED)) {
installWebUI()
// JettyUtils.createStaticHandlerSpnego("", "", "", "", "")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

val principal = authenticate(httpReq, httpResp) // auth SPNEGO

if (principal != null) {
// Создаем новую сессию
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All comments must be in English.

val authorization = getAuthorization(request)
val clientToken = Base64.getDecoder.decode(authorization)
try {
debug("step by step spnego ui")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

try {
debug("step by step spnego ui")
val serverPrincipal = getTokenServerName(clientToken)
debug("step 2 getTokenServerName")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

s"Invalid server principal $serverPrincipal decoded from client request")
}

debug("step 3 startsWith")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
})

debug("step 4 doAs")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
if (!gssContext.isEstablished) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED)
debug("SPNEGO in progress")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

private var serverSubject = new Subject()
private var keytab: String = _
private var principal: String = _
private val sessionTimeout = conf.get(KyuubiConf.SESSION_IDLE_TIMEOUT).toInt
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loss of accuracy?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SESSION_IDLE_TIMEOUT measure in seconds, but all numbers in config stored as long
it`s preconversion for usage

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the current code and default config, the session will live 21 600 000 seconds instead of 6 hours.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not a constant and also configurable

Copy link
Copy Markdown
Collaborator

@Asmoday Asmoday Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fallbackConf(SESSION_TIMEOUT)
createWithDefault(Duration.ofHours(6).toMillis)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can change it in kyuubi.defaults -> kyuubi.session.idle.timeout

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

httpResp.setHeader(WWW_AUTHENTICATE_HEADER, "Negotiate") // it must before sendError
httpResp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "No SPNEGO token")

case authHeader if authHeader.startsWith("Negotiate ") =>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuthSchemes.NEGOTIATE ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case must be with space, because exists variants with "Negotiate-something" etc

httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED)
if (conf.get(FRONTEND_REST_UI_SPNEGO_ENABLED)) {
// For using rest from ui required end-to-end auth
httpResponse.setHeader(WWW_AUTHENTICATE_HEADER, "Negotiate")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about requests that are not from the UI - /v1/*?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this header indicates client to what protocol work with. it does not change normal work mode

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many HTTP clients auto-react to this header. It change auth scheme priority.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it header will be added if matchedHandler == null. it mean that other schemes not found

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchedHandler == null means that the client has not yet attempted to authenticate.
What will happen with LDAP + UI Spnego case?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spnego works only kerberros. its end-to-end scheme. ui -> rest -> ...

@Asmoday
Copy link
Copy Markdown
Collaborator

Asmoday commented Mar 10, 2026

Please add tests to AuthenticationFilterSuite.

@Asmoday
Copy link
Copy Markdown
Collaborator

Asmoday commented Mar 10, 2026

Why create a new SpnegoSessionFilter instead of work with the KerberosAuthenticationHandler? The SPNEGO logic in both classes is identical.
Could SpnegoSessionFilter simply delegate authentication to KerberosAuthenticationHandler and only add session caching on top?

@paradoxfm
Copy link
Copy Markdown
Author

Why create a new SpnegoSessionFilter instead of work with the KerberosAuthenticationHandler? The SPNEGO logic in both classes is identical. Could SpnegoSessionFilter simply delegate authentication to KerberosAuthenticationHandler and only add session caching on top?

because I need manage sessions, heades and hander wothks readonly, and does not work with principal start with HTTP/
I couldn't get it to work notmaly

@Asmoday
Copy link
Copy Markdown
Collaborator

Asmoday commented Mar 10, 2026

Why create a new SpnegoSessionFilter instead of work with the KerberosAuthenticationHandler? The SPNEGO logic in both classes is identical. Could SpnegoSessionFilter simply delegate authentication to KerberosAuthenticationHandler and only add session caching on top?

because I need manage sessions, heades and hander wothks readonly, and does not work with principal start with HTTP/ I couldn't get it to work notmaly

readonly?
That won't work?


class SpnegoSessionFilter(conf: KyuubiConf) extends Filter {                                                                                                                                                                                                                                                                                                              
    private val kerberosHandler = new KerberosAuthenticationHandler                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                            
    override def init(cfg: FilterConfig): Unit = {
      kerberosHandler.init(conf)                                                                                                                                                                                                                                                                                                                                            
    }             

    override def doFilter {
...
      val auth = httpReq.getHeader("Authorization")
      ...
      
...
      val principal = kerberosHandler.authenticate(httpReq, httpResp)

      if (principal != null) {
        session
        ...

      }
    }

  }

@paradoxfm
Copy link
Copy Markdown
Author

readonly? That won't work?

I`ll try

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants