Skip to content

Lab: Enabling TLS

Task 1: Creating a Certificate

Use the certificate CR to create a new TLS certificate.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cluster-1-tls
spec:
  isCA: false
  commonName: Cluster 1
  secretName: cluster-1-tls-managed

  privateKey:
    algorithm: ECDSA
    size: 256
  issuerRef:
    name: root-ca-issuer
    kind: ClusterIssuer
    group: cert-manager.io

  dnsNames:
    - cluster-1-kafka-bootstrap
    # replace {your namespace}
    - cluster-1-kafka-bootstrap.{your namespace}
    # replace {your namespace}
    - cluster-1-kafka-bootstrap.{your namespace}.svc
    # replace {your namespace}
    - '*.cluster-1-kafka-brokers.{your namespace}.svc'

  usages:
    - "digital signature"
    - "key encipherment"

  keystores:
    pkcs12:
      create: true
      password: changeit
      profile: Modern2023
    jks:
      create: true
      alias: client-cert
      password: changeit

Warning

Replace {your namespace} with your personal namespace (3 occurrences).

Verifying Certificates

After deploying a certificate in your namespace, you can verify its successful creation by issuing the following command:

$ kubectl get -n {your namespace} certificate
If the certificate was issued correctly, it should be displayed as Ready: True in the output table.

Task 2: Adding a TLS Listener

Modify your existing Kafka cluster by adding a internal listener to tls using TLS encryption and the TCP port 9093.

https://strimzi.io/docs/operators/latest/configuring#type-GenericKafkaListener-reference

https://strimzi.io/docs/operators/latest/configuring#property-listener-config-brokerCertChainAndKey-reference

Hint 1

By creating a certificate in the previous exercise, CertManager created a new secret containing the TLS certificate and private key. Use this secret to configure a brokerCertChainAndKey in the listener configuration.

Hint 2
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
# ...
spec:
  kafka:
    # ...
    listeners:
      - name: tlsnoauth
        port: 9093
        type: internal
        tls: true
        configuration:
          brokerCertChainAndKey:
            secretName: cluster-1-tls-managed
            certificate: tls.crt
            key: tls.key
Hint 3
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: controller
  labels:
    strimzi.io/cluster: cluster-1
spec:
  replicas: 3
  roles:
    - controller
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 50Gi
        kraftMetadata: shared
        deleteClaim: false
        class: managed-csi
  resources:
    requests:
      memory: 2Gi
      cpu: "200m"
    limits:
      memory: 2Gi
---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: broker
  labels:
    strimzi.io/cluster: cluster-1
spec:
  replicas: 3
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 100Gi
        kraftMetadata: shared
        deleteClaim: false
        class: managed-csi
  resources:
    requests:
      memory: 4Gi
      cpu: "500m"
    limits:
      memory: 4Gi
---
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: cluster-1
  annotations:
    strimzi.io/node-pools: enabled
    strimzi.io/kraft: enabled
spec:
  kafkaExporter:
      topicRegex: "^[^_].*$"
      groupRegex: "^[^_].*$"
  kafka:
    version: 4.1.0
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: true
        configuration:
          brokerCertChainAndKey:
            secretName: cluster-1-tls-managed
            certificate: tls.crt
            key: tls.key
    config:
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
      default.replication.factor: 3
      min.insync.replicas: 2
    metricsConfig:
      type: jmxPrometheusExporter
      valueFrom:
        configMapKeyRef:
          name: kafka-metrics
          key: kafka-metrics-config.yml
  entityOperator:
    topicOperator: {}
    userOperator: {}

Task 3: Test the Connection

We would like to test the TLS connection using the Kafka CLI tools within the debug container.

Step 1: Mount the Truststore to the Debug CLI Pod

To allow the JVM to access the CA certificates and use them for validation, we need to mount the truststore into our Debug CLI pod. When creating the server certificate used by the TLS listener, cert-manager also created a truststore containing the correct CA certificate within the same secret used to store the listener certificate. For simplicity, we want to mount the secret in our Debug CLI pod.

Mount the secret cluster-1-tls-managed in your pod using the path /run/secrets/ca.

Hint 1

Copy the definition of your Debug CLI deployment from a previous setup and add the volume.

Hint 2
apiVersion: apps/v1
kind: Deployment
# <...>
spec:
  # ...
  template:
    # ...
    spec:
      # ...
      containers:
        - name: kafka-otc
          # ...
          volumeMounts:
            - name:  broker-tls
              mountPath: /run/secrets/ca/
            # ...
      volumes:
        - name: broker-tls
          secret:
            secretName: cluster-1-tls-managed
        # ...
Hint 3
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-debug-cli
  labels:
    app: debug-cli
spec:
  replicas: 1
  selector:
    matchLabels:
      app: debug-cli
  template:
    metadata:
      labels:
        app: debug-cli
    spec:
      initContainers:
        - name: debug-cli-chown
          image: krassestecontainerreistry.azurecr.io/kafka-oauth-client:latest
          securityContext:
            privileged: true
            runAsUser: 0
            runAsGroup: 0
          command: [ "chown", "-R", "user:user", "/opt/user_conf" ]
          volumeMounts:
            - name: user-conf
              mountPath: /opt/user_conf
              readOnly: false
      containers:
        - name: debug-cli
          image: krassestecontainerreistry.azurecr.io/kafka-oauth-client:latest #TODO: replace ACR name
          resources:
            limits:
              cpu: 200m
              memory: 200Mi
            requests:
              cpu: 200m
              memory: 200Mi
          volumeMounts:
            - name: user-conf
              mountPath: /opt/user_conf
              readOnly: false
            - name: cluster-1-config
              mountPath: /config/cluster-1
            - name:  broker-tls
              mountPath: /run/secrets/ca/
      volumes:
        - name: user-conf
          persistentVolumeClaim:
            claimName: debug-cli-user-conf
        - name: cluster-1-config
          configMap:
            name: cluster-1-client-cfg
        - name: broker-tls
          secret:
            secretName: cluster-1-tls-managed

Step 2: Adding a Client Config

Change the values within the existing ConfigMap you set up to store the client configuration.

Add those configs:

    sasl.mechanism=PLAIN
    security.protocol=SSL
    ssl.truststore.location=/run/secrets/ca/truststore.jks
    ssl.truststore.type=JKS
    ssl.truststore.password=changeit
Hint 1

Change the existing config map and also change the bootstrap server.

Hint 2
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-1-client-cfg
data:
  client.properties: |
    bootstrap.servers=cluster-1-kafka-bootstrap.{your namespace}.svc:9093
    sasl.mechanism=PLAIN
    security.protocol=SSL
    ssl.truststore.location=/run/secrets/ca/truststore.jks
    ssl.truststore.type=JKS
    ssl.truststore.password=changeit
    parse.key=true
    key.separator=:
Hint 3

ask the trainer

Step 3: Publishing Messages

Now publish some messages to the topic test-0.

Solution

Use the new properties file and the new port 9093, we can publish some sample messages to the topic test-0. Remember to replace {your namespace} with your personal namespace.

kafka-console-producer \
    --bootstrap-server cluster-1-kafka-bootstrap.{your namespace}:9093 \
    --producer.config /config/cluster-1/client.properties \
    --topic test-0 < /opt/samples/messages_glados_still_alive.txt