Skip to content

Scope-able elasticsearch clients #39430

Open

Description

Every time when Kibana needs to get access to data saved in elasticsearch it should perform a check whether an end user has access to the data.

Regular mode

This check relays heavily on Security that authenticates a user via elasticsearch API and set authorization header accordingly. Having user authenticated Kibana performs all requests to elasticsearch on behalf of the user by attaching authorization headers to an incoming request:

callWithRequest(request: Request)

Note: the whole Request object is not required to hit elasticsearch API, but something with interface { headers: { authorization: 'token, [...other authorization headers: string]: string } }.

FakeRequest mode

There are a couple of cases when the current model doesn't play well

  • When we need to check whether headers.authorization contains valid credentials.
// in legacy platform
try{
  request.headers.authorization = tokenCandidate;
  callWithRequest(request)
} catch(e){
  delete request.headers.authorization
}
// in new platform
asScoped({headers: {authorization: tokenCandidate }}.callAsCurrentUser()
  • When elasticsearch api is called outside of Http request context.

In Reporting plugin

const decryptedHeaders: string = await crypto.decrypt(job.headers);

And in Upgrade Assistant

const fakeRequest = { headers: credential } as Request;

In all those cases we 'mimic' Request object, although we need only authorization headers to be present.

Discuss

  • What core services need to support this "scoping" mechanic? Obviously, it works for elasticsearch and other services that wrap it, like SavedObjects. Probably there is something else that I missed.
  • What should be considered as a valid input for asScoped()? Are those use cases for FakeRequest are going to stay in a long-term? Should we operate Request term at all? Probably we could rename it to something less confusing, for example OwnerCredentials to emphasise that something with scope-able interface is a valid input.
  • Will Alerting plugin use the same FakeRequest pattern to perform access data? @mikecote
  • Should elasticsearch ClusterClient support headers re-configuring? At the moment it's not possible. On the one hand it's a good thing because we explicitly declare the creation of FakeRequest to perform a call and declare dependencies on the passed credentials.
const data = await dataClient.asScoped({headers: { authorization: ....}}).callAsInternalUser()

On the other hand, the ergonomic suffers as we have to use asScoped and cannot leverage coming Handler RFC API to extend a request for custom needs

// or in registerHandler
const dataClient = await dataClient$.pipe(take(1)).toPromise();
const dataClient = dataClient.asScoped(request);
// somewhere below
const data = await dataClient.callAsInternalUser({headers: { authorization: ....}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Feature:New PlatformTeam:CoreCore services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etcTeam:SecurityTeam focused on: Auth, Users, Roles, Spaces, Audit Logging, and more!discuss

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions