The Complete Trino Security Guide — Authentication, Authorization, TLS, and Internal Communication
A walkthrough of everything you need to run a Trino cluster securely in production: LDAP/OAuth2 authentication, TLS, the internal communication shared secret, file/Ranger/OPA-based authorization, column masking and row filters, and secrets management.
A Trino cluster running with default settings has no authentication. Anyone who can reach port 8080 can query every catalog, and inter-node traffic flows in plaintext. That's convenient during a PoC, but in production you absolutely must enable authentication, authorization, and encryption.
This post breaks Trino security down into four areas — transport encryption (TLS), authentication, authorization, and internal communication — and walks through each with real configuration files.
1. Security at a Glance
[Clients: BI, JDBC, CLI]
│ ① TLS (HTTPS) + ② Authentication
▼
┌──────────────────┐
│ Coordinator │ ③ Authorization (access control)
└──────────────────┘
│ ④ Internal communication: shared secret + (optional) TLS
┌─────────┼─────────┐
▼ ▼ ▼
Worker Worker Worker| Layer | What it prevents | Key configuration |
|---|---|---|
| ① TLS | Plaintext eavesdropping | http-server.https.* |
| ② Authentication | Identity spoofing | http-server.authentication.type |
| ③ Authorization | Unauthorized access | access-control.properties |
| ④ Internal communication | Rogue workers, internal eavesdropping | internal-communication.shared-secret |
An important prerequisite: most authentication methods require TLS to be enabled first. You can't send passwords over plaintext. So the order of configuration is TLS → authentication → authorization.
2. TLS — Start with Transport Encryption
Configure the coordinator to accept HTTPS. You'll need a keystore (PKCS#12 or JKS).
# etc/config.properties (coordinator)
http-server.https.enabled=true
http-server.https.port=8443
http-server.https.keystore.path=/etc/trino/tls/keystore.p12
http-server.https.keystore.key=changeit
# To close the plaintext 8080 port (mind health checks / internal paths)
http-server.http.enabled=falseYou can reuse the self-signed or internal CA certificates you were using in your Cloudera environment. (For certificate issuance itself, see the separate post "Creating self-signed TLS certificates that meet Cloudera's requirements.") On Kubernetes, TLS is usually terminated at a front-facing Ingress/LoadBalancer, with in-cluster traffic handled separately.
3. Authentication — Who Is Connecting
Specify the authentication method via http-server.authentication.type. List multiple methods separated by commas to try them in order (a fallback chain).
| Method | Value | Use case |
|---|---|---|
| Password (LDAP/file) | PASSWORD | Corporate LDAP/AD integration, the most common |
| OAuth2 / OIDC | OAUTH2 | Okta, Keycloak, Azure AD SSO |
| Kerberos | KERBEROS | Existing Cloudera/Hadoop Kerberos assets |
| Certificate (mTLS) | CERTIFICATE | Client-certificate based |
| JWT | JWT | Integration with a token-issuing system |
3.1 LDAP Authentication (PASSWORD)
This is the most widely used setup. Users log in with their corporate LDAP/AD username and password.
# etc/config.properties
http-server.authentication.type=PASSWORD# etc/password-authenticator.properties
password-authenticator.name=ldap
ldap.url=ldaps://ldap.example.com:636
ldap.bind-dn=cn=trino-svc,ou=services,dc=example,dc=com
ldap.bind-password=${ENV:LDAP_BIND_PASSWORD}
ldap.user-base-dn=ou=users,dc=example,dc=com
ldap.group-auth-pattern=(&(objectClass=person)(uid=${USER}))Using ldaps:// (LDAP over TLS) is the rule. You must add the LDAP server's certificate to Trino's truststore for verification to pass.
3.2 File-Based Passwords (Small / Internal Use)
If you don't have LDAP, you can authenticate against a bcrypt hash file.
# etc/password-authenticator.properties
password-authenticator.name=file
file.password-file=/etc/trino/password.db# Generate bcrypt hashes with htpasswd
htpasswd -B -C 10 -c /etc/trino/password.db alice3.3 OAuth2 / OIDC (SSO)
Integrate with an IdP such as Keycloak, Okta, or Azure AD to set up browser SSO.
# etc/config.properties
http-server.authentication.type=OAUTH2
http-server.authentication.oauth2.issuer=https://keycloak.example.com/realms/data
http-server.authentication.oauth2.client-id=trino
http-server.authentication.oauth2.client-secret=${ENV:OAUTH2_CLIENT_SECRET}
http-server.authentication.oauth2.scopes=openid,profile,emailA hybrid setup is common: the web UI and modern clients use the OAuth2 flow, while automation and batch jobs fall back to JWT or LDAP.
# Fallback chain: try OAuth2 first, then PASSWORD
http-server.authentication.type=OAUTH2,PASSWORD4. Authorization — What Can They Do
Authorization determines which catalogs, schemas, tables, and columns an authenticated user can access. You choose the system access control in etc/access-control.properties.
| Method | access-control.name | Characteristics |
|---|---|---|
| Allow all (default) | allow-all | No authorization. Never use in production |
| Read only | read-only | Blocks all writes |
| File based | file | JSON rules file. Good for small-to-medium deployments |
| Apache Ranger | (plugin) | Central policies and auditing, reuses Cloudera assets |
| OPA | opa | Open Policy Agent, fine-grained control via Rego policies |
4.1 File-Based Authorization
# etc/access-control.properties
access-control.name=file
security.config-file=/etc/trino/rules.json{
"catalogs": [
{ "user": "admin", "catalog": ".*", "allow": "all" },
{ "group": "analysts", "catalog": "iceberg", "allow": "read-only" }
],
"schemas": [
{ "group": "analysts", "catalog": "iceberg", "schema": "analytics", "owner": false }
],
"tables": [
{
"group": "analysts",
"catalog": "iceberg",
"schema": "analytics",
"table": ".*",
"privileges": ["SELECT"]
}
]
}Rules are evaluated top-down, first match wins. Anything not explicitly allowed is denied by default. tables rules can also define column masking and row filters.
4.2 Column Masking / Row Filters
Mask sensitive columns, or restrict which rows each user can see.
{
"tables": [
{
"group": "analysts",
"catalog": "iceberg",
"schema": "analytics",
"table": "users",
"privileges": ["SELECT"],
"columns": [
{ "name": "ssn", "mask": "'***-**-' || substr(ssn, 8)" }
],
"filter": "region = 'KR'"
}
]
}This rule shows the analysts group a masked prefix of ssn and exposes only rows where region = 'KR'.
4.3 Ranger / OPA
Organizations that already manage policies and auditing with Cloudera Ranger can port their policies via the Ranger plugin for Trino and keep centralized management and audit logs. If you want policy-as-code (GitOps), OPA is a strong option — Rego can express fine-grained rules like "allow only during specific hours" or "PII columns only for specific roles."
# etc/access-control.properties (OPA example)
access-control.name=opa
opa.policy.uri=http://opa.example.com:8181/v1/data/trino/allow5. Internal Communication — Preventing Rogue Workers and Internal Eavesdropping
The coordinator and workers trust each other. Even with authentication enabled, if this internal channel is unprotected, an attacker on the same network could attach a fake worker or intercept internal traffic. Configure the same shared secret on every node.
# etc/config.properties (identical on every coordinator + worker)
internal-communication.shared-secret=<a long random string># Example: generate a secret
openssl rand -hex 32Once authentication is enabled, the shared secret is mandatory. To additionally encrypt internal communication with TLS:
internal-communication.https.required=true
http-server.https.enabled=trueA common mistake: enabling external authentication (LDAP) but skipping the internal shared secret. Authentication can be bypassed in that case, so always configure the two together as a set.
6. Secrets Management — No Plaintext Passwords
Never leave the LDAP bind password, OAuth2 client secret, keystore password, and so on in configuration files as plaintext. Trino supports environment variable substitution.
ldap.bind-password=${ENV:LDAP_BIND_PASSWORD}
http-server.https.keystore.key=${ENV:KEYSTORE_PASSWORD}On Kubernetes, inject these environment variables from a Secret; on bare metal, supply them via a systemd EnvironmentFile or a Vault integration. No secrets should end up in configuration files (Git).
7. User Mapping and Groups
Normalize the authenticated principal (e.g. alice@EXAMPLE.COM, or a certificate CN) into a Trino-internal username, and assign groups for use in authorization rules.
# Authenticated principal → Trino username mapping (regex)
http-server.authentication.password.user-mapping.pattern=(.*)@example\.com
# Group provider: file or LDAP# etc/group-provider.properties (file-based example)
group-provider.name=file
file.group-file=/etc/trino/group.txt# group.txt : group-name:user1,user2
analysts:alice,bob
admins:carolThe groups referenced as "group": "analysts" in the authorization rules are defined here.
8. Production Security Checklist
- Enable TLS (HTTPS) on the coordinator; block external exposure of the plaintext 8080 port
- Choose and enable an authentication method (LDAP/OAuth2/Kerberos)
- Set
access-control.nameto something other thanallow-all - Apply column masking and row filters to sensitive tables
- Set the same
internal-communication.shared-secreton every node - (If needed) enable TLS for internal communication
- Move all passwords/secrets into environment variables or Secrets
- Configure user mapping and a group provider
- Set up a collection path for query audit logs (event listener)
9. Wrapping Up
| Layer | Minimum setup | Recommended setup |
|---|---|---|
| Transport | HTTPS on the coordinator | TLS for internal communication too |
| Authentication | File-based passwords | LDAP or OAuth2 SSO |
| Authorization | File-based rules | Ranger/OPA + column masking and row filters |
| Internal communication | Shared secret | Shared secret + TLS |
| Secrets | Environment variable substitution | Vault / K8s Secret |
The key to Trino security is recognizing that "the defaults are not safe" and enabling everything in order — TLS → authentication → authorization → internal communication — without skipping a step. The most frequent mistake is enabling external authentication while forgetting the internal shared secret, so treat the two as a single set. Most of your existing Cloudera LDAP, Kerberos, and Ranger assets can be reused, so the security side of a migration is lighter than you might expect.
This post was written against Trino in the 440 series. If you need help designing or auditing the security of a production Trino cluster, feel free to reach out.
— The Data Dynamics Engineering Team