Blog
trinosecurityldapoauth2tlsdata-platform

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.

Data DynamicsJune 5, 20268 min read

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
LayerWhat it preventsKey configuration
① TLSPlaintext eavesdroppinghttp-server.https.*
② AuthenticationIdentity spoofinghttp-server.authentication.type
③ AuthorizationUnauthorized accessaccess-control.properties
④ Internal communicationRogue workers, internal eavesdroppinginternal-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=false

You 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).

MethodValueUse case
Password (LDAP/file)PASSWORDCorporate LDAP/AD integration, the most common
OAuth2 / OIDCOAUTH2Okta, Keycloak, Azure AD SSO
KerberosKERBEROSExisting Cloudera/Hadoop Kerberos assets
Certificate (mTLS)CERTIFICATEClient-certificate based
JWTJWTIntegration 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 alice

3.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,email

A 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,PASSWORD

4. 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.

Methodaccess-control.nameCharacteristics
Allow all (default)allow-allNo authorization. Never use in production
Read onlyread-onlyBlocks all writes
File basedfileJSON rules file. Good for small-to-medium deployments
Apache Ranger(plugin)Central policies and auditing, reuses Cloudera assets
OPAopaOpen 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/allow

5. 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 32

Once authentication is enabled, the shared secret is mandatory. To additionally encrypt internal communication with TLS:

internal-communication.https.required=true
http-server.https.enabled=true

A 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:carol

The 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.name to something other than allow-all
  • Apply column masking and row filters to sensitive tables
  • Set the same internal-communication.shared-secret on 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

LayerMinimum setupRecommended setup
TransportHTTPS on the coordinatorTLS for internal communication too
AuthenticationFile-based passwordsLDAP or OAuth2 SSO
AuthorizationFile-based rulesRanger/OPA + column masking and row filters
Internal communicationShared secretShared secret + TLS
SecretsEnvironment variable substitutionVault / 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