How to create custom plugin for LDAP only for authorization

Tools used : 1. Elasticsearch 2.1 with Shield 2.1 2. DgLux as a front end report generation tool 3. Company LDAP to authenticate user against groups

I'm trying to create a custom plugin which should use LDAP only for authorization.

Authentication is already happening via a third party LDAP utility to login into the system.

Every request that goes from DgLux to Elasticsearch will be authenticated and authorized to make sure that the user can perform specific task on the indices.

My requirement is that request will only have user in the header and shield shouldn't try to authenticate the request, only authorization should happen.

How can I built that plugin?

If you have control over the header name that is passed to elasticsearch, you can use the run as feature of Shield. For this to work, DgLux would need to send authentication credentials for a user that had the ability to run as the actual user in Shield. In the configuration for Shield, you would define an LDAP realm (with a bind_dn) that will be used to look up the user in the run as header and could authorize the user. Note: you could use anonymous access for DgLux but that would not be very secure unless you can guarantee that DgLux is the only thing communicating directly with elasticsearch.

If that will not work for you, I suggest you take a look at custom realms and the example for 2.1.0. Your custom realm would look for the header passed from DgLux and convert that into a specific authentication token that your custom realm understands. The token would then get passed into the authenticate method by Shield and this is where you would implement code to lookup the user in LDAP and map them to the appropriate Shield role names. In this scenario, you would also want a way to authenticate the requests coming from DgLux otherwise this will not be secure since anyone can pass in the header and get into elasticsearch.

We were already working on run_as functionality and found that it is not feasible because of two reasons:

  1. For run_as functionality we need to pass a generic user with password which should have same access as the DgLux user. That means we need to do it dynamically as DgLux user which is supposed to get admin access can not run_as a restricted user from shield so we cannot hard code the generic user name and password for all requests.

  2. DgLux is unable to pass any additional parameters/headers.

So the only solution we are thinking is to develop a custom plugin and here are few thoughts we have:

  1. Override the default LDAP realm to change its functionality for authentication and authorization.
  2. For Authentication create a session using generic username and password which is defined in LDAP
  3. For Authorization set supportsUnauthenticatedSession=true from SessionFactory class so that it will only use the username to create LDAP session and perform role mappings.

For above feature we are trying use custom realm example CustomRealm.java to override authentication and authorization logics and CustomRealmFactory.java to instantiate CustomRealm. But there is no success yet. Any help would be appreciated.

I'm not sure I fully understand this, but I wanted to clarify how run-as works. Let's use a quick example: when using the run-as feature, you make a search request as the user my_application. As part of the request, set the header es-shield-runas-user: skearns. This tells Shield that the my_application user would like to run a request as the user skearns.

The my_application user does not need to have the same level of permissions as skearns. In fact, the my_application user only needs permission to run_as the user skearns, which you could achieve by granting the my_application user a role that only grants run_as capabilities, like this:

run_as_role:
    run_as: skearns

What other headers do you want to pass that you cannot?

My understanding of run_as functionality, based on what i have red and tested, is as per below syntax:

Curl -H "es-shield-runas-user: {Outside user who need access to cluster}" -u {Generic user defined in shield to be used for authentication} : {password for generic user defined in shield} http://{host}:{port}

Please correct me if i'm wrong.

Your understanding of run as is correct. The only think I would add is that you can use PKI to authenticate rather than a preconfigured user; not sure if DgLux would support that...

It sounds to me like you are trying to extend existing Shield classes? This really is not supported and there are no API guarantees for these classes; in a bugfix release a change to these classes could break your realm. These classes are not intended to be used in a custom realm.

Instead, I would implement a custom realm that does exactly what you need. The interfaces/classes exposed in the custom realm example are what I would consider stable and we will try to not break the API for these in minor releases.

You will need to provide more information. For things like this, "there is no success yet" does not provide any information that enables us to help. Please provide all of the details of what you have done and if possible code snippets.