Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,13 @@
*** xref:sql:connect-to-sql/language-clients/java-jdbc.adoc[]
*** xref:sql:connect-to-sql/language-clients/php-pdo.adoc[]
*** xref:sql:connect-to-sql/language-clients/dotnet-dapper.adoc[]
*** xref:sql:connect-to-sql/connect-with-oidc.adoc[Connect with OIDC]
** xref:sql:query-data/index.adoc[Query Data]
*** xref:sql:query-data/redpanda-catalogs.adoc[Redpanda Catalogs]
*** xref:sql:query-data/query-streaming-topics.adoc[Query Streaming Topics]
*** xref:sql:query-data/query-iceberg-topics.adoc[Query Iceberg Topics]
** xref:sql:manage/index.adoc[Manage Redpanda SQL]
*** xref:sql:manage/manage-access.adoc[Manage access]
** xref:sql:troubleshoot/index.adoc[Troubleshoot]
*** xref:sql:troubleshoot/degraded-state-handling.adoc[]
*** xref:sql:troubleshoot/memory-management.adoc[Memory Management]
Expand Down
128 changes: 128 additions & 0 deletions modules/sql/pages/connect-to-sql/connect-with-oidc.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
= Connect to Redpanda SQL with OIDC
:description: Authenticate to Redpanda SQL using a bearer token or client credentials issued by your OpenID Connect (OIDC) identity provider.
:page-topic-type: how-to
:personas: app_developer, data_engineer, platform_admin
:learning-objective-1: Obtain credentials from your OIDC identity provider for Redpanda SQL
:learning-objective-2: Connect to Redpanda SQL using a bearer token or client credentials

Authenticate to Redpanda SQL using glossterm:OpenID Connect (OIDC)[] instead of a SCRAM password. The cluster validates the credential locally against the configured glossterm:identity provider (IdP)[,identity provider] and takes the session identity from the glossterm:principal[] claim in the token, not from the `user=` field in the connection string. The cluster admin grants per-user data access separately. See xref:sql:manage/manage-access.adoc[] for the access model.

After completing these steps, you will be able to:

* [ ] {learning-objective-1}
* [ ] {learning-objective-2}

== Prerequisites

* A Redpanda glossterm:BYOC[] cluster on AWS with Redpanda SQL enabled. See xref:sql:get-started/deploy-sql-cluster.adoc[Enable Redpanda SQL].
* OIDC configured for your Redpanda cluster. See xref:security:authorization/gbac/gbac_dp.adoc[Configure GBAC in the Data Plane] for the cluster-level OIDC setup. Configuring OIDC is not specific to Redpanda SQL.
* https://www.postgresql.org/download/[`psql`^] or another PostgreSQL-compatible client.
* *A SQL user that matches the principal in your OIDC token.* Redpanda SQL does not auto-create users on first OIDC login. The cluster admin must run `CREATE USER <token-principal>` for each user, where `<token-principal>` is the value of the claim configured by the cluster's `oidc.oidc_principal_mapping` (default `$.sub`, often overridden to `$.preferred_username` for human-readable usernames). Usernames listed in the cluster's `oidc.protected_users` (default `["oxla"]`) cannot authenticate via OIDC even when a token resolves to that name.

== Authentication modes

Redpanda SQL accepts two OIDC authentication modes, selected by the connection-string `options` parameter:

[cols="<25%,<30%,<45%",options="header"]
|===
|Mode |`options` value |When to use

|Bearer token
|`auth_method=bearer`
|You already hold a JSON Web Token (JWT) issued by the identity provider (for example, an Authorization Code flow result on a developer workstation, or a token minted by a cluster-side workflow).

|Client credentials
|`auth_method=client_secret`
|Service-to-service connections (scheduled jobs, BI tools). Redpanda SQL exchanges the client ID and client secret for a token against the IdP's token endpoint, then validates the returned token.
|===

If you omit `options`, Redpanda SQL defaults to SCRAM password authentication. Redpanda SQL treats a glossterm:bearer token[] in the password field without `auth_method=bearer` as a SCRAM password, and the connection fails.

The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) and must use one of these signing algorithms: `RS256`, `RS384`, `RS512`, or `ES256`. Redpanda SQL rejects tokens signed with `alg: none`.

// TODO: Confirm the validated IdP coverage with engineering (qa-questions.md #16).
// E2E tests in oxla currently use Keycloak (tests/blackbox/configurations/keycloak/);
// Okta, Microsoft Entra ID, Auth0, and Google have not been confirmed as explicitly
// tested for Redpanda SQL bearer-token auth. List validated IdPs here once confirmed.

// TODO: Verify aud-as-array + azp validation semantics. The RFC states that when
// `aud` is an array, `azp` is also validated, but the JWT validator code has not
// been audited line-by-line for this case. Confirm with SME before publishing.

== Connect with a bearer token

Set `options=auth_method=bearer` in the connection string and pass the token in the password field. Redpanda SQL ignores the `user=` field and takes the session identity from the principal claim in the token.

.psql
[source,bash]
----
PGPASSWORD="$BEARER_TOKEN" \
psql "host=<sql-host> port=<sql-port> dbname=oxla user=ignored options='auth_method=bearer' sslmode=require"
----

.Python (psycopg2)
[source,python]
----
import os
import psycopg2

conn = psycopg2.connect(
host="<sql-host>",
port=<sql-port>,
dbname="oxla",
user="ignored",
password=os.environ["BEARER_TOKEN"],
options="auth_method=bearer",
sslmode="require",
)

cur = conn.cursor()
cur.execute("SELECT current_user")
# current_user is the principal from the token, not "ignored"
----

For more language-client examples, see xref:sql:connect-to-sql/index.adoc[Connect to Redpanda SQL].

[NOTE]
====
*Concurrent first-time logins.* First-time logins through a connection pool can occasionally produce duplicate role entries in the distributed catalog, after which DDL operations against the role fail. Track https://redpandadata.atlassian.net/browse/OXLA-9382[OXLA-9382^]. As a workaround, have each user log in once with a single connection before using a connection pool against that account.
====

== Connect with client credentials

Set `options=auth_method=client_secret`, pass the OIDC client ID in `user=`, and the client secret in the password field. Redpanda SQL exchanges these against the identity provider's token endpoint and validates the returned token. The resolved principal becomes the session identity.

[source,bash]
----
PGPASSWORD="$CLIENT_SECRET" \
psql "host=<sql-host> port=<sql-port> dbname=oxla user=<client-id> options='auth_method=client_secret' sslmode=require"
----

// TODO: Confirm the exact token-endpoint timeout to document.
// Source default in oxla/src/net/http/http_client.h is 10s (request_timeout{10000}),
// constructed via default-initialised HttpClientConfig in
// oxla/src/network/leader_factory.cpp:15. The RFC quotes 5s. Document the correct
// value once verified with SME.

== Use TLS on OIDC connections

OIDC credentials travel in the password field of the PostgreSQL startup message. To protect them in transit, set `sslmode=require` on every OIDC connection.

Two distinct cluster settings affect TLS for OIDC:

* The cluster's SSL mode controls TLS on the `psql` connection to Redpanda SQL itself. To reject OIDC connections that aren't using TLS, configure the cluster to reject all non-TLS connections. See xref:security:authorization/gbac/gbac_dp.adoc[].
* `oidc.require_tls` (default `true`) controls whether Redpanda SQL uses HTTPS when contacting the identity provider: the OIDC discovery document URL, the JWKS endpoint, and the token endpoint for the client-credentials flow. This setting does not gate TLS on the client's `psql` connection.

== Reconnect when a token expires

OIDC bearer tokens are short-lived. Redpanda SQL validates the token once at connection time and does not re-validate it over the lifetime of the session. After the token expires, the database session continues until it closes for some other reason, but new connections must present a fresh token. Obtain a new token from the identity provider and reconnect.

// TODO: Confirm the exact in-session behavior after a token expires. Source has
// a single validateToken call at oxla/src/net/postgres/states/wait_for_bearer_auth_state.cpp
// and no re-validation path, so "the session is unaffected until closed" appears
// correct, but please confirm and tighten with SME before publishing.

== Next steps

* xref:sql:manage/manage-access.adoc[Manage access]: how the admin grants per-user access after authentication.
* xref:sql:connect-to-sql/index.adoc[Connect to Redpanda SQL]: language-client connection guides.
97 changes: 97 additions & 0 deletions modules/sql/pages/manage/manage-access.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
= Manage access to Redpanda SQL
:description: Authentication and authorization model for Redpanda SQL — OIDC for authentication, deny-all by default, admin-issued GRANT for per-user table access.
:page-topic-type: concept
:personas: platform_admin

Redpanda SQL separates authentication and authorization:

* *Authentication* into Redpanda SQL is handled by your OIDC identity provider, configured at the cluster level.
* *Authorization* — the data a user can read after they authenticate — is enforced inside Redpanda SQL by table-level `GRANT` statements that an admin issues. Redpanda SQL is deny-all by default.

This page describes the admin-side model. For the client-side connection guide, see xref:sql:connect-to-sql/connect-with-oidc.adoc[].

== Authentication

OIDC authenticates the user to Redpanda SQL. Configuring OIDC is not specific to Redpanda SQL — it is a cluster-level configuration. See xref:security:authorization/gbac/gbac_dp.adoc[Configure GBAC in the Data Plane] for the setup steps.

When a user successfully authenticates with an OIDC bearer token, Redpanda SQL provisions the user automatically on first sign-in.

[CAUTION]
====
// TODO: Tighten this caution wording with engineering before publishing
// (qa-questions.md #17). The underlying issue is OXLA-9382 — concurrent
// CREATE ROLE under OIDC auto-provisioning corrupts the privilege cache.

Concurrent first-time sign-ins from a connection pool can trigger duplicate role creation under OIDC auto-provisioning, which can corrupt the privilege cache. To avoid this, stagger first-time sign-ins for new OIDC users, or have an admin pre-create the role before the user signs in. Track https://redpandadata.atlassian.net/browse/OXLA-9382[OXLA-9382^] for fix status.
====

// TODO: Confirm validated IdP coverage with engineering (qa-questions.md #16).
// Add an "IdPs validated for Redpanda SQL" section listing the providers
// engineering has explicitly tested (Keycloak is confirmed; Okta, Microsoft
// Entra ID, Auth0, and Google have not yet been confirmed for SQL).

== How queries reach the underlying topics

All Redpanda SQL queries — regardless of which user issued them — connect to the underlying Redpanda cluster as a single super-user SASL credential associated with the default Redpanda catalog (`default_redpanda_connection`). The super-user credential is provisioned automatically when Redpanda SQL is enabled.

This means:

* Kafka ACLs do not gate query-time access — every query reaches the topics under the super-user SASL credential.
* The boundary that prevents users from reading data they should not see is enforced inside Redpanda SQL, by `GRANT` and `REVOKE` on the SQL tables themselves.

== Authorization

// TODO: Confirm the GRANT mechanism with engineering (qa-questions.md #21).
// Specifically: does the SQL `GRANT` statement alone enforce per-user table
// access, or is an additional ACL / Kafka-side step required? Document the
// exact scope and granularity (table only, schema-wide, etc.) once confirmed.

// TODO: Add xref to GRANT, REVOKE, CREATE ROLE, ALTER ROLE, DROP ROLE
// reference pages once they exist. These statement reference pages do NOT
// exist yet under modules/reference/pages/sql/sql-statements/ — the SQL
// reference set currently covers CATALOG/STORAGE/TABLE DDL + DML only.
// Filing a follow-up DOC ticket for this coverage gap; the inline examples
// below are temporary until reference pages land.

// TODO: Document the schema-visibility / creation-privilege policy changes
// from oxla PR #6793: system.catalogs and SHOW CATALOGS are now filtered by
// schema USAGE (previously CONNECT only); non-superuser catalog/storage
// creation now requires CREATE on the schema. The policy half of #6793 is
// not covered by DOC-2134's scope (that ticket covers the system.catalogs
// schema reshape but not the ACL-policy tightening). No DOC ticket yet.

// TODO: Document the grants surface from oxla PR #6858: new
// information_schema.role_external_relation_grants view; ALL PRIVILEGES on
// external sources resolves to SELECT-only; REVOKE on a non-wildcard pattern
// matching nothing now errors (was previously a silent no-op); catalog-level
// grants now appear in information_schema.role_table_grants. No DOC ticket
// yet — file a follow-up for this when the GRANT/REVOKE reference pages are
// scoped, since the two work-streams are related.

Redpanda SQL is deny-all by default. After a user authenticates, they cannot read any table until the admin explicitly grants access. To allow a user to query a table:

. Create a role for the user.
+
[source,sql]
----
CREATE ROLE analyst LOGIN PASSWORD '<password>';
----

. Grant the role `SELECT` on the table.
+
[source,sql]
----
GRANT SELECT ON TABLE default_redpanda_connection=>orders TO analyst;
----

. To remove access, revoke the privilege.
+
[source,sql]
----
REVOKE SELECT ON TABLE default_redpanda_connection=>orders FROM analyst;
----

== Next steps

* xref:sql:connect-to-sql/connect-with-oidc.adoc[Connect with OIDC]: how a user obtains a bearer token and connects to Redpanda SQL.
* xref:security:authorization/gbac/gbac_dp.adoc[Configure GBAC in the Data Plane]: cluster-level OIDC and GBAC setup.