Elasticsearch 7.17.x User-Based Auth with Liferay DXP 7.4

A very common yet very important security aspect.

Today, we will be discussing how to configure an Elasticsearch cluster (2+ nodes) over Native User Authentication and integrate it with Liferay DXP. 

Contents:

  • Elasticsearch Vulnerability
  • Configuring Elasticsearch & Enabling Native User Auth
  • Configuring Liferay DXP + Elasticsearch with Native User Auth Enabled

Elasticsearch Vulnerability:

Before making the Liferay-hosted Websites/Portals Live to the end customers, it is very important to run a Security scan test on the whole Website/Portals to minimize the loose ends related to security and reduce the risks of anonymous attacks.

One of the most common security issue reported is Elasticsearch Unrestricted Access Information Disclosure. Now, before starting the actual Setup, I would like to advise that the User Auth in Elasticsearch MUST be configured & enabled while setting up the Vanilla instances of Elasticsearch for all those Environments which will have Remote Elasticsearch in its strategy, and of course PRODUCTION Env. is necessary.

Configuring Elasticsearch & Enabling Native User Auth:

For this Blog, I will be taking 3 nodes Elasticsearch cluster (you can have 2 or multiple nodes, the configuration remains similar)

Step #1: Once the Elasticsearch is installed or extracted (based on the mode of setup), open the elasticsearch.yml file and add the below configuration in all 3 nodes respectively.

    cluster.name: LiferayElasticsearchCluster
    network.host: nodeN_ip
    http.port: 9200
    transport.port: 9300
    node.name: node-N
    cluster.initial_master_nodes: ["node-N","node-N+1","node-N+2"]
    discovery.seed_hosts: ["nodeN_ip:9300","nodeN+1_ip:9300","nodeN+2_ip:9300"]
    ingest.geoip.downloader.enabled: false
    xpack.security.enabled: true

(Here N=1)

   (Remember to change the value of network.host: as per the node IP address)

For "cluster.initial_master_nodes" 

  • Starting an Elasticsearch cluster for the very first time requires the initial set of master-eligible nodes to be explicitly defined on one or more of the master-eligible nodes in the cluster. This is known as cluster bootstrapping. This is only required the first time a cluster starts up: nodes that have already joined a cluster store this information in their data folder for use in a full cluster restart and freshly-started nodes that are joining a running cluster obtain this information from the cluster’s elected master.
  • When you start a master-eligible node, you can provide this setting on the command line or in the elasticsearch.yml file. After the cluster has formed, remove this setting from each node’s configuration. It should not be set for master-ineligible nodes, master-eligible nodes joining an existing cluster, or when restarting one or more nodes.
  • It is technically sufficient to set cluster.initial_master_nodes on a single master-eligible node in the cluster, and only to mention that single node in the setting’s value, but this provides no fault tolerance before the cluster has fully formed. It is therefore better to bootstrap using at least three master-eligible nodes, each with a cluster.initial_master_nodes setting containing all three nodes

IMPORTANT

You must set cluster.initial_master_nodes to the same list of nodes on each node on which it is set in order to be sure that only a single cluster forms during bootstrapping and therefore to avoid the risk of data loss.

Step #2: Now, start all the 3 fresh ES servers.

Step #3: Once all three ES are UP and the cluster is formed (check logs for cluster formation).                    Go to any one of the node ESN_home/bin and execute the command:
              ./elasticsearch-setup-passwords interactive
              Provide the passwords (keep it same for all services)

NOTE: Step #3 has to be followed on any one of the cluster nodes, no need to perform it on every node.

Step #4: Once the passwords are set, you can shut down all the nodes.

OPTIONAL: The below Step #5 is to be followed if you do not have any signed CA certificate, but if you have then copy that certificate to ESN_Home/bin/ directory and jump to Step #6.

BELOW STEP i.e. Step #5 To be performed on any 1 of the nodes and not required on others. 

Step #5: Go to ESN_home/bin and execute below command:
              ./elasticsearch-certutil ca
              (It will ask for a name, just press enter and keep the default name i.e. elastic-stack-ca.p12 . Then, it will ask for the password, provide a password & Press Enter. Now CA has been generated.)

Step #6: In the same bin folder(as in Step5) execute below command
               ./elasticsearch-certutil cert --ca elastic-stack-ca.p12
               (It will ask for the password, provide the password which was given in Step #5 and press enter. It will ask for Desired Output file, just press enter to keep the default file name i.e. elastic-certificates.p12)

Here, I have used elastic-stack-ca.p12 certificate, but you can use your signed CA certificate. Please provide the password when prompted.

Step #7: The certificate generated in Step #6 i.e. elastic-certificates.p12 will be present in ESN_Home/ directory. Copy this file i.e. elastic-certificates.p12 to all the Nodes EsN_home/conf, EsN+1_home/conf, EsN+2_home/conf directory.

Step #8: This step is to be followed on EVERY Node individually

               Go to ESN_Home/bin/ and execute the below command
               ./elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
               (It will ask for password, provide the password which was generated in Step #6 and press enter.)

               Now, execute below command at the same location as above
               ./elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
               
(It will ask for password, provide the password which was generated in Step #6 and press enter.)

Step #9: Add the below properties in EVERY node ESN_home/config/elasticsearch.yml file 

xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate 
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

Step #10: Now start the nodes one by one, once all the Nodes are UP and running, Go to browser and access the nodes http://ESN_ip:9200, it will prompt for username and password. Enter the credentials as generated in Step #3 and you will be able to see Elasticsearch Details after that.

 

Configuring Liferay DXP + Elasticsearch with Native User Auth Enabled

Till now, we have successfully enabled User authentication on Elasticsearch Service. Let's move on to Integrate this with Liferay. There are two ways to do it - One via UI i.e. Liferay Control Panel>Search>Elasticsearch. Second(preferrable) is via Elasticsearch config file in osgi/configs file.

Create a file with name com.liferay.portal.search.elasticsearch7.configuration.ElasticsearchConfiguration.config

Open the above-created file and add the below parameters:

authenticationEnabled=B"true"
clusterName="LiferayElasticsearchCluster"
networkHostAddresses=[\
  "http://nodeN_ip:9200",\
  "http://nodeN+1_ip:9200",\
  "http://nodeN+2_ip:9200"\
]
operationMode="REMOTE"
productionModeEnabled=B"true"
username="elastic"
password="***********"

Save the File and Exit.

Now if Liferay is UP, then shut it down and copy the above-created config file to Liferay_Home/osgi/configs/ directory

Please Note: nodeN_ip, nodeN+1_ip, nodeN+2_ip are the Elasticsearch nodes IPs. For the field password, please provide the password which was generated in Step #3.

Now, delete osgi/state, liferay_home/work/, tomcat/temp and tomcat/work directory and start the Liferay Service.

Once the above steps are done. Go to Liferay Control Panel> Search and check in active connections all the Elasticsearch nodes are getting reflected.

Kudos, we have successfully configured Liferay with Elasticsearch Native Authentication.