This is an automated email from the ASF dual-hosted git repository.

ipolyzos pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fluss.git


The following commit(s) were added to refs/heads/main by this push:
     new bdbbbce94 [helm] Enable SASL authenticated connection to Zookeeper 
nodes (#2700)
bdbbbce94 is described below

commit bdbbbce945ae4884ac72f45b602dfe9e4a681876
Author: Muhammet Orazov <[email protected]>
AuthorDate: Sun Mar 29 17:14:43 2026 +0200

    [helm] Enable SASL authenticated connection to Zookeeper nodes (#2700)
    
    ---
    
    Co-authored-by: Lorenzo Affetti <[email protected]>
---
 helm/templates/_security.tpl                       |  91 +++++++-
 helm/templates/configmap.yaml                      |   6 +
 helm/templates/secret-jaas-config.yaml             |  17 +-
 helm/templates/sts-coordinator.yaml                |   8 +-
 helm/templates/sts-tablet.yaml                     |   8 +-
 helm/tests/security_test.yaml                      | 231 +++++++++++++++++++++
 helm/values.yaml                                   |   9 +
 website/docs/install-deploy/deploying-with-helm.md |  27 +++
 8 files changed, 385 insertions(+), 12 deletions(-)

diff --git a/helm/templates/_security.tpl b/helm/templates/_security.tpl
index 210a35746..f3684fcd4 100644
--- a/helm/templates/_security.tpl
+++ b/helm/templates/_security.tpl
@@ -29,6 +29,28 @@ Usage:
 {{- $mechanism -}}
 {{- end -}}
 
+{{/*
+Returns the ZooKeeper SASL authentication mechanism value.
+Allowed mechanism values: '', 'plain'
+Usage:
+  include "fluss.security.zookeeper.sasl.mechanism" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.mechanism" -}}
+{{- $sasl := .Values.security.zookeeper.sasl | default (dict) -}}
+{{- $mechanism := lower (default "" $sasl.mechanism) -}}
+{{- $mechanism -}}
+{{- end -}}
+
+{{/*
+Returns true if ZooKeeper SASL authentication is enabled (mechanism is 
non-empty).
+Usage:
+  include "fluss.security.zookeeper.sasl.enabled" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.enabled" -}}
+{{- $mechanism := include "fluss.security.zookeeper.sasl.mechanism" . -}}
+{{- if ne $mechanism "" -}}true{{- end -}}
+{{- end -}}
+
 {{/*
 Returns true if any of the listeners uses SASL based authentication mechanism 
('plain' for now).
 Usage:
@@ -117,6 +139,56 @@ Usage:
 {{- end -}}
 {{- end -}}
 
+{{/*
+Validates that ZooKeeper SASL mechanism is valid.
+Returns an error message if invalid, empty string otherwise.
+Usage:
+  include "fluss.security.zookeeper.sasl.validateMechanism" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.validateMechanism" -}}
+{{- $allowedMechanisms := list "" "plain" -}}
+{{- $mechanism := include "fluss.security.zookeeper.sasl.mechanism" . -}}
+{{- if not (has $mechanism $allowedMechanisms) -}}
+  {{- print "security.zookeeper.sasl.mechanism must be empty or: plain" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Validates that ZooKeeper SASL loginModuleClass is not empty when ZK SASL is 
enabled.
+Returns an error message if invalid, empty string otherwise.
+Usage:
+  include "fluss.security.zookeeper.sasl.validateLoginModuleClass" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.validateLoginModuleClass" -}}
+{{- if and (include "fluss.security.zookeeper.sasl.enabled" .) (not 
.Values.security.zookeeper.sasl.plain.loginModuleClass) -}}
+  {{- print "security.zookeeper.sasl.plain.loginModuleClass must not be empty 
when security.zookeeper.sasl.mechanism is plain" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Validates that ZooKeeper SASL username is not empty when ZK SASL is enabled.
+Returns an error message if invalid, empty string otherwise.
+Usage:
+  include "fluss.security.zookeeper.sasl.validateUsername" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.validateUsername" -}}
+{{- if and (include "fluss.security.zookeeper.sasl.enabled" .) (not 
.Values.security.zookeeper.sasl.plain.username) -}}
+  {{- print "security.zookeeper.sasl.plain.username must not be empty when 
security.zookeeper.sasl.mechanism is plain" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Validates that ZooKeeper SASL password is not empty when ZK SASL is enabled.
+Returns an error message if invalid, empty string otherwise.
+Usage:
+  include "fluss.security.zookeeper.sasl.validatePassword" .
+*/}}
+{{- define "fluss.security.zookeeper.sasl.validatePassword" -}}
+{{- if and (include "fluss.security.zookeeper.sasl.enabled" .) (not 
.Values.security.zookeeper.sasl.plain.password) -}}
+  {{- print "security.zookeeper.sasl.plain.password must not be empty when 
security.zookeeper.sasl.mechanism is plain" -}}
+{{- end -}}
+{{- end -}}
+
 {{/*
 Returns the default internal SASL username based on the release name.
 Usage:
@@ -153,6 +225,17 @@ Usage:
 {{- .Values.security.internal.sasl.plain.password | default (include 
"fluss.security.sasl.plain.internal.defaultPassword" .) -}}
 {{- end -}}
 
+{{/*
+Returns true if JAAS configuration is required, either by listeners using SASL 
protocol or ZooKeeper SASL enablement.
+Usage:
+  include "fluss.security.jaas.required" .
+*/}}
+{{- define "fluss.security.jaas.required" -}}
+{{- if or (include "fluss.security.sasl.enabled" .) (include 
"fluss.security.zookeeper.sasl.enabled" .) -}}
+{{- true -}}
+{{- end -}}
+{{- end -}}
+
 {{/*
 Returns a warning if the internal SASL user is using auto-generated 
credentials.
 Usage:
@@ -179,6 +262,10 @@ Usage:
 {{- $errMessages := list -}}
 {{- $errMessages = append $errMessages (include 
"fluss.security.sasl.validateMechanisms" .) -}}
 {{- $errMessages = append $errMessages (include 
"fluss.security.sasl.validateClientPlainUsers" .) -}}
+{{- $errMessages = append $errMessages (include 
"fluss.security.zookeeper.sasl.validateMechanism" .) -}}
+{{- $errMessages = append $errMessages (include 
"fluss.security.zookeeper.sasl.validateLoginModuleClass" .) -}}
+{{- $errMessages = append $errMessages (include 
"fluss.security.zookeeper.sasl.validateUsername" .) -}}
+{{- $errMessages = append $errMessages (include 
"fluss.security.zookeeper.sasl.validatePassword" .) -}}
 
 {{- $errMessages = without $errMessages "" -}}
 {{- $errMessage := join "\n" $errMessages -}}
@@ -202,8 +289,8 @@ Usage:
 {{/*
 Returns the SASL JAAS config name.
 Usage:
-  include "fluss.security.sasl.configName" .
+  include "fluss.security.jaas.configName" .
 */}}
-{{- define "fluss.security.sasl.configName" -}}
+{{- define "fluss.security.jaas.configName" -}}
 {{ include "fluss.fullname" . }}-sasl-jaas-config
 {{- end -}}
diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml
index 66f3eb095..c4574b6c1 100644
--- a/helm/templates/configmap.yaml
+++ b/helm/templates/configmap.yaml
@@ -53,3 +53,9 @@ data:
     {{- end }}
 
     {{- end }}
+
+    ### Zookeeper
+
+    {{- if (include "fluss.security.zookeeper.sasl.enabled" .) }}
+    zookeeper.client.config.path: /etc/fluss/conf/zookeeper-client.properties
+    {{- end }}
diff --git a/helm/templates/secret-jaas-config.yaml 
b/helm/templates/secret-jaas-config.yaml
index 6ed411acb..436a2fbb2 100644
--- a/helm/templates/secret-jaas-config.yaml
+++ b/helm/templates/secret-jaas-config.yaml
@@ -16,7 +16,7 @@
 # limitations under the License.
 #
 
-{{ if (include "fluss.security.sasl.plain.enabled" .) }}
+{{ if (include "fluss.security.jaas.required" .) }}
 {{- $internalMechanism := include "fluss.security.listener.mechanism" (dict 
"context" .Values "listener" "internal") -}}
 {{- $clientMechanism := include "fluss.security.listener.mechanism" (dict 
"context" .Values "listener" "client") -}}
 {{- $internalUsername := include "fluss.security.sasl.plain.internal.username" 
. -}}
@@ -24,12 +24,13 @@
 apiVersion: v1
 kind: Secret
 metadata:
-  name: {{ include "fluss.security.sasl.configName" . }}
+  name: {{ include "fluss.security.jaas.configName" . }}
   labels:
     {{- include "fluss.labels" . | nindent 4 }}
 type: Opaque
 stringData:
   jaas.conf: |
+{{- if (include "fluss.security.sasl.plain.enabled" .) }}
 {{- if eq $internalMechanism "plain" }}
     internal.FlussServer {
        org.apache.fluss.security.auth.sasl.plain.PlainLoginModule required
@@ -49,4 +50,16 @@ stringData:
 {{- end }};
     };
 {{- end }}
+{{- end }}
+{{- if (include "fluss.security.zookeeper.sasl.enabled" .) }}
+    ZookeeperClient {
+       {{ .Values.security.zookeeper.sasl.plain.loginModuleClass }} required
+       username="{{ .Values.security.zookeeper.sasl.plain.username }}"
+       password="{{ .Values.security.zookeeper.sasl.plain.password }}";
+    };
+{{- end }}
+{{- if (include "fluss.security.zookeeper.sasl.enabled" .) }}
+  zookeeper-client.properties: |
+    zookeeper.sasl.clientconfig=ZookeeperClient
+{{- end }}
 {{- end -}}
diff --git a/helm/templates/sts-coordinator.yaml 
b/helm/templates/sts-coordinator.yaml
index c443e230f..7a6774b28 100644
--- a/helm/templates/sts-coordinator.yaml
+++ b/helm/templates/sts-coordinator.yaml
@@ -60,7 +60,7 @@ spec:
               valueFrom:
                 fieldRef:
                   fieldPath: status.hostIP
-            {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+            {{- if (include "fluss.security.jaas.required" .) }}
             - name: FLUSS_ENV_JAVA_OPTS
               value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
             {{- end }}
@@ -105,7 +105,7 @@ spec:
               mountPath: /opt/conf
             - name: data
               mountPath: /tmp/fluss/data
-            {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+            {{- if (include "fluss.security.jaas.required" .) }}
             - name: sasl-config
               mountPath: /etc/fluss/conf
               readOnly: true
@@ -118,10 +118,10 @@ spec:
         - name: data
           emptyDir: {}
         {{- end }}
-        {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+        {{- if (include "fluss.security.jaas.required" .) }}
         - name: sasl-config
           secret:
-            secretName: {{ include "fluss.security.sasl.configName" . }}
+            secretName: {{ include "fluss.security.jaas.configName" . }}
         {{- end }}
   {{- if .Values.coordinator.storage.enabled }}
   volumeClaimTemplates:
diff --git a/helm/templates/sts-tablet.yaml b/helm/templates/sts-tablet.yaml
index 1ffe1af31..b58fc49f8 100644
--- a/helm/templates/sts-tablet.yaml
+++ b/helm/templates/sts-tablet.yaml
@@ -56,7 +56,7 @@ spec:
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
-            {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+            {{- if (include "fluss.security.jaas.required" .) }}
             - name: FLUSS_ENV_JAVA_OPTS
               value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
             {{- end }}
@@ -102,7 +102,7 @@ spec:
               mountPath: /opt/conf
             - name: data
               mountPath: /tmp/fluss/data
-            {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+            {{- if (include "fluss.security.jaas.required" .) }}
             - name: sasl-config
               mountPath: /etc/fluss/conf
               readOnly: true
@@ -115,10 +115,10 @@ spec:
         - name: data
           emptyDir: {}
         {{- end }}
-        {{- if (include "fluss.security.sasl.plain.enabled" .) }}
+        {{- if (include "fluss.security.jaas.required" .) }}
         - name: sasl-config
           secret:
-            secretName: {{ include "fluss.security.sasl.configName" . }}
+            secretName: {{ include "fluss.security.jaas.configName" . }}
         {{- end }}
   {{- if .Values.tablet.storage.enabled }}
   volumeClaimTemplates:
diff --git a/helm/tests/security_test.yaml b/helm/tests/security_test.yaml
index f6d67f508..d73e2604e 100644
--- a/helm/tests/security_test.yaml
+++ b/helm/tests/security_test.yaml
@@ -282,3 +282,234 @@ tests:
       - matchRegex:
           path: spec.template.spec.containers[0].command[2]
           pattern: '>> \$FLUSS_HOME/conf/server\.yaml'
+
+---
+
+suite: zookeeper-sasl-enabled-secret
+templates:
+  - templates/secret-jaas-config.yaml
+tests:
+  - it: renders ZookeeperClient JAAS block when ZK SASL is enabled
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - hasDocuments:
+          count: 1
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'ZookeeperClient\s*\{'
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'username="zk-user"'
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'password="zk-pass"'
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'DigestLoginModule required'
+      - matchRegex:
+          path: stringData["zookeeper-client.properties"]
+          pattern: 'zookeeper\.sasl\.clientconfig=ZookeeperClient'
+  - it: renders both SASL and ZK JAAS blocks when both are enabled
+    set:
+      security.internal.sasl.mechanism: plain
+      security.internal.sasl.plain.username: internal-user
+      security.internal.sasl.plain.password: internal-pass
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'internal\.FlussServer\s*\{'
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'ZookeeperClient\s*\{'
+  - it: does not render SASL listener blocks when only ZK SASL is enabled
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - notMatchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'internal\.FlussServer\s*\{'
+      - notMatchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'FlussClient\s*\{'
+
+---
+
+suite: zookeeper-sasl-enabled-statefulset
+templates:
+  - templates/sts-coordinator.yaml
+  - templates/sts-tablet.yaml
+  - templates/configmap.yaml
+tests:
+  - it: renders JAAS env var and mounts secret volume for coordinator when ZK 
SASL is enabled
+    template: templates/sts-coordinator.yaml
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: FLUSS_ENV_JAVA_OPTS
+            value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: sasl-config
+            secret:
+              secretName: RELEASE-NAME-fluss-sasl-jaas-config
+  - it: renders JAAS env var and mounts secret volume for tablet when ZK SASL 
is enabled
+    template: templates/sts-tablet.yaml
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: FLUSS_ENV_JAVA_OPTS
+            value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: sasl-config
+            secret:
+              secretName: RELEASE-NAME-fluss-sasl-jaas-config
+  - it: renders zookeeper client config path in configmap when ZK SASL is 
enabled
+    template: templates/configmap.yaml
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - matchRegex:
+          path: data["server.yaml"]
+          pattern: 'zookeeper\.client\.config\.path: 
/etc/fluss/conf/zookeeper-client\.properties'
+
+---
+
+suite: zookeeper-sasl-custom-login-module
+templates:
+  - templates/secret-jaas-config.yaml
+tests:
+  - it: renders custom login module class in ZookeeperClient JAAS block
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+      security.zookeeper.sasl.plain.loginModuleClass: 
"com.example.CustomLoginModule"
+    asserts:
+      - matchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'com\.example\.CustomLoginModule required'
+      - notMatchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'DigestLoginModule'
+
+---
+
+suite: zookeeper-sasl-disabled
+templates:
+  - templates/secret-jaas-config.yaml
+  - templates/sts-coordinator.yaml
+  - templates/sts-tablet.yaml
+  - templates/configmap.yaml
+tests:
+  - it: does not render ZookeeperClient JAAS block when ZK SASL is disabled
+    template: templates/secret-jaas-config.yaml
+    set:
+      security.internal.sasl.mechanism: plain
+      security.internal.sasl.plain.username: internal-user
+      security.internal.sasl.plain.password: internal-pass
+    asserts:
+      - hasDocuments:
+          count: 1
+      - notMatchRegex:
+          path: stringData["jaas.conf"]
+          pattern: 'ZookeeperClient\s*\{'
+      - isNull:
+          path: stringData["zookeeper-client.properties"]
+  - it: does not render JAAS secret when neither SASL nor ZK SASL is enabled
+    template: templates/secret-jaas-config.yaml
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: does not render JAAS env var or volume mount for coordinator when ZK 
SASL is disabled
+    template: templates/sts-coordinator.yaml
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: FLUSS_ENV_JAVA_OPTS
+            value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
+      - notContains:
+          path: spec.template.spec.volumes
+          content:
+            name: sasl-config
+          any: true
+  - it: does not render JAAS env var or volume mount for tablet when ZK SASL 
is disabled
+    template: templates/sts-tablet.yaml
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: FLUSS_ENV_JAVA_OPTS
+            value: 
"-Djava.security.auth.login.config=/etc/fluss/conf/jaas.conf"
+      - notContains:
+          path: spec.template.spec.volumes
+          content:
+            name: sasl-config
+          any: true
+  - it: does not render zookeeper client config path in configmap when ZK SASL 
is disabled
+    template: templates/configmap.yaml
+    asserts:
+      - notMatchRegex:
+          path: data["server.yaml"]
+          pattern: 'zookeeper\.client\.config\.path'
+
+---
+
+suite: zookeeper-sasl-validation
+templates:
+  - templates/NOTES.txt
+tests:
+  - it: fails when loginModuleClass is empty and ZK SASL is enabled
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+      security.zookeeper.sasl.plain.loginModuleClass: ""
+    asserts:
+      - failedTemplate:
+          errorMessage: "VALUES 
VALIDATION:\nsecurity.zookeeper.sasl.plain.loginModuleClass must not be empty 
when security.zookeeper.sasl.mechanism is plain"
+  - it: fails when ZK SASL is enabled but username is empty
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - failedTemplate:
+          errorMessage: "VALUES 
VALIDATION:\nsecurity.zookeeper.sasl.plain.username must not be empty when 
security.zookeeper.sasl.mechanism is plain"
+  - it: fails when ZK SASL is enabled but password is empty
+    set:
+      security.zookeeper.sasl.mechanism: plain
+      security.zookeeper.sasl.plain.username: zk-user
+    asserts:
+      - failedTemplate:
+          errorMessage: "VALUES 
VALIDATION:\nsecurity.zookeeper.sasl.plain.password must not be empty when 
security.zookeeper.sasl.mechanism is plain"
+  - it: fails for invalid zookeeper mechanism value
+    set:
+      security.zookeeper.sasl.mechanism: bogus
+      security.zookeeper.sasl.plain.username: zk-user
+      security.zookeeper.sasl.plain.password: zk-pass
+    asserts:
+      - failedTemplate:
+          errorMessage: "VALUES VALIDATION:\nsecurity.zookeeper.sasl.mechanism 
must be empty or: plain"
diff --git a/helm/values.yaml b/helm/values.yaml
index 63c11e724..219fbc75c 100644
--- a/helm/values.yaml
+++ b/helm/values.yaml
@@ -75,6 +75,15 @@ security:
         username: ""
         password: ""
 
+  zookeeper:
+    sasl:
+      # "" | plain
+      mechanism: ""
+      plain:
+        username: ""
+        password: ""
+        loginModuleClass: 
"org.apache.fluss.shaded.zookeeper3.org.apache.zookeeper.server.auth.DigestLoginModule"
+
 metrics:
   reporters: ""
   prometheus:
diff --git a/website/docs/install-deploy/deploying-with-helm.md 
b/website/docs/install-deploy/deploying-with-helm.md
index ba9a8932b..f7e543934 100644
--- a/website/docs/install-deploy/deploying-with-helm.md
+++ b/website/docs/install-deploy/deploying-with-helm.md
@@ -202,6 +202,15 @@ If the internal SASL username or password is left empty, 
the chart automatically
 
 It is recommended to set these explicitly in production.
 
+#### ZooKeeper SASL Parameters
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `security.zookeeper.sasl.mechanism` | ZooKeeper SASL mechanism (`""`, 
`plain`) | `""` |
+| `security.zookeeper.sasl.plain.username` | ZooKeeper SASL username | `""` |
+| `security.zookeeper.sasl.plain.password` | ZooKeeper SASL password | `""` |
+| `security.zookeeper.sasl.plain.loginModuleClass` | JAAS login module class 
for ZooKeeper | 
`org.apache.fluss.shaded.zookeeper3.org.apache.zookeeper.server.auth.DigestLoginModule`
 |
+
 ### Metrics Parameters
 
 | Parameter | Description | Default |
@@ -325,6 +334,24 @@ security:
         password: internal-password
 ```
 
+### Enabling ZooKeeper SASL Authentication
+
+You can enable ZooKeeper ensemble SASL authentication, with the following 
values in the Fluss Helm chart:
+
+```yaml
+security:
+  zookeeper:
+    sasl:
+      mechanism: plain
+      plain:
+        username: fluss-zk-user
+        password: fluss-zk-password
+```
+
+The `security.zookeeper.sasl.plain.username` and 
`security.zookeeper.sasl.plain.password` fields are required when 
`security.zookeeper.sasl.mechanism` is set to `plain`.
+
+ZooKeeper SASL can be enabled independently or together with the listeners 
SASL authentication.
+
 ### Metrics and Monitoring
 
 When `metrics.reporters` is set, the chart adds the following `server.yaml` 
configuration entries:

Reply via email to