Security — Kerberos, Ranger, Knox, and ACLs
This chapter describes how to configure and verify Kerberos authentication, Ranger authorization, Knox proxying, access control lists (ACLs), encryption in transit, and auditing for Apache SeaTunnel in ODP.
1. Kerberos
1.1 Kerberos configuration installed by the mpack
When you run the Ambari Kerberize wizard, Ambari creates the following Kerberos configurations on each host that runs a SeaTunnel component.
Configuration | Description |
Principal | seatunnel/<fqdn>@<REALM> |
Keytab | /etc/security/keytabs/seatunnel.service.keytab |
Keytab permissions | 0640, with ownership set to seatunnel:hadoop |
JAAS configuration | /etc/seatunnel/conf/seatunnel-jaas.conf |
JVM properties | Kerberos and ZooKeeper SASL properties for the master and worker JVMs |
Hadoop proxy-user configuration | hadoop.proxyuser.seatunnel.hosts=* and hadoop.proxyuser.seatunnel.groups=* in core-site.xml |
The params.py script generates the JAAS configuration by using values from Ambari. For more information, see section 1.3.
The Hadoop proxy-user properties provide the configuration required for future doAs impersonation support.
1.2 Verify Kerberos authentication for the SeaTunnel principal
To verify that the SeaTunnel service principal can authenticate with Kerberos, follow these steps:
- List the principals stored in the SeaTunnel keytab.
sudo klist -k /etc/security/keytabs/seatunnel.service.keytab
- Authenticate as the seatunnel user by using the service keytab.
sudo -u seatunnel kinit -kt /etc/security/keytabs/seatunnel.service.keytab \
seatunnel/$(hostname -f)@ADSRE.COM
- Verify the Kerberos ticket.
sudo -u seatunnel klist | head -5
- Default principal: seatunnel/<host>@ADSRE.COM
- A valid ticket-granting ticket (TGT): krbtgt/ADSRE.COM@ADSRE.COM
Validation status: Verified in the lab environment.
1.3 Verify that the JAAS configuration contains valid values
Verify that the JAAS configuration contains valid keytab paths and Kerberos principals.
Run the following command:
grep -E 'keyTab|principal' /etc/seatunnel/conf/seatunnel-jaas.conf
- No configuration entry contains the literal value None.
- Each keyTab entry points to an existing keytab file.
- Each principal entry contains a valid service principal in the service/host@REALM format.
Previous issue
The params.py script previously generated None values when stack_select.get_role_component_current_stack_version() returned None on hosts other than the first host.
The issue was resolved by implementing a three-level fallback mechanism:
- commandParams
- stack_select
- /usr/odp/current symbolic link resolution using readlink
For more information, see section 7 in 05-troubleshooting.md.
1.4 Verify JVM Kerberos properties
Verify that the SeaTunnel master JVM receives the required Kerberos and ZooKeeper SASL properties.
- Identify the SeaTunnel master JVM process.
JPID=$(pgrep -f 'SeaTunnelServer -r master' | head -1)
Display the JVM command-line arguments related to Kerberos and ZooKeeper SASL.
tr '\0' '\n' < /proc/$JPID/cmdline | grep -E 'java.security|zookeeper.sasl'
-Djava.security.krb5.conf=/etc/krb5.conf
-Djava.security.auth.login.config=/etc/seatunnel/conf/seatunnel-jaas.conf
-Dzookeeper.sasl.client=true
-Dzookeeper.sasl.clientconfig=Client
1.5 Verify outbound HDFS RPC authentication
Verify that the seatunnel user can authenticate with Kerberos and access HDFS.
Run the following command:
sudo -u seatunnel bash -c '
kinit -kt /etc/security/keytabs/seatunnel.service.keytab seatunnel/$(hostname -f)@ADSRE.COM
hdfs dfs -ls /tmp/seatunnel-out
'
Client cannot authenticate via:[TOKEN, KERBEROS]
- Outdated keytab: The keytab might contain outdated credentials. Regenerate the keytab by using the Ambari Kerberize wizard.
- Insufficient HDFS permissions: The seatunnel user might not have permission to access /tmp/seatunnel-out. Configure the required Ranger policies or HDFS ACLs.
For more information, see section 2, Ranger — Authorization model.
2. Ranger — Authorization model
Apache Ranger controls access to downstream resources that SeaTunnel connectors use.
Does the seatunnel user require Ranger policies?
Yes. When jobs run on the Zeta engine, the seatunnel service identity requires appropriate Ranger permissions for each downstream resource.
For Flink and Spark engines, Ranger typically evaluates permissions against the Kerberos identity of the user who submits the job, rather than the SeaTunnel service principal.
2.1 Zeta engine — SeaTunnel as the effective principal
The SeaTunnel master and worker daemons authenticate by using the seatunnel service keytab.
Jobs submitted through bin/seatunnel.sh or the POST /submit-job REST endpoint run within these JVMs.
During outbound Kerberos SASL/SSL authentication, the JVMs present the following service principal:
seatunnel/<host>@<REALM>
Configure the following permissions based on the resources that each pipeline accesses.
Ranger plugin | Resource | Required permissions |
HDFS | Sink path | read, write, execute |
Hive | Target database | select, update, create |
Kafka | Target topic and consumer group | publish, consume, describe |
HBase | Target namespace or table | read, write, create, admin |
YARN | Target queue | submit-app, admin-queue |
Note: YARN permissions apply when Flink or Spark jobs are submitted to YARN as the seatunnel user.
2.2 Flink and Spark engines — Submitter identity
The Flink and Spark connector scripts invoke their respective execution engines:
- start-seatunnel-flink-19-connector-v2.sh invokes ${FLINK_HOME}/bin/flink run.
- start-seatunnel-spark-3.5-connector-v2.sh invokes ${SPARK_HOME}/bin/spark-submit.
These processes inherit the Kerberos ticket cache of the user who invokes the script.
For example, when a user named alice runs the SeaTunnel client with a valid Kerberos ticket, Flink or Spark runs under Alice's identity. Ranger evaluates access permissions against Alice's policies instead of those assigned to seatunnel.
If the script runs as the seatunnel user, Ranger evaluates permissions against seatunnel.
Example: YARN authorization failure
The following error occurred during Flink 1.19 validation on YARN when the seatunnel user did not have the required Ranger YARN permissions:
Caused by: org.apache.hadoop.security.AccessControlException:
User seatunnel does not have permission to submit application_1789593044248_0004 to queue default
2.3 Recommended Ranger policies for the Zeta engine
If Apache Ranger Admin is installed, configure the following policies for common SeaTunnel pipelines.
Repository | Resource | User | Permissions |
cm_hdfs | /tmp/seatunnel-out/*, /user/seatunnel/* | seatunnel | read, write, execute |
cm_hdfs | /warehouse/iceberg/*, /warehouse/hudi/* | seatunnel | read, write, execute |
cm_yarn | Queue root.default | seatunnel | submit-app, admin-queue |
cm_hive | Database mytarget | seatunnel | select, update, create |
cm_kafka | Topic st_*, consumer group st_* | seatunnel | publish, consume, describe |
cm_hbase | Namespace default, table st_* | seatunnel | read, write, create, admin |
Note: The source document indicates that Ranger Admin was not deployed in the initial lab environment. These policies are recommended configurations, not validation results from that environment.
2.4 Provision Ranger users after installation
Validated September 30, 2026 · ODP 3.3.6.6-1004
After installing Ranger and starting the Ranger plugins, repository creation for HDFS, YARN, Hive, and HBase might fail with the following errors:
{"statusCode":400,"msgDesc":"Operation denied. User name: rangerlookup specified in policy does not exist in ranger admin."}
{"statusCode":400,"msgDesc":"Operation denied. User name: ambari-qa specified in policy does not exist in ranger admin."}
Cause
The source identifies two upstream issues:
- Missing rangerlookup user: The Ranger Admin database initialization process does not create the rangerlookup user. Default plugin policy templates reference this user for resource lookup, causing repository creation to fail with HTTP 400.
The relevant implementation is in ranger/security-admin/scripts/db_setup.py or the equivalent Java initialization process. - Missing policy users in Ranger: The create_ranger_repository() function in ranger_functions_v2.py does not verify that the configured policy_user exists in Ranger before creating the repository.
The default YARN service-check policy references ambari-qa. If Ambari has not synchronized this user with Ranger, YARN plugin initialization fails.
Workaround
Step 1: Create the required users in Ranger Admin
Before starting the services for the first time, create the required users.
RANGER=http://<ranger-admin>:6080
AUTH="admin:<ranger-admin-pwd>"
for u in rangerlookup ambari-qa seatunnel hdfs yarn hive hbase spark flink; do
curl -s -u "$AUTH" -H "Content-Type: application/json" -X POST \
"$RANGER/service/xusers/secure/users" \
-d "{\"name\":\"$u\",\"password\":\"User@2026\",\"firstName\":\"$u\",\"description\":\"pre-provisioned for plugin repo\",\"status\":1,\"isVisible\":1,\"userSource\":0,\"userRoleList\":[\"ROLE_USER\"]}"
done
curl -s -u "$AUTH" -H "Content-Type: application/json" -X PUT \
"$RANGER/service/xusers/users/rangerlookup" \
-d '{"name":"rangerlookup","userRoleList":["ROLE_SYS_ADMIN"]}'
Step 2: Remove the affected Ranger repository cache and restart the master component
If plugin initialization has already failed and the cache directories exist, the setup script might skip repository creation on subsequent attempts.
On the host running the affected master component, remove its Ranger cache directory:
sudo rm -rf /etc/ranger/<CLUSTER>_<component>
hadoop, yarn, hive, hbase, or kafka3.
Important: Confirm the cluster and component values before deleting the directory. The command permanently removes the specified directory.
Restart the affected master component through the Ambari REST API. The following example restarts the HDFS NameNode:
curl -u admin:admin -H "X-Requested-By: ambari" -X POST \
-d '{"RequestInfo":{"command":"RESTART","context":"ranger repo re-post","operation_level":{"level":"HOST_COMPONENT","cluster_name":"<CLUSTER>","host_name":"<host-fqdn>","service_name":"HDFS"}},
"Requests/resource_filters":[{"service_name":"HDFS","component_name":"NAMENODE","hosts":"<host-fqdn>"}]}' \
http://<ambari>:8080/api/v1/clusters/<CLUSTER>/requests
Step 3: Verify Ranger repository creation
Run the following command to list Ranger repositories:
curl -s -u "$AUTH" "$RANGER/service/public/v2/api/service" | python3 -c "
import sys,json
for s in json.load(sys.stdin):
print(s['name'], s['type'], 'enabled='+str(s['isEnabled']))
"
ODP_Titan_kafka3 kafka enabled=True
ODP_Titan_tag tag enabled=True
ODP_Titan_hadoop hdfs enabled=True
ODP_Titan_yarn yarn enabled=True
ODP_Titan_hbase hbase enabled=True
ODP_Titan_hive hive enabled=True
2.5 Add Ranger policies for the SeaTunnel user
Lab-validated procedure
When creating a Ranger policy through the REST API, the request might fail with HTTP 400 if the policy references a group that Ranger UserSync has not imported.
For example, the hadoop group might not be available until UserSync completes synchronization.
To avoid this issue, specify users directly or omit the groups field.
Create an HDFS policy
The following example grants the seatunnel user read, write, and execute permissions on the specified HDFS paths.
curl -s -u "$AUTH" -H "Content-Type: application/json" -X POST -d '{
"name":"seatunnel-write-tmp-and-warehouse",
"isEnabled":true, "service":"<CLUSTER>_hadoop",
"resources":{"path":{"values":["/tmp/seatunnel-out","/tmp/seatunnel-out/*","/warehouse","/warehouse/*","/user/seatunnel","/user/seatunnel/*"],"isExcludes":false,"isRecursive":true}},
"policyItems":[{"accesses":[{"type":"read","isAllowed":true},{"type":"write","isAllowed":true},{"type":"execute","isAllowed":true}],
"users":["seatunnel"], "delegateAdmin":false}]
}' "$RANGER/service/public/v2/api/policy"
Service | Policy requirement |
YARN | Allow seatunnel to submit applications to the default queue. |
Hive | Grant seatunnel the required permissions on the target database. |
Kafka | Allow seatunnel to publish, consume, describe, and create resources for topics matching st_*. |
HBase | Grant seatunnel the required read, write, create, and administration permissions. |
The source references complete policy payloads in docs/examples/ranger-policies/*.json.
Update an existing HBase policy
Ranger creates the default HBase policy named all - table, column-family, column during repository initialization.
Instead of creating another policy, update the existing policy to include the seatunnel user.
- Identify the existing policy ID.
POL=$(curl -s -u "$AUTH" "$RANGER/service/public/v2/api/service/<CLUSTER>_hbase/policy" \
- | python3 -c "import sys,json; [print(p['id']) for p in json.load(sys.stdin) if p['name']=='all - table, column-family, column']")
Retrieve the policy configuration.
curl -s -u "$AUTH" "$RANGER/service/public/v2/api/policy/$POL" > /tmp/p.json
Add a policy item for the seatunnel user to the policyItems array, with the required accesses.
{
"accesses": [
{
"type": "read",
"isAllowed": true
}
],
"users": ["seatunnel"],
"groups": [],
"delegateAdmin": false
- }
The read permission is illustrative. Include all required permissions before updating the policy.- Submit the updated policy.
curl -s -u "$AUTH" -H "Content-Type: application/json" -X PUT \
-d @/tmp/p.json \
- "$RANGER/service/public/v2/api/policy/$POL"
Configure SEATUNNEL_CLASSPATH for cluster-provided libraries
Some SeaTunnel connectors require libraries provided by ODP that the SeaTunnel launcher does not include in its classpath by default.
Examples include:
- Hive connector: hive-exec, hive-metastore, and libthrift.
- HBase connector: HBase client libraries.
Instead of packaging these libraries into the connector JAR files, ODP uses the SEATUNNEL_CLASSPATH environment variable.
The seatunnel-env.xml mpack configuration adds the following logic to /etc/seatunnel/conf/seatunnel-env.sh:
export SEATUNNEL_CLASSPATH="${SEATUNNEL_CLASSPATH:-}"
for _odp_lib in /usr/odp/current/hive-client/lib /usr/odp/current/hbase-client/lib; do
if [ -d "${_odp_lib}" ]; then
export SEATUNNEL_CLASSPATH="${SEATUNNEL_CLASSPATH}:${_odp_lib}/*"
fi
done
ODP also modifies bin/seatunnel.sh and bin/seatunnel-cluster.sh to append the following expression to the JVM classpath:
${SEATUNNEL_CLASSPATH:+:${SEATUNNEL_CLASSPATH}}
Verify the classpath
Run the following commands:
JPID=$(pgrep -f 'SeaTunnelServer -r master' | head -1)
tr '\0' '\n' < /proc/$JPID/cmdline | grep -A1 '^-cp$' | tail -1 | tr ':' '\n' | grep hive
/usr/odp/current/hive-client/lib/*
2.6a Kerberos _HOST substitution in connectors
ODP-specific patch
Issue
Six upstream SeaTunnel connectors pass the kerberos_principal value directly to UserGroupInformation.loginUserFromKeytab() without performing Hadoop's standard _HOST substitution through SecurityUtil.getServerPrincipal().
In a multi-host cluster, a connector configuration that specifies a principal for one host might fail when a task runs on another worker.
The worker's keytab contains only its own host principal, resulting in the following error:
LoginException: Unable to obtain password from user
Resolution
The ODP fork includes a patch in branch nightly/ODP-3.3.6.6.
The patch updates the following connector implementations:
Connector | Implementation |
HDFS | connector-file-base/.../hadoop/HadoopLoginFactory.java |
Hive JDBC | connector-jdbc/.../internal/dialect/hive/HadoopLoginFactory.java |
Hudi | connector-hudi/.../HudiUtil.java |
Kudu | connector-kudu/.../KuduUtil.java |
Hive JDBC utilities | connector-jdbc/.../HiveJdbcUtils.java |
Iceberg | connector-iceberg/.../IcebergCatalogLoader.java |
Each implementation resolves the hostname before authenticating:
String resolvedPrincipal =
SecurityUtil.getServerPrincipal(principal, InetAddress.getLocalHost().getCanonicalHostName());
UserGroupInformation.loginUserFromKeytab(resolvedPrincipal, keytabPath);
Configure the Kerberos principal
Use _HOST in the kerberos_principal property so that the same configuration works across multiple workers.
sink {
HdfsFile {
...
kerberos_principal = "seatunnel/_HOST@ADSRE.COM"
kerberos_keytab_path = "/etc/security/keytabs/seatunnel.service.keytab"
}
}
Alternative: If the patch is unavailable, create a merged keytab containing the principals for all worker hosts and distribute it to each worker.
The source identifies kadmin.local with the ktadd -norandkey option as the method for generating the merged keytab.
2.6b Proposed upstream fixes
The source identifies two changes proposed for upstream projects.
Ranger Admin initialization
Update the Ranger Admin database initialization process to create the rangerlookup user during initial setup.
Currently, Ambari creates the Kerberos principal through kerberos.json, but the corresponding Ranger Admin user record is not guaranteed to exist.
The relevant source files are:
- ranger/security-admin/scripts/db_setup.py
- ranger/security-admin/src/main/java/org/apache/ranger/patch/PatchForKafkaServiceDefUpdate_J10033.java
The second file references rangerlookup as a default policy user but does not guarantee that the user exists.
Ambari repository creation
Update create_ranger_repository() in ranger_functions_v2.py to create missing policy users before submitting the repository creation request.
The proposed implementation:
- Extracts usernames from repo_properties, including policy_user and configs.default-policy.*.policyItem.*.users.
- Calls create_ambari_admin_user() for each required user.
- Calls create_repository_urllib2() to create the repository.
Status: These changes are proposed upstream fixes, not confirmed upstream releases.
2.7 Configure native ACLs when Ranger is unavailable
If Ranger is not installed, configure native access control lists (ACLs) for the services that SeaTunnel connectors access.
Kafka authorizer configuration
By default, the ODP Kafka3 broker uses the native Kafka authorizer:
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
To enable Ranger authorization for Kafka:
- In Ambari, go to Kafka3 > Configs > Advanced kafka-broker.
- Set the following property:
authorizer.class.name=org.apache.ranger.authorization.kafka.authorizer.RangerKafkaAuthorizer
Install and configure the Ranger Kafka plugin.
Validation status: The source reports successful validation with native Kafka ACLs. Ranger authorization required the authorizer change.
Native ACL examples
Service | Configuration |
HDFS | Use hdfs dfs -chown and hdfs dfs -setfacl to configure ownership and permissions. |
Kafka | Use kafka-acls.sh to grant producer permissions and configure IdempotentWrite on the cluster. |
HBase | Use the HBase shell grant command. |
Hive | Use SQL GRANT statements. |
YARN | Configure yarn.admin.acl and queue ACLs in capacity-scheduler.xml. |
HDFS
hdfs dfs -chown seatunnel:hadoop <path>
hdfs dfs -setfacl -m user:seatunnel:rwx <path>
kafka-acls.sh --add --allow-principal User:seatunnel --producer --topic <t>
For the validated st_smoke example, see the Fake-to-Kafka procedure in 03-connectors.md.
HBase
grant "seatunnel", "RWXCA", "@<namespace>"
GRANT ALL ON DATABASE mytarget TO USER seatunnel;
The source uses the following configuration in the shared lab environment:
yarn.acl.enable=false
2.4b Identify the effective user for a SeaTunnel job
The identity used for downstream authorization depends on the execution engine and submission method.
Pattern | Submission method | Effective downstream user |
A — Service identity | Submit through Zeta as seatunnel, including the Web UI or Knox REST endpoint. | seatunnel |
B — Human submitter | Submit a Flink or Spark job from a user's authenticated shell. | The submitting user, such as alice |
C — Proxy-user impersonation | Submit through the seatunnel service with connector-level impersonation enabled. | The configured proxy user, such as alice |
Configure Ranger policies and HDFS ACLs for the effective user associated with the selected submission method.
Pattern A — Service identity
In this pattern, all pipelines authenticate to downstream services as the seatunnel user.
Run the following command:
sudo -u seatunnel bash -c '
kinit -kt /etc/security/keytabs/seatunnel.service.keytab seatunnel/$(hostname -f)@<REALM>
/usr/odp/current/seatunnel/bin/seatunnel.sh --config job.conf
'
Advantages: Centralized permission management and no need to manage individual user keytabs.
Limitation: Audit logs identify seatunnel as the actor for all pipelines, making it difficult to attribute individual operations to a human submitter.
Pattern B — Human submitter
Use this pattern when CI pipelines or individual users submit Flink or Spark jobs with their own Kerberos credentials.
For example, run the following commands as alice on a cluster edge node:
kinit alice@<REALM>
# Alternatively, authenticate with a keytab.
# kinit -kt /etc/security/keytabs/alice.headless.keytab alice
/usr/odp/current/seatunnel/bin/start-seatunnel-flink-19-connector-v2.sh \
-e run-application --target yarn-application --config /tmp/job.conf
- Flink inherits Alice's Kerberos ticket cache.
- The YARN ApplicationMaster runs under Alice's identity.
- Ranger evaluates YARN and downstream resource permissions against Alice's policies.
Prerequisites
- Create a Kerberos principal for Alice in the KDC.
- Configure an optional keytab if required.
- Ensure Alice belongs to the appropriate operating system group on the YARN NodeManager hosts, or to a group synchronized with Ranger.
- Configure Ranger policies for the YARN queue and downstream resources.
- Do not configure Hadoop proxy-user properties for direct submission unless another component requires impersonation.
Example authorization failure
Caused by: org.apache.hadoop.security.AccessControlException:
User seatunnel does not have permission to submit application_... to queue default
To resolve the issue, either grant seatunnel the required queue permissions or submit the job as an authorized user.
Pattern C — Proxy-user impersonation
In this pattern, the SeaTunnel daemon runs as seatunnel, but a connector impersonates another user for downstream operations.
For example, the connector can call UserGroupInformation.doAs() to perform HDFS operations as alice.
This allows audit logs to identify the actual user instead of attributing every operation to the service account.
Verify Hadoop proxy-user configuration
The mpack configures the following properties in core-site.xml through kerberos.json:
hadoop.proxyuser.seatunnel.hosts=*
hadoop.proxyuser.seatunnel.groups=*
Security consideration: Wildcard values permit broad impersonation. For production deployments, restrict the allowed hosts and groups according to your organization's security requirements.
Configure connector-level impersonation
The following example shows the source configuration for an HDFS sink:
sink {
HdfsFile {
...
kerberos_principal = "seatunnel/_HOST@<REALM>"
kerberos_keytab_path = "/etc/security/keytabs/seatunnel.service.keytab"
hdfs_site_path = "/etc/hadoop/conf/hdfs-site.xml"
hadoop.impersonation.enable = true
hadoop.impersonation.proxy_user = "alice"
}
}
According to the source's code inspection:
Connector | Impersonation support |
HdfsFile | Supported |
Hive sink | Supported through Hive impersonation |
JDBC | Supported through the jdbc.properties configuration |
Kafka | Not supported |
HBase | Not supported |
Kudu | Not supported |
Iceberg | Not supported |
Hudi | Not supported |
To verify connector support, inspect the connector implementation for UserGroupInformation.createProxyUser() or UGI.doAs().
Ranger policies must grant the proxy user access to the target resources, and Hadoop must allow the service identity to impersonate that user.
Verify impersonation in audit logs
The HDFS audit log should contain an entry similar to:
ugi=alice (auth:PROXY) via seatunnel/<fqdn>@<REALM> (auth:KERBEROS)
requestUser=alice
clientIP=<seatunnel-host>
2.5 Proxy-user (doAs) support
The mpack configures the following properties in core-site.xml:
hadoop.proxyuser.seatunnel.hosts=*
hadoop.proxyuser.seatunnel.groups=*
SeaTunnel 2.3.13 does not enable impersonation globally. Configure the hadoop.impersonation properties for each connector that supports this capability.
3. Knox — Web UI and REST proxying
3.1 Verify that the Knox topology includes the SEATUNNEL role
Run the following command to verify that the Knox topology includes the SEATUNNEL service role:
curl -s -u admin:admin -H 'X-Requested-By: ambari' \
'http://<ambari>:8080/api/v1/clusters/<cluster>/configurations/service_config_versions?service_name=KNOX&is_current=true&fields=configurations' \
| grep -c '<role>SEATUNNEL</role>'
The SeaTunnel service definition is available in the Knox codebase at the following path:
gateway-service-definitions/src/main/resources/services/seatunnel/2.3.13/
3.2 Verify that the service definition files exist on Knox hosts
Run the following command to verify that the SeaTunnel service definition files exist on the Knox hosts:
sudo ls -la /usr/odp/current/knox-server/data/services/seatunnel/2.3.13/
- service.xml
- rewrite.xml
Both files must have the following ownership and permissions:
- Owner and group: knox:hadoop
- Permissions: 0644
3.3 Verify that Knox challenges unauthenticated requests
Run the following command to verify that Knox requires authentication for requests to the SeaTunnel Web UI:
curl -sk -o /dev/null -w '%{http_code}\n' https://<knox-host>:8443/gateway/default/seatunnel/
The response includes the following authentication challenge:
WWW-Authenticate: BASIC realm="application"
3.4 Verify that LDAP-authenticated requests return the Web UI
Run the following command to verify that an LDAP-authenticated request returns the SeaTunnel single-page application (SPA):
curl -sk -u admin:admin-password https://<knox-host>:8443/gateway/default/seatunnel/ | \
grep -E 'title|assets|favicon'
<title>Seatunnel Engine UI</title>
https://<knox>:8443/gateway/default/seatunnel/assets/...
Resolution: Restart Knox to load the rewrite configuration.
3.5 Verify REST endpoint access through Knox
Run the following command to verify that the SeaTunnel REST endpoint is accessible through Knox:
curl -sk -u admin:admin-password https://<knox-host>:8443/gateway/default/seatunnel/overview
{
"projectVersion": "2.3.13...",
"runningJobs": "0",
"workers": "1"
}
3.6 Configure Knox for an HTTPS backend
When enable_https=true is configured on the Zeta master, the HTTPS service uses port 8483 instead of the HTTP port 8380.
To configure Knox to communicate with the HTTPS backend:
- Open the Knox topology configuration.
- Locate the <service> block that contains the SEATUNNEL role.
- Update the <url> element to point to the Zeta master's HTTPS endpoint.
<service>
<role>SEATUNNEL</role>
<url>https://<master>:8483</url>
</service>
The client-facing URL remains unchanged:
https://<knox-host>:8443/gateway/default/seatunnel/
4. Kerberos and engine wiring — Required configuration
For a SeaTunnel job to run successfully with Kerberos authentication, verify that the following configurations are in place.
- Verify that the submitter has a valid Kerberos ticket-granting ticket (TGT).
Before submitting a job, authenticate by using the appropriate keytab and principal:
kinit -kt <keytab> <principal>
- This requirement applies to all three execution engines: Zeta, Flink, and Spark.
- Verify that the execution engine passes the required JVM properties.
The mechanism for configuring Kerberos authentication depends on the execution engine:
| Engine | Kerberos configuration | |---|---| | Zeta | The master and worker JVMs inherit the -D properties from the systemd unit's ExecStart configuration. | | Flink | The flink run command uses the security.kerberos.login.* properties defined in flink-conf.yaml. | | Spark | The spark-submit command uses the --principal and --keytab options or an existing Kerberos TGT. | - Configure Kerberos authentication for the connector.
A connector obtains its Kerberos credentials from its configuration or the Java Authentication and Authorization Service (JAAS) configuration.
For connectors that support keytab-based Kerberos authentication, specify the following properties in the connector configuration:
kerberos_principal = "<principal>"
kerberos_keytab_path = "<keytab-path>"
- These properties apply to Kerberos-aware connectors such as HDFS, Hive, and HBase. Kafka SASL uses its own JAAS configuration mechanism, as described in section 5.1.
Note: Relying only on the JAAS configuration might cause authentication failures if a connector creates a thread pool that does not inherit the -Djava.security.auth.login.config property. - Verify that the required Ranger policies or native ACLs exist.
Ensure that the effective user has the required permissions to access the downstream resources.
For more information, see section 2, Ranger — Authorization model. - Configure cross-realm trust, if required.
If the source or sink belongs to a different Kerberos realm than the SeaTunnel service, verify that the /etc/krb5.conf file contains:- Both Kerberos realms in the [realms] section.
- Domain-to-realm mappings for both host domain suffixes in the [domain_realm] section.
5. Kerberos and specific connectors — Inline JAAS configuration
5.1 Kafka (SASL_PLAINTEXT/GSSAPI)
Updated October 7, 2026, following multi-host JDK 21 validation.
Earlier guidance required inline sasl.jaas.config for Kafka authentication. This requirement applied to the single-host JDK 17 lab environment, where JAAS configuration was passed through the SEATUNNEL_JVM_OPTS environment variable. However, this variable might not propagate to all Zeta worker thread pools.
In the current mpack-deployed Zeta cluster, the systemd unit passes the following property directly to the JVM:
-Djava.security.auth.login.config=/etc/seatunnel/conf/seatunnel-jaas.conf
The recommended Kafka authentication configuration now depends on the execution engine.
Recommended configuration for the SeaTunnel Zeta engine
For the Zeta engine, omit inline sasl.jaas.config from the Kafka connector configuration.
sink { # or source
Kafka {
bootstrap.servers = "<broker-list>:6669"
topic = "..."
format = "json"
kafka.config = {
security.protocol = "SASL_PLAINTEXT"
sasl.mechanism = "GSSAPI"
sasl.kerberos.service.name = "kafka"
# NO sasl.jaas.config — the Zeta JVM's global JAAS KafkaClient entry handles it
}
}
}
This configuration was validated on a multi-host JDK 21 cluster with the following pipelines:
- Fake-to-Kafka sink
- Kafka-to-Console source
- MySQL CDC-to-Kafka
All three pipelines completed successfully without inline JAAS configuration.
For validation details, see section 10.5b in 14-findings.md.
Known limitation: On the validated Kafka 3.9 cluster, inline sasl.jaas.config consistently caused authentication failures on the Consumer and Admin paths, even when _HOST substitution was configured correctly.
The Producer path continued to work. Therefore, successful producer-only validation does not confirm that the same configuration works for consumers.
Avoid inline JAAS configuration for standard Zeta jobs that use the mpack-provisioned service identity.
5.1a Kafka — Configure custom Kerberos credentials for individual jobs
Some SeaTunnel jobs might require a Kerberos identity other than the default seatunnel service user.
Examples include:
- A development team that uses its own keytab.
- A service account that belongs to another Kerberos realm.
- A Kafka producer that must be audited under a pipeline-specific identity, such as pipeline-x.
Do not modify the global /etc/seatunnel/conf/seatunnel-jaas.conf file for individual jobs. Changes to this file affect the entire cluster.
Use one of the following approaches.
Option 1: Configure inline JAAS for an individual Kafka connector
Add sasl.jaas.config to the connector's kafka.config block.
This configuration applies only to the specified connector.
On the validated cluster, inline JAAS worked reliably for Kafka sink and producer operations. Validation included 200,000 read/write operations with no failures.
However, Kafka 3.9 exhibited authentication conflicts between inline JAAS and the JVM-wide static JAAS configuration on the source and consumer paths.
For Kafka sources, use a headless principal or the shared service identity where appropriate.
Example: Configure a custom principal for a Kafka sink
kafka.config = {
security.protocol = "SASL_PLAINTEXT"
sasl.mechanism = "GSSAPI"
sasl.kerberos.service.name = "kafka"
sasl.jaas.config = "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab=\"/home/pipeline-x/pipeline-x.keytab\" principal=\"pipeline-x@ADSRE.COM\";"
}
Kafka's Krb5LoginModule does not perform Hadoop-style _HOST substitution. It treats _HOST as a literal value.
If the keytab does not contain a matching principal, authentication fails.
Option 2: Override the JAAS file for the submitting JVM
Set SEATUNNEL_JVM_OPTS before submitting the job.
# On the submit host, before invoking ./bin/seatunnel.sh
export SEATUNNEL_JVM_OPTS="-Djava.security.auth.login.config=/home/pipeline-x/pipeline-x-jaas.conf"
./bin/seatunnel.sh --config /path/to/job.conf -m cluster -n my_job
Limitation: Based on the October 7, 2026, multi-host validation, the override does not propagate to the Zeta worker JVMs. Workers continue to use the JAAS configuration provided by their systemd units.
To configure task-time credentials on Zeta workers, use the inline JAAS approach described in Option 1, subject to its connector limitations.
Option 3: Change the cluster-wide Kerberos identity
If the requirement is to replace the SeaTunnel service account across the cluster, update the mpack's kerberos.json configuration to request the new identity.
Use Ambari to regenerate /etc/seatunnel/conf/seatunnel-jaas.conf on all three hosts.
Use this approach for permanent, cluster-wide identity changes, not for individual jobs.
For per-job authentication, use connector-scoped credentials without modifying shared files under /etc/seatunnel/conf/.
5.1b Kafka — When inline sasl.jaas.config is required
Use inline JAAS configuration in environments where the mpack-provisioned JAAS file is unavailable to the execution containers.
These environments include:
- Flink 2 on YARN: Per-job ApplicationMasters can run on any YARN NodeManager. These hosts might not have /etc/seatunnel/conf/seatunnel-jaas.conf.
- Spark 3.5 and 4.1 on YARN: Jobs can run in containers that do not have the mpack-provisioned JAAS configuration.
- Non-ODP SeaTunnel deployments: The deployment might not provide a host-specific JAAS file.
For these environments, create a headless Kerberos principal such as seatunnel@REALM.
Ensure that the corresponding keytab is readable by the user running the YARN container and is available on every worker where the job might execute.
Configure inline JAAS without _HOST substitution.
kafka.config = {
security.protocol = "SASL_PLAINTEXT"
sasl.mechanism = "GSSAPI"
sasl.kerberos.service.name = "kafka"
sasl.jaas.config = "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab=\"/etc/security/keytabs/seatunnel.headless.keytab\" principal=\"seatunnel@<REALM>\";"
}
For more information, see section 11 in 14-findings.md.
5.2 HDFS, Hive, HBase, and Kudu
The HDFS, Hive, HBase, and Kudu connectors support the following Kerberos configuration properties:
- kerberos_principal
- kerberos_keytab_path
Specify these properties in each connector configuration to provide explicit Kerberos credentials.
This approach helps avoid authentication failures caused by differences in how connectors inherit JAAS configuration.
5.3 ZooKeeper (used indirectly by the HBase source)
ZooKeeper SASL authentication uses the JAAS configuration associated with the Kafka client entry.
Because the HBase source interacts with ZooKeeper, verify that the following JVM property is enabled:
-Dzookeeper.sasl.client=true
For more information about verifying the JVM properties, see section 1.4.
6. Encryption in transit
6.1 Enable TLS (HTTPS) for the Zeta Web UI
The mpack provides the configuration properties supported by the Zeta engine's HttpConfig and ServerConfigOptions.
The properties are defined and processed in the following files:
File | Description |
seatunnel-yaml.xml:105-181 | Defines the HTTPS configuration properties. |
params.py:193-203 | Reads the configuration values from Ambari. |
seatunnel-yaml.xml:205-221 | Renders the configuration template. |
setup.py:146-158 | Disables HTTPS for worker JVMs to prevent port conflicts. |
Only the active Zeta master serves the Web UI and REST endpoints. Worker JVMs do not require HTTPS configuration.
To prevent a BindException when a worker runs on the same host as the master, setup.py sets enable-https to false in seatunnel-worker.yaml.
6.1.1 Create the keystore on each master host
For lab environments, you can use a self-signed certificate.
For production environments, use a certificate signed by a trusted certificate authority (CA). Replace the -genkeypair operation with the appropriate -certreq, CA signing, and -importcert operations. The HTTPS configuration properties remain unchanged.
- Create the certificate directory.
sudo mkdir -p /etc/seatunnel/certs
Generate a PKCS12 keystore.
sudo keytool -genkeypair -alias seatunnel \
-keyalg RSA -keysize 2048 -validity 3650 \
-storetype PKCS12 \
-keystore /etc/seatunnel/certs/seatunnel.p12 \
-storepass '<KS_PWD>' -keypass '<KEY_PWD>' \
-dname "CN=$(hostname -f),OU=ODP,O=Acceldata,L=,ST=,C=US" \
- -ext "SAN=DNS:$(hostname -f),DNS:localhost,IP:$(hostname -I | awk '{print $1}')"
Set the ownership and permissions.
sudo chown seatunnel:hadoop /etc/seatunnel/certs/seatunnel.p12
- sudo chmod 0640 /etc/seatunnel/certs/seatunnel.p12
If the certificate does not contain a matching SAN, an HTTPS request to https://<master>:8483 might fail with one of the following errors:
unable to verify the first certificate
hostname verification failed
6.1.2 Configure HTTPS in Ambari
- In Ambari, go to SeaTunnel > Configs > Advanced seatunnel-yaml.
- Configure the following properties.
Property | Value | Description |
enable_https | true | Enables HTTPS. |
https_port | 8483 | Specifies the HTTPS port. The default is 8483. Avoid port 8443 because Knox might use it on the same host. |
key_store_path | /etc/seatunnel/certs/seatunnel.p12 | Specifies the keystore path. The seatunnel user must have read access. |
key_store_password | <KS_PWD> | Specifies the keystore password. Ambari uses the PASSWORD property type to mask the value in the UI and encrypt it at rest. |
key_manager_password | <KEY_PWD> | Specifies the key password. Leave this property empty to use key_store_password, or set it if the key password differs from the keystore password. |
trust_store_path | Empty | Optional. Configure this property only when mutual TLS (mTLS) is required. |
trust_store_password | Empty | Required when trust_store_path is configured. |
Save the configuration changes.- Restart the SeaTunnel service.
You can restart only the SEATUNNEL_ZETA_MASTER component because worker JVMs do not bind to the HTTPS port.
Note: Keep enable_http=true during the transition so existing clients can continue using port 8380. After Knox and all direct clients have migrated to HTTPS on port 8483, set enable_http=false.
6.1.3 Verify the rendered configuration
After you save the Ambari configuration, the http block in /etc/seatunnel/conf/seatunnel.yaml contains the following properties:
http:
enable-http: true
port: 8380
enable-dynamic-port: false
enable-https: true
https-port: 8483
key-store-path: /etc/seatunnel/certs/seatunnel.p12
key-store-password: <KS_PWD>
key-manager-password: <KEY_PWD>
The worker configuration file, /etc/seatunnel/conf/seatunnel-worker.yaml, must contain:
enable-https: false
6.1.4 Verify HTTPS connectivity
Complete the following checks to verify that HTTPS is enabled and functioning.
Step 1: Verify that the master listens on port 8483
# TCP bind — master only
sudo ss -lntp | grep -E ':8483'
Step 2: Verify the TLS handshake and certificate
# TLS handshake, cert chain, SAN
openssl s_client -connect $(hostname -f):8483 -servername $(hostname -f) </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
Step 3: Verify the REST endpoint over HTTPS
# REST through TLS
curl -sk https://$(hostname -f):8483/overview | python3 -m json.tool
{
"projectVersion": "2.3.13...",
"runningJobs": "0",
"workers": "1"
}
https://<master>:8483/
6.1.5 Configure Knox to use the HTTPS backend
After enabling HTTPS on the Zeta master, update the Knox topology to use the HTTPS backend.
- Open the Knox topology configuration.
- Locate the SEATUNNEL service block.
- Update the backend URL.
<service>
<role>SEATUNNEL</role>
<url>https://<master-fqdn>:8483</url>
- </service>
If the backend certificate is self-signed or issued by an internal CA, import it into the Knox truststore.
sudo keytool -importcert -noprompt -alias seatunnel-backend \
-file /etc/seatunnel/certs/seatunnel.crt \
-keystore /usr/odp/current/knox-server/conf/gateway.jks \
-storepass $(sudo cat /usr/odp/current/knox-server/data/security/master)
sudo ambari-agent restart # or restart KNOX_GATEWAY via Ambari UI
https://<knox>:8443/gateway/<topo>/seatunnel/
6.1.6 Troubleshoot common HTTPS failures
Symptom | Cause | Resolution |
master.log displays FileNotFoundException: …/seatunnel.p12. | The seatunnel user cannot read the keystore. | Set the ownership to seatunnel:hadoop and permissions to 0640. |
master.log displays Keystore was tampered with, or password was incorrect. | key_store_password does not match the keystore password specified by -storepass. | Update key_store_password in Ambari > Advanced seatunnel-yaml, and restart the master. |
master.log displays Cannot recover key. | key_manager_password does not match the key password. | Clear key_manager_password to inherit key_store_password, or specify the password used with -keypass. |
master.log displays Address already in use: 8483 on a worker host. | HTTPS is incorrectly enabled in the worker configuration. | Verify that seatunnel-worker.yaml contains enable-https: false. If the file was manually modified, redeploy the configuration through Ambari. The setup.py logic disables HTTPS for workers. |
openssl s_client reports a self-signed certificate error, or the browser displays NET::ERR_CERT_AUTHORITY_INVALID. | The client does not trust the self-signed certificate. | Import the certificate into the client truststore, or use a CA-signed certificate in production. |
Knox returns 502 Bad Gateway for /gateway/<topo>/seatunnel/overview. | The topology points to the HTTP backend, or Knox does not trust the backend certificate. | Update the topology URL to https://<master>:8483 and import the backend certificate into the Knox truststore. |
The browser displays hostname verification failed. | The certificate's Common Name (CN) or SAN does not match the URL hostname. | Regenerate the certificate with a SAN that matches the hostname used by clients. |
6.2 Other encryption in transit
Kafka SASL_SSL
To enable encrypted Kafka communication, set security.protocol to SASL_SSL in sink.Kafka.kafka.config.
security.protocol = "SASL_SSL"
- ssl.truststore.location
- ssl.truststore.password
HDFS encryption zones
HDFS encryption zones are transparent to SeaTunnel.
Kerberos authentication and Ranger policies or native ACLs continue to control access to HDFS resources.
The Key Management Server (KMS) manages the encryption keys.
Hive over LLAP
When using Hive LLAP, configure the JDBC connection to use HTTPS transport with SSL enabled.
jdbc:hive2://…/;transportMode=http;httpPath=cliservice;ssl=true
7. Auditing
Use the following audit logs to monitor authentication, authorization, and data access for SeaTunnel pipelines.
Ranger audit trail
Ranger records authorization decisions, including allowed and denied access requests, in the Solr or HDFS audit store.
Filter the audit records by the seatunnel service user or the submitting user's identity to trace the resources accessed by a pipeline.
HDFS audit log
The HDFS audit log records file operations, including file access and creation, along with the user identity and client IP address.
Log location:
/var/log/hadoop-hdfs/hdfs-audit.log
Kafka authorizer log
The audit location depends on the Kafka authorizer.
- Native Kafka authorizer (AclAuthorizer): Review the broker authorization log at:
/var/log/kafka3/kafka-authorizer.log
Ranger Kafka authorizer: Review the Ranger audit records.
SeaTunnel Zeta REST audit
The embedded Jetty server writes REST access logs to the following file:
seatunnel-engine-master.log
Kerberos KDC log
The Kerberos Key Distribution Center (KDC) records authentication requests for the seatunnel principal.
Log location:
/var/log/krb5kdc.log
- AS-REQ: Authentication Service requests.
- TGS-REQ: Ticket-Granting Service requests.
These records help trace Kerberos authentication activity associated with the SeaTunnel service principal.
8. Common security failures and resolutions
The following table lists common security-related failures, their possible causes, and the recommended resolutions.
Symptom | Possible cause | Resolution |
Client cannot authenticate via:[TOKEN, KERBEROS] | The effective user does not have a valid Kerberos ticket-granting ticket (TGT), or the JAAS configuration is not loaded. | Authenticate by using kinit and verify the JVM Kerberos properties. See section 1.4. |
Kafka job reports FINISHED, but no messages appear in the topic. | The required Kafka ACL or Ranger policy is missing. | See section 1 in 05-troubleshooting.md. |
AccessControlException: Permission denied on HDFS. | The required HDFS ACL or Ranger policy is missing. | Configure the required permissions by using hdfs dfs -setfacl or create a Ranger policy. |
User seatunnel does not have permission to submit … to queue default | The seatunnel user does not have permission to submit applications to the target YARN queue. | Configure the required Ranger YARN policy or update yarn.admin.acl. |
Knox returns HTTP 401 after LDAP authentication. | The Knox topology is missing the required <provider> configuration, or the <url> value is incorrect. | Verify the Knox topology and authentication configuration. See sections 3.1–3.4. |
Knox returns 502 Bad Gateway for /gateway/default/seatunnel/overview. | The Knox topology points to an incorrect backend port, such as 8380 when Zeta uses HTTPS on 8483. | Update the backend URL in the Knox topology. See section 3.6. |
The Zeta master fails to start after setting enable_https=true. The log displays FileNotFoundException or Keystore was tampered with. | The keystore path or password is incorrect, or the keystore has insufficient file permissions. | Verify the keystore configuration and permissions. See section 6.1.6. |
The browser displays NET::ERR_CERT_AUTHORITY_INVALID or hostname verification failed when accessing https://<master>:8483. | The client does not trust the self-signed certificate, or the certificate has a missing or incorrect Subject Alternative Name (SAN). | Verify the certificate trust configuration and SAN values. See sections 6.1.1 and 6.1.6. |

Have a suggestion?