diff --git a/platform/control-plane/query-engines/engine-detail.md b/platform/control-plane/query-engines/engine-detail.md index e690a9d..3f0a166 100644 --- a/platform/control-plane/query-engines/engine-detail.md +++ b/platform/control-plane/query-engines/engine-detail.md @@ -71,7 +71,6 @@ How Egret signs in to the coordinator depends on the engine: |---|---|---| | JWT delegation (the default for a provisioned Trino engine) | **You**, with the engine token Egret mints for you | What the engine's own policy lets you see: other users' queries only if it lets you view them. Killing a query is decided the same way. | | Password users or impersonation | The engine's `egret-monitor` account | The queries that account may see. | -| No authentication | `egret-monitor` | Every query. | The node list comes from Trino's `GET /v1/node` where the coordinator serves it. Trino 483 does not by default, and then Egret reads `system.runtime.nodes` instead. That query runs as the same sign-in, so on a JWT engine it appears in the **Queries** table under your name (on the demo stack: `SELECT http_uri FROM system.runtime.nodes`, user `admin`, **FINISHED**). If it is refused too, **nodes** shows `—`: the count is unknown, not zero, and the query counts are still shown. diff --git a/platform/control-plane/query-engines/index.md b/platform/control-plane/query-engines/index.md index b55b2db..e4bc8b4 100644 --- a/platform/control-plane/query-engines/index.md +++ b/platform/control-plane/query-engines/index.md @@ -22,6 +22,8 @@ A summary strip counts **engines**, how many are **running** and **not running** | **Status** | The lifecycle status of a provisioned engine (**Provisioning**, **Running**, **Failed**). **External** for a registered one: egret does not monitor it. | | Actions | **Details** opens the engine. | +A provisioned Trino engine can also carry a **Re-apply needed** badge (the API field is `securityReapplyNeeded` on the engine). Its tooltip says *This engine still accepts unauthenticated requests on port 8080. Re-apply it to turn on authentication.* The engine was applied before platform #842 and still runs the old configuration. The badge clears after the next successful apply. An engine with JWT only and no password users never shows it. See [Provision an engine](./provision.md#security--exposure). + ## Add an engine Two buttons sit at the top right: diff --git a/platform/control-plane/query-engines/provision.md b/platform/control-plane/query-engines/provision.md index d456da4..babd973 100644 --- a/platform/control-plane/query-engines/provision.md +++ b/platform/control-plane/query-engines/provision.md @@ -52,6 +52,24 @@ The form shows *Cluster-wide, coordinator, and worker Trino config. Leave fields | **Per-user delegation** | How queries from SQL Lab, charts and dashboards run as the calling user (below). | | **Ingress exposure** | *Create a Kubernetes Ingress for the coordinator. TLS terminates at the ingress.* With **Expose via ingress** on you set **Host**, **Ingress class**, **Ingress TLS cert** and **Annotations**. **Host** is required: without it the field says *Enter the host the ingress serves, or turn off Expose via ingress.* and **Create** stays disabled. | +Every provisioned Trino engine authenticates, since platform #842. An engine created or updated with no authentication setting has `{"password":{}}` stored (password authentication with no users) and applied; an existing engine gains it at its next apply. Egret still provisions its own `egret-monitor` account and, in impersonate mode, the `egret_delegator` account. External engines are not affected: Egret does not render their configuration. + +The coordinator also refuses authentication over plain HTTP (`http-server.authentication.allow-insecure-over-http=false`). Measured on Trino 483: + +| Request to the coordinator | Result | +|---|---| +| Plain HTTP on port 8080, no `X-Forwarded-Proto: https` header | `403`, *Authentication over HTTP is not enabled*, before any identity is read. A client cannot claim to be another user by setting `X-Trino-User`. | +| The same with `X-Forwarded-Proto: https` and no credential | `401`. | +| The same with `X-Forwarded-Proto: https` and a Basic credential | Accepted. | +| The delegator over HTTPS 8443 | Accepted. | +| `GET /v1/info`, no credential | `200`. Health checks keep working. | + +Egret's monitor sends `X-Forwarded-Proto: https` with a credential; delegated queries use HTTPS on port 8443. The engine's ingress sends the header too. The header was simulated by hand; it was not measured against a real ingress controller or kube proxy. + +A client that dials `http://:8080` directly with no password, for example `trino --server http://:8080 --user x`, no longer works. Connect through the engine's ingress, or on HTTPS 8443 on engines that serve it (delegation-capable engines: impersonate mode, and JWT mode with a JWT block), with a password or JWT. An engine with neither an ingress nor port 8443 has no direct client path, only Egret's own. Impersonation does not make plain HTTP safe: the earlier belief that an impersonate engine was safe over plain HTTP because only the delegator could impersonate was measured to be false, and is why the flag is now off. + +An engine that was applied before this release still runs the old configuration. See **Re-apply needed** in [the engine list](./index.md#the-engine-list) (the badge) and the [upgrade notes](../../deploy-operate/upgrade.md#trino-engines-authenticate-and-refuse-plain-http-identity). + The delegation modes: | Mode | What it does | diff --git a/platform/deploy-operate/engines-and-ranger.md b/platform/deploy-operate/engines-and-ranger.md index 3753cfe..e947426 100644 --- a/platform/deploy-operate/engines-and-ranger.md +++ b/platform/deploy-operate/engines-and-ranger.md @@ -119,7 +119,7 @@ names them, and the engine's **Logs** and **Exec** buttons answer *not available | Engine | Requirement | |---|---| | Trino | `http-server.process-forwarded=true`. Egret sends `X-Forwarded-Proto`; without the setting Trino answers *406* and Egret reports *502*. See [Engine 406 and 502 errors](./troubleshooting/engine-406-502). | -| Trino | For per-user delegation, JWT authentication (`http-server.authentication.type=JWT`) with `principal-field=preferred_username` and `required-audience=trino`, **over HTTPS**. Over plain HTTP Trino accepts a valid JWT but does not require one. | +| Trino | For per-user delegation, JWT authentication (`http-server.authentication.type=JWT`) with `principal-field=preferred_username` and `required-audience=trino`, **over HTTPS**. Over plain HTTP, with `allow-insecure-over-http=true`, Trino accepts a valid JWT but does not require one. Engines Egret provisions set that flag to `false` and always authenticate (platform #842). An engine you run needs both an authenticator and `allow-insecure-over-http=false`: without an authenticator anyone can claim any user, whatever the flag says. | | StarRocks | A security integration of type `authentication_jwt` for per-user delegation, with `required_issuer` equal to Egret's issuer and `required_audience` `starrocks`. The `jwks_url` must start with `http://` or `https://`. | | Both | A network path from the engine to Egret for policy downloads, and to the catalog if you use it. | diff --git a/platform/deploy-operate/upgrade.md b/platform/deploy-operate/upgrade.md index ae411e2..1629d07 100644 --- a/platform/deploy-operate/upgrade.md +++ b/platform/deploy-operate/upgrade.md @@ -612,6 +612,29 @@ returned by the API; keep `SECRET` values in `SECRET` outputs and inputs. There is no supported in-place rollback. Restore the database from the backup taken in step 2, then start the previous binary. Object storage is not changed by migrations, but files written by the newer version stay in the bucket. +### Trino engines authenticate and refuse plain-HTTP identity + +From platform #842 every provisioned Trino engine authenticates, and its coordinator refuses authentication over plain HTTP +(`http-server.authentication.allow-insecure-over-http=false`). There is a migration (`0215`, one column that records which +security revision an engine was last applied with) and one API field, `securityReapplyNeeded`. + +The new settings take effect when an engine is next applied (re-apply, or any change that applies it). Until then it keeps the +configuration of its last apply. + +- **Re-apply every provisioned Trino engine** after the upgrade. In **Control plane → Engines** the engines that still need it + show a **Re-apply needed** badge; the badge clears after the next successful apply. An engine with JWT only and no + password users never shows it. +- **Direct plain-HTTP clients stop working** once an engine is re-applied: `trino --server http://:8080 --user x` + with no password gets 403 *Authentication over HTTP is not enabled*. Point such clients at the engine's ingress, or at HTTPS + on port 8443 where the engine serves it (delegation-capable engines), with a password or a JWT. An engine with neither has no + direct client path, only Egret's own. +- `/v1/info` stays open. Egret's monitor sends `X-Forwarded-Proto: https` with a credential; delegated queries use HTTPS on + port 8443. The ingress sends the header too (simulated with a hand-set header; not measured against a real ingress controller). +- External engines are not changed by Egret. + +See [Security & Exposure](../control-plane/query-engines/provision.md#security--exposure) and KI-355 in +[Known issues](../known-issues.md). + ## Further reading - [Backup and restore](./backup-restore) diff --git a/platform/known-issues.md b/platform/known-issues.md index 7ea2996..be9de2d 100644 --- a/platform/known-issues.md +++ b/platform/known-issues.md @@ -405,6 +405,7 @@ Collected while writing the detailed pages for each area (October 2026), checked | KI-352 | Governance / Trino on OPA | UX | S3 | On a Trino profile on OPA, a deny of one privilege hides an object from listings even when the user may read it: a user who may read `s1.t2` but is denied **write** on it can `SELECT` from it, yet `SHOW TABLES`, `information_schema` and so JDBC metadata and catalog browsers do not list `t2`. On Ranger they list it. OPA is stricter by design (Egret hides an object any deny or withheld classification covers), never looser. *Workaround:* none on OPA; query the table by its full name. (Measured end to end on Trino 483 for platform #839; see [Trino on OPA](./data-governance/engines-and-policy/trino-on-opa.md#known-differences-from-ranger).) | | KI-353 | Governance / Trino on OPA | Gap | S2 | View lineage is not captured through a Trino engine whose profile is on OPA: OPA refuses the `egret-lineage` principal the unmasked reads the Ranger download gives it on JWT-mode engines, so its lineage `EXPLAIN` fails closed. *Workaround:* keep the profile on Ranger where view lineage matters. (Platform #839.) | | KI-354 | Governance / Trino on OPA | Gap | S1 | An external Trino 483 engine bound to its own compiled profile on OPA cannot run any query: the profile gets no infrastructure rows (query execution, self-impersonation), and no grant can add them, so Trino's per-query checks are denied. *Workaround:* keep such an engine's profile on Ranger. (Measured on the end-to-end stack for platform #839.) | +| KI-355 | Engines / Trino | Security | S1 | **Fixed in platform #842 (November 2026).** A provisioned Trino engine could run with no authentication and accepted authentication over plain HTTP, so anyone who reached port 8080 and set `X-Trino-User` (or `--session-user`) ran queries as that user, impersonate-mode engines included. Every provisioned Trino engine now authenticates and refuses plain HTTP without `X-Forwarded-Proto: https` (403 *Authentication over HTTP is not enabled*; with the header and no credential, 401). Measured on Trino 483. `/v1/info` stays open; Egret's monitor and the ingress send the header with a credential (simulated, not measured against a real ingress controller). An engine applied before the fix keeps the old configuration until it is next applied: the engine list shows **Re-apply needed**. A client with no password must use the engine's ingress, or HTTPS 8443 where the engine serves it. External engines are not changed by Egret. | ## Not verified