Configure TLS with Platform Operator

Learn how to secure Hazelcast cluster with TLS and Hazelcast Platform Operator.

Overview

In this tutorial, you’ll do the following:

  • Create a Kubernetes Secret with a TLS certificate and key

  • Deploy a Hazelcast cluster with TLS (mTLS) encryption enforced between members

  • Deploy Management Center to monitor your Hazelcast cluster

  • Connect to your cluster using TLS to encrypt member-to-client network traffic

The tutorial should take approximately 10 minutes to complete.

Prerequisites

Before you begin, make sure that you have:

Create Kubernetes secret with TLS certificate and key

  1. Generate TLS certificate and key in PEM format using OpenSSL

    openssl req -x509 -sha256 -nodes -days 3650 -subj '/CN=example' -addext "subjectAltName=DNS:example" -newkey rsa:2048 -outform pem -keyout example.key -out example.crt -addext "extendedKeyUsage=serverAuth,clientAuth"
  2. Create Kubernetes secret with TLS certificate and key

    kubectl create secret generic example \
      --from-file=tls.crt=example.crt \
      --from-file=tls.key=example.key
    You can also set ca.crt to create a truststore. For more information, see TLS.

Deploy Hazelcast cluster with TLS

  1. Create a secret with your Hazelcast Enterprise License

    kubectl create secret generic hazelcast-license-key --from-literal=license-key=<hz-license-key>
  2. Create the Hazelcast cluster with TLS configured

    kubectl apply -f - <<EOF
    apiVersion: hazelcast.com/v1alpha1
    kind: Hazelcast
    metadata:
      name: hazelcast
    spec:
      clusterSize: 3
      licenseKeySecretName: hazelcast-license-key
      tls:
        secretName: example
      exposeExternally:
        type: Smart
        discoveryServiceType: LoadBalancer
        memberAccess: LoadBalancer
    EOF
  3. Check cluster status:

    kubectl get hazelcast hazelcast
    NAME        STATUS    MEMBERS
    hazelcast   Running   3/3
  4. Fetch external addresses of the cluster:

    kubectl get hazelcastendpoint --selector="app.kubernetes.io/instance=hazelcast"
    NAME            TYPE        ADDRESS
    hazelcast       Discovery   35.184.21.18:5701
    hazelcast-0     Member      35.188.131.33:5701
    hazelcast-1     Member      34.122.242.55:5701
    hazelcast-2     Member      35.194.44.37:5701
    hazelcast-wan   WAN         35.184.21.18:5710

Deploy Management Center

Enabling TLS for a Hazelcast cluster adds an essential layer of security to protect data during communication. When TLS is enabled, all clients, including the Management Center, must be configured with the appropriate TLS certificates to establish a secure connection with the Hazelcast cluster.

Apply the Management Center custom resource:

kubectl apply -f - <<EOF
apiVersion: hazelcast.com/v1alpha1
kind: ManagementCenter
metadata:
  name: managementcenter
spec:
  repository: 'hazelcast/management-center'
  licenseKeySecretName: hazelcast-license-key
  externalConnectivity:
    type: LoadBalancer
  hazelcastClusters:
    - address: hazelcast
      name: dev
      tls:
        secretName: example
EOF

Connect to Hazelcast cluster over TLS

  1. Open the examples folder to access all sample clients:

    cd hazelcast-platform-operator-tls

    The sample code (excluding CLC) for this tutorial is in the docs/modules/ROOT/examples/ directory.

  2. Configure the Hazelcast client with the TLS certificate:

    • CLC

    • Java

    • NodeJS

    • Go

    • Python

    CLC must be installed in your system. See the CLC installation instructions.

    Add the cluster config to the CLC:

    clc config add hz cluster.name=dev cluster.address=<EXTERNAL-IP> ssl.enabled=true ssl.server=example ssl.ca-path=<PATH/TO/example.crt>
    package com.hazelcast;
    
    import com.hazelcast.client.HazelcastClient;
    import com.hazelcast.client.config.ClientConfig;
    import com.hazelcast.config.SSLConfig;
    import com.hazelcast.core.HazelcastInstance;
    
    import java.util.Properties;
    
    public class example {
      public static void main(String[] args) throws Exception {
        ClientConfig config = new ClientConfig();
        config.getNetworkConfig().addAddress("<EXTERNAL-IP>");
    
        Properties clientSSLProps = new Properties();
        clientSSLProps.setProperty("trustStore", "example.jks");
        clientSSLProps.setProperty("trustStorePassword", "hazelcast");
        config.getNetworkConfig().setSSLConfig(new SSLConfig()
          .setEnabled(true)
          .setProperties(clientSSLProps));
    
        HazelcastInstance client = HazelcastClient.newHazelcastClient(config);
        System.out.println("Successful connection!");
      }
    }
    'use strict';
    
    const { Client } = require('hazelcast-client');
    
    const clientConfig = {
      network: {
        clusterMembers: [
          '<EXTERNAL-IP>'
        ],
        ssl: {
          enabled: true,
          sslOptionsFactoryProperties: {
            caPath: 'example.crt',
            servername: 'example',
          }
        }
      }
    };
    
    (async () => {
      try {
        const client = await Client.newHazelcastClient(clientConfig);
        console.log('Successful connection!');
      } catch (err) {
        console.error('Error occurred:', err);
      }
    })();
    package main
    
    import (
    	"context"
    	"crypto/tls"
    	"fmt"
    
    	"github.com/hazelcast/hazelcast-go-client"
    	"github.com/hazelcast/hazelcast-go-client/cluster"
    )
    
    func main() {
    	var clusterConfig cluster.Config
    	clusterConfig.Network.SetAddresses("<EXTERNAL-IP>")
    	clusterConfig.Discovery.UsePublicIP = true
    	clusterConfig.Network.SSL.Enabled = true
    	clusterConfig.Network.SSL.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
    
    	ctx := context.Background()
    	config := hazelcast.Config{Cluster: clusterConfig}
    	client, err := hazelcast.StartNewClientWithConfig(ctx, config)
    	if err != nil {
    		panic(err)
    	}
    	fmt.Println("Successful connection!", client)
    }
    import logging
    
    import hazelcast
    
    logging.basicConfig(level=logging.INFO)
    
    client = hazelcast.HazelcastClient(
        cluster_members=["<EXTERNAL-IP>"],
        use_public_ip=True,
        ssl_enabled=True,
        ssl_cafile="example.crt",
    )
    
    print("Successful connection!", flush=True)
  3. Build and run the Hazelcast client example:

    • CLC

    • Java

    • NodeJS

    • Go

    • Python

    clc -c hz map size
    cd java
    mvn package
    java -jar target/*.jar
    cd nodejs
    npm install
    npm start
    cd go
    go run example.go
    cd python
    pip install -r requirements.txt
    python example.py

Clean Up

To clean up the created resources remove the all Custom Resources and secrets:

kubectl delete $(kubectl get hazelcast,managementcenter -o name)
kubectl delete secret example

Summary

In this tutorial, you’ve learned how to:

  • Create a Kubernetes Secret with a TLS certificate and key

  • Deploy a Hazelcast cluster with TLS (mTLS) encryption enforced between members

  • Deploy Management Center to monitor your Hazelcast cluster

  • Connect to your cluster using TLS to encrypt member-to-client network traffic