Configuring Apache and security settings

November 14, 2023

Integrating with an Apache HTTP Web Server

In some production setups, you will often need to redirect the port 8181 and 9443 to the default HTTP (80) and HTTPS (443) ports. To do so, you will need to setup an Apache HTTP web server in front of jCustomer.

Here is an example configuration using mod_proxy and the DNS name "unomi.apache.org":

In your jCustomer package directory, in <cxs-install-dir>/etc/unomi.custom.system.properties:

org.apache.unomi.cluster.public.address=https://unomi.apache.org
org.apache.unomi.cluster.internal.address=http://192.168.1.1:8181

 and you will also need to change the following property:

org.apache.unomi.profile.cookie.domain=apache.org

Main virtual host config:

<VirtualHost *:80>
        Include /var/www/vhosts/unomi.apache.org/conf/common.conf
</VirtualHost>
<IfModule mod_ssl.c>
    <VirtualHost *:443>
        Include /var/www/vhosts/unomi.apache.org/conf/common.conf 
        SSLEngine on
        SSLCertificateFile /var/www/vhosts/unomi.apache.org/conf/ssl/24d5b9691e96eafa.crt 
        SSLCertificateKeyFile /var/www/vhosts/unomi.apache.org/conf/ssl/apache.org.key 
        SSLCertificateChainFile /var/www/vhosts/unomi.apache.org/conf/ssl/gd_bundle-g2-g1.crt
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
            SSLOptions +StdEnvVars
        </Directory>
        BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
    </VirtualHost>
</IfModule>

common.conf:

ServerName unomi.apache.org
ServerAdmin webmaster@apache.org
DocumentRoot /var/www/vhosts/unomi.apache.org/html
CustomLog /var/log/apache2/access-unomi.apache.org.log combined
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
<Directory /var/www/vhosts/unomi.apache.org/html>
    Options FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
</Directory>
<Location /cxs>
    Order deny,allow
    deny from all
    allow from <jahia-dx-ip-address>
</Location>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]
ProxyPreserveHost On
ProxyPass /server-status !
ProxyPass /robots.txt !
RewriteCond %{HTTP_USER_AGENT} Googlebot [OR]
RewriteCond %{HTTP_USER_AGENT} msnbot [OR]
RewriteCond %{HTTP_USER_AGENT} Slurp
RewriteRule ^.* - [F,L]
ProxyPass / http://localhost:8181/ connectiontimeout=20 timeout=300 ttl=120
ProxyPassReverse / http://locahost:8181 
Warning: Make sure you protected the /cxs from external accesses. Only the Jahia server should be able to use it directly.

Security aspects

Administrator username and password

The jCustomer REST API is protected using JAAS authentication and using Basic or Digest HTTP auth. By default, the login/password for the REST API full administrative access is "karaf/karaf". It is strongly recommended that you change the default username and password as soon as possible. This can be done by modifying the following configuration file <cxs-install-dir>/etc/unomi.custom.system.properties:

org.apache.unomi.security.root.password=${env:UNOMI_ROOT_PASSWORD:-karaf}

In-depth details for the JAAS security in the CXS’ Karaf server can be found at: http://karaf.apache.org/manual/latest/security.

Warning: do not leave the default karaf/karaf password in the user.properties file when putting a system in production !

SSL certificate

The jCustomer package is configured with a default SSL certificate. You can change it by following these steps: 1. Replace the existing keystore in file <cxs-install-dir>/etc/keystore by your own certificate. See How to configure SSL for details. 2. Update the keystore and certificate password in <cxs-install-dir>/etc/unomi.custom.system.properties file:

org.osgi.service.http.secure.enabled = true
org.ops4j.pax.web.ssl.keystore=${karaf.etc}/keystore
org.ops4j.pax.web.ssl.password=changeme
org.ops4j.pax.web.ssl.keypassword=changeme
org.osgi.service.http.port.secure=9443

You should now have SSL setup on jCustomer with your certificate, and you can test it by trying to access it on port 9443.

Securing a production environment

Before going live with a project, you should absolutely read the following sections that will help you setup a proper secure environment for running your jCustomer.

Install and configure a firewall (port numbers)

You should setup a firewall around your cluster of jCustomers and/or ElasticSearch nodes. If you have an application-level firewall you should only allow the following connections open to the whole world:

  • http://localhost:8181/context.js
  • http://localhost:8181/eventcollector
  • http://localhost:8181/client

All other ports and urls should not be accessible to the world. For your jCustomer client applications (such as the jExperience), you will need to make the following ports accessible to the client machine:

  • 8181 - jCustomer HTTP port
  • 9443 - jCustomer HTTPS port For your jCustomers and for any standalone ElasticSearch nodes you will need to open the following ports for proper node-to-node communication:
  • 5700 - 5800 Hazelcast cluster protocol
  • 9200 - ElasticSearch REST API
  • 9300 - ElasticSearch TCP transport

Of course, any ports listed here are the default ports configured in each server, you may adjust them if needed in the "Network And HTTP" section of the <elasticsearch-install-dir>/config/elasticsearch.yml file or in the <cxs-install-dir>/etc property files.

Note that if you need a temporary SSL certificate for a pre-production environment for example, you can generate one using Certbot (https://github.com/certbot/certbot) until a proper one is delivered from IT.

Secure Elasticsearch

It is recommended when going live to restrict the automatic index creation to only indexes that are created by jCustomer (and/or your other application using indices in the same ES cluster). In order to do that you should add the following line to your <es-install-dir>/config/elasticsearch.yml file:

action.auto_create_index: +context*,-*

Also we recommend to follow industry recommended best practices for securing ElasticSearch. You may find more valuable recommendations here:

Setup a (SSL) proxy

As an alternative to an application-level firewall, you could also route all traffic to jCustomer through a proxy and use it to filter any communication.

A relatively straight-forward way to do this is to use an Apache HTTP server in front of the public-facing jCustomer endpoint. You could even setup this proxy connection to use SSL-only and proxy to the http://UNOMI_HOST:8181/ port. Configuration could look something like this:

Listen 443
NameVirtualHost unomi.org:443
<VirtualHost unomi.org:443>
    SSLEngine On
    # Set the path to SSL certificate
    # Usage: SSLCertificateFile /path/to/cert.pem
    SSLCertificateFile /etc/apache2/ssl/file.pem
    ProxyPass / http://UNOMI_HOST:8181/
    ProxyPassReverse / http://UNOMI_HOST:8181/
</VirtualHost>

This way all the traffic to the http://unomi.org:443 endpoint will be secured using SSL, and then will proxy the requests to jCustomer on the HTTP port 8181.

Search robots and crawlers

By default jCustomer includes a /robots.txt file with the following content:

User-agent: *
Disallow: /

The setting does not allow search bots and crawlers to access the content. On top of it you could block the known search bots on your front-end Apache HTTPD server using the following rewrite rules:

RewriteCond %{HTTP_USER_AGENT} Googlebot [OR]
RewriteCond %{HTTP_USER_AGENT} msnbot [OR]
RewriteCond %{HTTP_USER_AGENT} Slurp
RewriteRule ^.* - [F,L]