GridGain Developers Hub

Security Guide: Configuring SSL/TLS/HTTPS

Senior Software Engineer
May 16, 2022

Introduction

GridGain’s distributed processing allows fast calculations and data queries by sending data between nodes, thin clients, and other applications connected to the system. However, transmitting data is done in plain text and may not be safe for your organization’s most sensitive data. Hence, it is essential to have a data security strategy in place.

This guide explains how to use SSL/TLS protocols to provide a secure connection among all nodes, thin clients, and HTTPs clients (REST, Web Console).

Configuration and Preparation

This example uses the following applications:

Item Version

GridGain

8.7.X

GridGain Web Console

old version (<8.7.7) and new version (20XX.XX.XX)

Security Protocol Version

TLSv1.2

OpenSSL

1.1.1

JDK

openjdk version 11

The following algorithms may be supported https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#sslcontext-algorithms. However, you should check the JAVA release documentation for your implementation to see if these algorithms are supported. By default, JAVA 11 supports the following protocols:

  • TLSv1

  • TLSv1.1

  • TLSv1.2

For this example, we will assume that by default GridGain supports only these three protocols when started with JAVA 11.

To obtain an SSL certificate from a certificate authority (CA), you need to generate a certificate signing request (CSR). A CSR consists mainly of the public key of a key pair and some additional information. Both of these components are inserted into the certificate when it is signed.

Let’s create a certificate authority to sign certificates for GridGain nodes keys by using the following steps:

  1. Generate a CSR and a private key:

    openssl req -new -newkey rsa:2048 -nodes -config ca_key.conf -out ca.csr -keyout ca.key
    The following options are used here:
    • -newkey rsa:2048 - key should be 2048-bit, used algorithm is RSA

    • -nodes - private key should not be encrypted with a passphrase

    • -new - CSR is being generated

    The command will prompt the following questions:

    Question Response

    Country Name (2 letter code)

    The two-letter country code where your company is legally located.

    State or Province Name (full name)

    The state/province where your company is legally located.

    Locality Name (e.g., city)

    The city where your company is legally located.

    Organization Name (e.g., company)

    Your company’s legally registered name (e.g., YourCompany, Inc.).

    Organizational Unit Name (e.g., section)

    The name of your department within the organization. (You can leave this option blank; simply press Enter.)

    Common Name (e.g., server FQDN)

    The fully-qualified domain name (FQDN) (e.g., www.example.com).

    Email Address

    Your email address. (You can leave this option blank; simply press Enter.)

    A challenge password

    Leave this option blank (simply press Enter).

    An optional company name

    Leave this option blank (simply press Enter).

    After this command the ca.csr and ca.key files will be generated.

  2. Generate the SSL certificate:

    openssl x509 -trustout -signkey ca.key -req -in ca.csr -out ca.pem
    The following options are used here:
    • -x509 - -req will create self-signed cerificate

    • -days 365 - certificate will be valid for 365 days

    • -signkey - shows which key will be used

    • -in - which CSR will be used

    • -out - path to the generated certificate

    After this command the ca.pem file will be generated. This is the self-sign certificate of the new CA. We can now use it to sign certificates. Note that other applications will not accept such certificates on HTTPS since anybody could have signed it; but it’s secure for nodes if we don’t lose ca.key.

  3. Put the generated certificate into a Java key store:

    keytool -deststorepass ${PASS} -noprompt  -import -file ca.pem -alias CertificateAuthority -keystore trust.jks
    The following options are used here:
    • -import - new certificate should be added to keystore

    • -file - which certificate should be added to keystore

    • -keystore - which keystore will be used

    • -alias - some unique name which will be associated with current certificate

    After setting the password, the trust.jks file will be generated. Note that every node may have their own primary key, which should be also signed by our CA.

  4. Prepare the configuration file (ca.cnf):

    cat << EOF > ca.cnf
    [ ca ]
    default_ca = CertificateAuthority
    
    [ CertificateAuthority ]
    certificate = ./ca.pem
    database = ./index.txt
    private_key = ./ca.key
    new_certs_dir = ./
    default_md = sha256
    policy = policy_match
    serial = ./serial
    default_days = 365
    
    [policy_match]
    commonName = supplied
    EOF

    Here index.txt and serial files should be generated:

    touch index.txt
    echo 01 > serial

    Now we are ready to configure SSL in the GridGain cluster. Make sure that you have all the following files:

    ca.conf  ca.csr  ca.key  ca.pem  index.txt  serial  trust.jks
  5. Use the following script to generate the certificates for your GridGain cluster:

    #!/usr/bin/env bash
    
    set -x
    
    # Certificates password.
    PASS=qwerty
    
    # Server.
    SERVER_DN="CN=localhost,OU=ID,O=GG,L=Hursley,S=Hants,C=GB"
    
    # Client.
    CLIENT_DN="CN=client.com,OU=Qs,O=GG,L=WEWe,S=Asda,C=GB"
    
    # Cleanup.
    rm -vf node.*
    rm -vf client.*
    rm -vf wc.*
    rm -vf ca.*
    rm -vf in*
    rm -vf seri*
    rm -vf trust*
    rm -vf *pem
    rm -vf *cnf
    rm -vf *conf
    
    # ca key config.
    cat << EOF > ca_key.conf
    [req]
    prompt                 = no
    distinguished_name     = dn
    req_extensions         = req_ext
    [ dn ]
    countryName            = US
    stateOrProvinceName    = New York
    localityName           = New York
    organizationName       = GridGain
    commonName             = localhost
    organizationalUnitName = IT
    emailAddress           = node@test.local
    [ req_ext ]
    subjectAltName         = @alt_names
    [ alt_names ]
    DNS.1                  = localhost
    EOF
    
    # ca configuration file
    cat << EOF > ca.cnf
    [ ca ]
    default_ca = CertificateAuthority
    
    [ CertificateAuthority ]
    certificate = ./ca.pem
    database = ./index.txt
    private_key = ./ca.key
    new_certs_dir = ./
    default_md = sha256
    policy = policy_match
    serial = ./serial
    default_days = 365
    
    [policy_match]
    commonName = supplied
    EOF
    
    # webconsole configuration file
    cat << EOF > wc.conf
    [req]
    prompt                 = no
    distinguished_name     = dn
    req_extensions         = req_ext
    [ dn ]
    countryName            = RU
    stateOrProvinceName    = Russia
    localityName           = Moscow
    organizationName       = GridGain
    commonName             = localhost
    organizationalUnitName = IT
    emailAddress           = wc@test.local
    [ req_ext ]
    subjectAltName         = @alt_names
    [ alt_names ]
    DNS.1                  = localhost
    IP.1                   = 127.0.0.1
    EOF
    
    touch index.txt
    echo 01 > serial
    
    # Generate CA
    openssl req -new -newkey rsa:2048 -nodes -config ca_key.conf -out ca.csr -keyout ca.key
    openssl x509 -trustout -signkey ca.key -req -in ca.csr -out ca.pem
    keytool -deststorepass ${PASS} -noprompt  -import -file ca.pem -alias CertificateAuthority -keystore trust.jks
    
    # Generate node certificates
    keytool -genkey -keyalg RSA -keysize 2048 -alias node -deststorepass ${PASS} -keystore node.jks -noprompt \
     -dname ${SERVER_DN} \
     -storepass ${PASS} \
     -keypass ${PASS}
    keytool -deststorepass ${PASS} -certreq -alias node -file node.csr -keystore node.jks
    openssl ca -batch -config ca.cnf -out node.pem -infiles node.csr
    keytool -deststorepass ${PASS} -import -alias ca -keystore node.jks -file ca.pem -noprompt
    keytool -deststorepass ${PASS} -import -alias node -keystore node.jks -file node.pem -noprompt
    keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore node.jks -destkeystore node.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias node -destalias node -noprompt
    openssl pkcs12 -in node.p12 -out ca_odbc.pem -passin pass:${PASS} -nodes
    
    # Generate Client cerificates
    keytool -genkey -keyalg RSA -keysize 2048 -alias client -deststorepass ${PASS} -keystore client.jks -noprompt \
     -dname ${CLIENT_DN} \
     -storepass ${PASS} \
     -keypass ${PASS}
    keytool -deststorepass ${PASS} -certreq -alias client -file client.csr -keystore client.jks
    openssl ca -batch -config ca.cnf -out client.pem -infiles client.csr
    keytool -deststorepass ${PASS} -import -alias ca -keystore client.jks -file ca.pem -noprompt
    keytool -deststorepass ${PASS} -import -alias client -keystore client.jks -file client.pem -noprompt
    keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore client.jks -destkeystore client.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias client -destalias client -noprompt
    openssl pkcs12 -in client.p12 -out client.pem -passin pass:${PASS} -nodes
    
    # Generate web console cerificates
    openssl genrsa -des3 -passout pass:${PASS} -out wc.key 1024
    openssl req -new -passin pass:${PASS} -key wc.key -config wc.conf -out wc.csr
    openssl x509 -req -days 365 -in wc.csr -CA ca.pem -CAkey ca.key -set_serial 01 -extensions req_ext -extfile wc.conf -out wc.crt
    openssl pkcs12 -export -in wc.crt -inkey wc.key -passin pass:${PASS} -certfile wc.crt -out wc.p12 -passout pass:${PASS}
    keytool -importkeystore -srckeystore wc.p12 -srcstoretype PKCS12 -destkeystore wc.jks -deststoretype JKS -noprompt -srcstorepass ${PASS} -deststorepass ${PASS}

    The script generates the following certificates:

    • node.jks - can be used by any cluster node

    • client.jks - can also be used by any cluster node, but we will use it for thin connections

    • client.pem and ca_odbc.pem - can be used for ODBC connection

    • wc.jks - will be used by the Web Console and Jetty

SSL/TLS for Thick Nodes

Before configuring GridGain nodes, you must generate the private key for every node. Here is an example of how this can be done for one node:

  1. Generate the primary key for a node:

    keytool -genkey -keyalg RSA -keysize 2048 -alias node -deststorepass ${PASS} -keystore node.jks -noprompt \
     -dname ${SERVER_DN} \
     -storepass ${PASS} \
     -keypass ${PASS}

    This will create the node.jks file.

  2. Generate the CSR for node:

    keytool -deststorepass ${PASS} -certreq -alias node -file node.csr -keystore node.jks

    This will create the node.csr file.

  3. Using the previously created ca.cnf, create a signed certificate for the node:

    openssl ca -batch -config ca.cnf -out node.pem -infiles node.csr

    This will create the node.pem certificate.

  4. Add both node.pem and ca.pem certificates to the Java key store:

    keytool -deststorepass ${PASS} -import -alias ca -keystore node.jks -file ca.pem -noprompt
    keytool -deststorepass ${PASS} -import -alias node -keystore node.jks -file node.pem -noprompt

    After these commands node.jks file should be created. Both node.jks and trust.jks files can now be used to configure the SSL/TLS for GridGain node. Here is the XML configuration file:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="grid.cfg"
              class="org.apache.ignite.configuration.IgniteConfiguration">
            <property name="sslContextFactory">
                <bean class="org.apache.ignite.ssl.SslContextFactory">
                    <property name="keyStoreFilePath" value="node.jks"/>
                    <property name="keyStorePassword" value="qwerty"/>
                    <property name="trustStoreFilePath" value="trust.jks"/>
                    <property name="trustStorePassword" value="qwerty"/>
                </bean>
            </property>
            <property name="connectorConfiguration">
                <bean class="org.apache.ignite.configuration.ConnectorConfiguration">
                    <property name="sslEnabled" value="true"/>
                    <property name="sslClientAuth" value="true"/>
                    <property name="jettyPath" value="jetty.xml" />
                </bean>
            </property>
            <property name="clientConnectorConfiguration">
                <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
                    <property name="host" value="127.0.0.1"/>
                    <property name="port" value="11110"/>
                    <property name="portRange" value="10"/>
                    <property name="sslEnabled" value="true"/>
                    <property name="useIgniteSslContextFactory" value="false"/>
                    <property name="sslClientAuth" value="true"/>
                    <property name="sslContextFactory">
                        <bean class="org.apache.ignite.ssl.SslContextFactory">
                            <property name="keyStoreFilePath" value="node.jks"/>
                            <property name="keyStorePassword" value="qwerty"/>
                            <property name="trustStoreFilePath" value="trust.jks"/>
                            <property name="trustStorePassword" value="qwerty"/>
                        </bean>
                    </property>
                </bean>
            </property>
            <property name="discoverySpi">
                <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                    <property name="ipFinder">
                        <bean
                            class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                            <property name="addresses">
                                <list>
                                    <value>127.0.0.1:47500..47510</value>
                                </list>
                            </property>
                        </bean>
                    </property>
                </bean>
            </property>
            <property name="communicationSpi">
                <bean
                    class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
                    <property name="localPort" value="48100"/>
                    <property name="localPortRange" value="10"/>
                    <property name="socketWriteTimeout" value="300000"/>
                </bean>
            </property>
            <property name="pluginConfigurations">
                <bean class="org.gridgain.grid.configuration.GridGainConfiguration"/>
            </property>
        </bean>
    </beans>
  5. Now start the nodes and make sure to add -Djdk.tls.client.protocols=TLSv1.2 JVM option to tell JVM that we are going to use TLS > 1.2.

Now you can take a look at the logs:

[19:02:58] Security status [authentication=off, tls/ssl=on]

You can see now that TLS/SSL is working. Note that TLS/SSL does not provide any authorization; it only provides secure messaging between nodes (authentication).

Let’s check what happens if you add a client without correct certificates:

  • Client node without SslContextFactory

    Caused by: class org.apache.ignite.spi.IgniteSpiException: Unable to establish secure connection. Was remote cluster configured with SSL? [rmtAddr=/127.0.0.1:47500, errMsg="Failed to deserialize object with given class loader: sun.misc.Launcher$AppClassLoader@18b4aac2"]
  • Client node with incorrect certificate

    Server:
    
    [19:11:19] Failed to initialize connection (missing SSL configuration on remote node?) [rmtAddr=/127.0.0.1]
    [19:16:45] Failed to initialize connection (missing SSL configuration on remote node?) [rmtAddr=/127.0.0.1]
    
    Client:
    
    [19:16:59] Failed to connect to any address from IP finder (will retry to join topology every 2000 ms; change 'reconnectDelay' to configure the frequency of retries): [/127.0.0.1:47500, /127.0.0.1:47501, /127.0.0.1:47502, /127.0.0.1:47503, /127.0.0.1:47504, /127.0.0.1:47505, /127.0.0.1:47506, /127.0.0.1:47507, /127.0.0.1:47508, /127.0.0.1:47509]

When everything is configured correctly, you will see that both nodes have discovered each other:

[19:23:32] Ignite node started OK (id=f0969bc7, instance name=client)
[19:23:32] Topology snapshot [ver=2, locNode=f0969bc7, servers=1, clients=1, state=ACTIVE, CPUs=4, offheap=6.4GB, heap=15.0GB]

This method can be used by cluster thick nodes and clients (that can use IgniteConfiguration):

  • GridGain servers (Java, .Net, C++)

  • GridGain clients (Java, .Net, C++)

  • Visor GUI in external mode

  • Ignite Jdbc Driver

  • Web agent for Web Console

Following sections describe how to configure SSL/TLS for thin clients (ODBC/JDBC) and HTTP connections (REST, Web Console).

SSL/TLS for Thin Clients (ODBC/JDBC)

To use SSL/TLS for communication between your GridGain cluster and thin clients, you will need to configure the ClientConnectorConfiguration bean in your nodes' XML configuration, like so:

<property name="clientConnectorConfiguration">
    <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
        <property name="host" value="127.0.0.1"/>
        <property name="port" value="11110"/>
        <property name="portRange" value="10"/>
        <property name="sslEnabled" value="true"/>
        <property name="useIgniteSslContextFactory" value="false"/>
        <property name="sslClientAuth" value="true"/>
        <property name="sslContextFactory">
            <bean class="org.apache.ignite.ssl.SslContextFactory">
                <property name="keyStoreFilePath" value="node.jks"/>
                <property name="keyStorePassword" value="qwerty"/>
                <property name="trustStoreFilePath" value="trust.jks"/>
                <property name="trustStorePassword" value="qwerty"/>
            </bean>
        </property>
    </bean>
</property>

Thin JDBC Client

Ignite thin JDBC driver allows you to use secure socket communication to provide a secure connection between JDBC driver and GridGain node (includes the initial handshake).

Here is an example of how to create a secure thin JDBC connection:

Ignite ignite = Ignition.start("server.xml");

ignite.cluster().active(true);

// Register JDBC driver.
Class.forName("org.apache.ignite.IgniteJdbcThinDriver");

// Open the JDBC connection.
try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:11110?" +
    "sslMode=require&" +
    "sslClientCertificateKeyStoreUrl=" + pathToClientJks + "&" +
    "sslClientCertificateKeyStorePassword=" + clientPassword + "&" +
    "sslTrustCertificateKeyStoreUrl=" + pathToTrustStoreJks + "&" +
    "sslTrustCertificateKeyStorePassword=" + trustorePassword)) {
    conn.createStatement().executeQuery("select 1");

    System.out.println("Done");
}
catch (SQLException e) {
    e.printStackTrace();
}
The following properties are used here:
  • sslMode - enables SSL connection

    Available modes - require: SSL protocol is enabled on the client. Only SSL connection is available. disable: SSL protocol is disabled on the client. Only plain connection is supported.

  • sslClientCertificateKeyStoreUrl - URL of the client key store file

  • sslClientCertificateKeyStorePassword - client key store password

  • sslTrustCertificateKeyStoreUrl - URL of the trust store file

  • sslTrustCertificateKeyStorePassword - trust store password

You can find other JDBC parameters in the documentation here: https://www.gridgain.com/docs/latest/developers-guide/SQL/JDBC/jdbc-driver

Thin ODBC Client

Since an ODBC connection can’t be started with Java, JKS can’t be used. In case if you have generated two JKS for server node and client node, then you can prepare the required keys and certificates using the following OpenSSL commands from created files:

  • node.jks will be used by server node that will be used for ODBC connection

  • client.jks will be used by ODBC clients..

# Extracting server certificate into PEM file. This is going to be our CA file for the ODBC client.
keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore node.jks -destkeystore node.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias node -destalias node -noprompt
openssl pkcs12 -in node.p12 -out ca_odbc.pem -passin pass:${PASS} -nodes

# Extracting client certificate and key into PEM file. This is going to be our private credentials file for the ODBC client.
keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore client.jks -destkeystore client.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias client -destalias client -noprompt
openssl pkcs12 -in client.p12 -out client.pem -passin pass:${PASS} -nodes

Now we are ready to make the ODBC connection using following connection string:

DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=PUBLIC;SSL_MODE=require;SSL_KEY_FILE=client.pem;SSL_CERT_FILE=client.pem;SSL_CA_FILE=ca_odbc.pem;

You can read more about the ODBC connection string and its parameters here: https://www.gridgain.com/docs/latest/developers-guide/SQL/ODBC/connection-string-dsn

HTTPS for REST

Ignite Web console and REST can also use a secured connection to cluster. In this case, we will need to set up -Dhttps.protocols=TLSv1.2 and configure the Jetty https server, as well as perform following additional steps:

  1. Prepare the configuration file for generating of the certificates:

    cat << EOF > wc.conf
    [req]
    prompt                 = no
    distinguished_name     = dn
    req_extensions         = req_ext
    [ dn ]
    countryName            = RU
    stateOrProvinceName    = Russia
    localityName           = Moscow
    organizationName       = GridGain
    commonName             = localhost
    organizationalUnitName = IT
    emailAddress           = wc@test.local
    [ req_ext ]
    subjectAltName         = @alt_names
    [ alt_names ]
    DNS.1                  = localhost
    IP.1                   = 127.0.0.1
    EOF

    It’s important to have the same CN (or alt_names) as used in the server. Otherwise, the SSL handshake can fail.

  2. Generate the private key and certificate for web console:

    openssl genrsa -des3 -passout pass:${PASS} -out wc.key 1024
    openssl req -new -passin pass:${PASS} -key wc.key -config wc.conf -out wc.csr
    openssl x509 -req -days 365 -in wc.csr -CA ca.pem -CAkey ca.key -set_serial 01 -extensions req_ext -extfile wc.conf -out wc.crt
    openssl pkcs12 -export -in wc.crt -inkey wc.key -passin pass:${PASS} -certfile wc.crt -out wc.p12 -passout pass:${PASS}
    keytool -importkeystore -srckeystore wc.p12 -srcstoretype PKCS12 -destkeystore wc.jks -deststoretype JKS -noprompt -srcstorepass ${PASS} -deststorepass ${PASS}
  3. Prepare the Jetty configuration file for HTTPS support:

    openssl genrsa -des3 -passout pass:${PASS} -out wc.key 1024
    openssl req -new -passin pass:${PASS} -key wc.key -config wc.conf -out wc.csr
    openssl x509 -req -days 365 -in wc.csr -CA ca.pem -CAkey ca.key -set_serial 01 -extensions req_ext -extfile wc.conf -out wc.crt
    openssl pkcs12 -export -in wc.crt -inkey wc.key -passin pass:${PASS} -certfile wc.crt -out wc.p12 -passout pass:${PASS}
    keytool -importkeystore -srckeystore wc.p12 -srcstoretype PKCS12 -destkeystore wc.jks -deststoretype JKS -noprompt -srcstorepass ${PASS} -deststorepass ${PASS}
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    Copyright (C) GridGain Systems. All Rights Reserved.
    _________        _____ __________________        _____
    __  ____/___________(_)______  /__  ____/______ ____(_)_______
    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
    -->
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
    <Configure id="Server" class="org.eclipse.jetty.server.Server">
        <Arg name="threadPool">
            <!-- Default queued blocking thread pool -->
            <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
                <Set name="minThreads">10</Set>
                <Set name="maxThreads">200</Set>
            </New>
        </Arg>
        <New id="httpsCfg" class="org.eclipse.jetty.server.HttpConfiguration">
            <Set name="secureScheme">https</Set>
            <Set name="securePort">
                <SystemProperty name="IGNITE_JETTY_PORT" default="8443" />
            </Set>
            <Set name="sendServerVersion">true</Set>
            <Set name="sendDateHeader">true</Set>
            <Call name="addCustomizer">
                <Arg>
                    <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
                </Arg>
            </Call>
        </New>
        <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
            <Set name="keyStorePath">wc.jks</Set>
            <Set name="keyStorePassword">qwerty</Set>
            <Set name="keyManagerPassword">qwerty</Set>
            <Set name="trustStorePath">trust.jks</Set>
            <Set name="trustStorePassword">qwerty</Set>
        </New>
        <Call name="addConnector">
            <Arg>
                <New class="org.eclipse.jetty.server.ServerConnector">
                    <Arg>
                        <Ref refid="Server" />
                    </Arg>
                    <Arg>
                        <Array type="org.eclipse.jetty.server.ConnectionFactory">
                            <Item>
                                <New class="org.eclipse.jetty.server.SslConnectionFactory">
                                    <Arg>
                                        <Ref refid="sslContextFactory" />
                                    </Arg>
                                    <Arg>http/1.1</Arg>
                                </New>
                            </Item>
                            <Item>
                                <New class="org.eclipse.jetty.server.HttpConnectionFactory">
                                    <Arg>
                                        <Ref refid="httpsCfg" />
                                    </Arg>
                                </New>
                            </Item>
                        </Array>
                    </Arg>
                    <!--
                        Note that in order to override local host and port values,
                        system properties must have names IGNITE_JETTY_HOST and
                        IGNITE_JETTY_PORT accordingly.
                    -->
                    <Set name="host">
                        <SystemProperty name="IGNITE_JETTY_HOST" default="0.0.0.0" />
                    </Set>
                    <Set name="port">
                        <SystemProperty name="IGNITE_JETTY_PORT" default="8443" />
                    </Set>
                    <Set name="idleTimeout">30000</Set>
                    <Set name="reuseAddress">true</Set>
                </New>
            </Arg>
        </Call>
        <Set name="handler">
            <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
                <Set name="handlers">
                    <Array type="org.eclipse.jetty.server.Handler">
                        <Item>
                            <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection" />
                        </Item>
                    </Array>
                </Set>
            </New>
        </Set>
        <Set name="stopAtShutdown">false</Set>
    </Configure>
  4. Add the following dependency to your pom.xml file:

    <dependency>
        <groupId>org.gridgain</groupId>
        <artifactId>ignite-rest-http</artifactId>
        <version>${ignite.version}</version>
    </dependency>
  5. Add the path for Jetty configuration into connectorConfiguration:

    <property name="connectorConfiguration">
        <bean class="org.apache.ignite.configuration.ConnectorConfiguration">
            <property name="sslEnabled" value="true"/>
            <property name="sslClientAuth" value="true"/>
            <property name="jettyPath" value="jetty.xml" />
        </bean>
    </property>
  6. After configuring the HTTPS Jetty web server, you can run the following REST command in your browser:

    https://localhost:8443/ignite?cmd=version

    If you see an output similar to the one below, then HTTPS was configured correctly.

    {"successStatus":0,"error":null,"sessionToken":null,"response":"8.7.X"}

SSL/TLS for Monitoring Tools

Visor GUI

Visor GUI provides real-time monitoring and management capabilities for various features and functionalities provided by GridGain. Currently, this tool is deprecated because it does not support JAVA 9+, but you still can find it in binary sources and run it under JAVA 8.

Visor GUI can work in two modes:

  • Internal mode - In this mode, Visor GUI starts a daemon node that connects to the cluster and communicates with it using the standard GridGain API. A configuration file should be provided to the Visor when trying to establish a connection to the cluster.

  • External mode - In this mode, Visor GUI connects to the cluster via a REST client using a unique REST API protocol, which is implemented and supported on the GridGain side. When using this mode, you need to provide Visor GUI with an address and port of one of the nodes in the cluster. The default port used by all the nodes is 11211.

The internal mode can be secured if you provide SslContextFactory(as described above for thick Java client). Additionally, you should enable SSL/TLS for external connections, like so:

<property name="connectorConfiguration">
    <bean class="org.apache.ignite.configuration.ConnectorConfiguration">
        <property name="sslEnabled" value="true"/>
        <property name="sslClientAuth" value="true"/>
        <property name="jettyPath" value="jetty.xml" />
    </bean>
</property>

The external mode requires setting the path to keystore and truststore:

Sunset
Sunset

Visor CLI

Visor Command Line Interface provides scriptable monitoring capabilities for Ignite. It can be used to get statistics about nodes, caches, and tasks in the grid. General details about the topology showing various metrics and node configuration properties can also be viewed here. Visor CLI also allows you to start and stop remote nodes.

To securely connect Visor CLI to the cluster, enable the external SSL/TLS connections in the XML configuration of the client node, like so:

<property name="sslContextFactory">
    <bean class="org.apache.ignite.ssl.SslContextFactory">
        <property name="keyStoreFilePath" value="node.jks"/>
        <property name="keyStorePassword" value="qwerty"/>
        <property name="trustStoreFilePath" value="trust.jks"/>
        <property name="trustStorePassword" value="qwerty"/>
    </bean>
</property>

Use the following steps to start Visor CLI:

  1. Set the IGNITE_HOME variable to folder with your GridGain binaries

  2. Copy your client.xml with configured sslContextFactory to IGNITE_HOME/config folder. It will help you to see this file in comand line interface.

  3. Run $IGNITE_HOME/bin/ignitevisorcmd.sh.

  4. Write open.

  5. Choose your configuration file from the list.

  6. Visor CLI will be started.

SSL/TLS for Old Stand-alone Web Console

In some scenarios, containerized deployment using Docker might not be available or desirable. For example, some organizations may prefer to manage deployment using virtual or cloud machine images (e.g., .vmx or .ami images), or deploy on bare metal. To meet such infrastructure policies, you can deploy GridGain Web Console directly on the host operating system using a pre-built ZIP package.

You can read more about the current deployment here - https://www.gridgain.com/docs/web-console/latest/deploying-web-console

GridGain Web Console can be secured in the following ways:

  • Between the cluster and the web agent

  • Between the web agent and the backend of the Web Console

  • Between the backend of the Web Console and clients (browsers)

Below you can find how to secure the Web Console for these cases. All required parts were created in the sections above. So, here are the required steps:

  1. Download the archive and unzip somewhere

  2. Start the standalone web console over HTTPS

    gridgain-web-console-win.exe --server:ssl true --server:key  wc.key --server:cert  wc.crt --server:ca ca.pem --server:passphrase "qwerty" --server:host localhost
  3. Go to https://localhost:80/ and create a new user.

  4. Download the agent from web console and unzip it.

  5. Go to user information and obtain the security token.

  6. Run the web agent as follows (here we can use the JKS files generated in the sections above):

    java -jar ./ignite-web-agent-8.7.X.jar --node-key-store node.jks --node-key-store-password qwerty --node-trust-store trust.jks --node-trust-store-password qwerty --server-key-store wc.jks --server-key-store-password qwerty --server-trust-store trust.jks --server-trust-store-password qwerty -t tc7q1LcmBWSrr6dPPVWq -s https://localhost:80 -n https://localhost:8443
    The following options are used in the command:
    • node-key-store and node-key-store-password - trust store and password used for secured connection to GridGain cluster (as a client node)

    • server-key-store and server-key-store-password - trust store and password used for secured connection to web console (the same key should be used in Jetty configuration)

    • -t - the security token or tokens for all your users that will work through this web agent

    • -s - the address of Web Console

    • -n - the address of the Jetty server

If your web agent does not work with self-signed certificates, then try to add the -Dtrust.all=true option.

Additionally, you can set the SSL/TLS connection between the Web Console backend and the clients that try to connect, for example - browsers, by adding the following options to the start command of the Web Console:

  • --server:requestCert true - Set to true to specify whether a server should request a certificate from a connecting client

  • --server:rejectUnauthorized true - If not false a server automatically reject clients with invalid certificates

When you set these options, you can import your certificate to the browser, like so:

Sunset

SSL/TLS for New Stand-alone Web Console

The new version of GridGain Web Console contains several significant changes from the previous versions:

  • Isolated GridGain nodes are used instead of MongoDB

  • The way it should be configured is changed; Now it supports related configuration files, YAML configuration, or environment variables.

So some steps should be changed for the new stand-alone version. Here are the new steps:

  1. Download the archive and unzip it.

  2. Create a application.properties file in the root of the archive.

  3. Add the following properties to this file:

    server.port=443
    server.ssl.protocol=TLS
    server.ssl.key-store-type=JKS
    server.ssl.key-store=node.jks
    server.ssl.key-store-password=qwerty
    server.ssl.trust-store-type=JKS
    server.ssl.trust-store=trust.jks
    server.ssl.trust-store-password=qwerty
  4. Run the following command:

    bash web-console.sh
  5. The Web Console will be started at https://localhost:443. Go to Web Console UI and download the web agent. Also, you should go to your user configuration and copy your security token.

    Sunset
  6. Unzip the web agent archive and run following to start it:

    bash ignite-web-console-agent.sh --node-key-store node.jks --node-key-store-password qwerty --node-trust-store trust.jks --node-trust-store-password qwerty --server-key-store wc.jks --server-key-store-password qwerty --server-trust-store trust.jks --server-trust-store-password qwerty -t 9fae7710-3a6c-475f-84f6-2c760eed67a6 -s https://localhost:443 -n https://localhost:8443

    If your web agent does not work with self-signed certificates, then try to add the -Dtrust.all=true option.

Configuration for SSL/TLS connection between the Web Console backend and clients that try to connect, for example - browsers, was also changed. For the new Web Console, you should add the following option to the application.properties file:

server.ssl.client-auth=need

SSL/TLS for Old Docker Web Console

For docker installation, you should

  1. Perform all the previously described steps first:

    • Generate certificates

    • Start secure cluster with correct Jetty configuration

  2. Prepare Nginx configuration web-console.conf file:

    server {
    listen 443 ssl;
    ssl_certificate     wc.crt;
    ssl_certificate_key wc.key;
    ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    set $ignite_console_dir /data/www;
    set $maintenance /data/www/maintenance.file;
    root $ignite_console_dir;
    location / {
        if (-f $maintenance) {
            return 503;
        }
         try_files $uri @prerender;
    }
    location @prerender {
        proxy_set_header X-Prerender-Token LXewR5QLHlsYArAX9gKm;
        set $prerender 0;
        if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
           set $prerender 1;
        }
        if ($args ~ "_escaped_fragment_") {
           set $prerender 1;
        }
        if ($http_user_agent ~ "Prerender") {
           set $prerender 0;
        }
        if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
            set $prerender 0;
        }
        resolver 8.8.8.8;
        if ($prerender = 0) {
            rewrite .* /index.html break;
        }
    }
    location /api/v1 {
        proxy_set_header Host staging-console.gridgain.com;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://backend:3000;
    }
    location /socket.io {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://backend:3000;
    }
    location /browsers {
        proxy_http_version 1.1;
        proxy_pass http://backend:3000;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
    location /agents {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://backend:3000;
    }
    location /google03ebf4d63a28f673.html {
        alias /etc/nginx/conf.d/staging-search-console-google.html;
    }
    location /yandex_7a49d3c578f9668e.html {
        alias /etc/nginx/conf.d/staging-webmaster-yandex.html;
    }
    location /robots.txt {
        alias /etc/nginx/conf.d/robots.txt;
    }
    location ~* \.(?:css|js)$ {
      expires 15m;
      access_log off;
      add_header Cache-Control "public";
    }
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /data/www;
    }
    }
    server {
        listen 80;
        server_name _;
        return 301 https://$host$request_uri;
    }
  3. Start mongo_db in your docker:

    docker run -d --name=console_db mongo:3.4
  4. Start the backend part of the Web Console. Note that you should have access to this docker repository from your GridGain sales manager or support team.

    docker run -d --name=console_backend --link console_db:mongodb -e "mongodb_url=mongodb://mongodb/console" -e "server_host=0.0.0.0"
    -v docker\\mongo:/data gridgain/web-console-backend:8.7.X

SSL/TLS for New Docker Web Console

The main difference here will be related to Mongo DB support. It’s not required anymore. Generally, the steps will be the same.

You can find all the commands here: