From 0a44900d97ec68ca1f9bef1bca2863e333751f8d Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Thu, 7 May 2026 20:46:09 -0700 Subject: [PATCH 01/12] Draft OIDC content --- modules/ROOT/nav.adoc | 2 + .../connect-to-sql/connect-with-oidc.adoc | 83 +++++++++++++++++++ modules/sql/pages/manage/manage-access.adoc | 75 +++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 modules/sql/pages/connect-to-sql/connect-with-oidc.adoc create mode 100644 modules/sql/pages/manage/manage-access.adoc diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 142049a66..2dc2961ab 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -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] diff --git a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc new file mode 100644 index 000000000..65a91483e --- /dev/null +++ b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc @@ -0,0 +1,83 @@ += Connect to Redpanda SQL with OIDC +:description: Authenticate to Redpanda SQL using a bearer token issued by your OIDC identity provider. +:page-topic-type: how-to +:personas: app_developer, data_engineer, platform_admin +:learning-objective-1: Obtain an OIDC bearer token from your identity provider +:learning-objective-2: Connect to Redpanda SQL with the token using psql or a PostgreSQL client driver + +Authenticate to Redpanda SQL using a bearer token issued by your OIDC identity provider. OIDC authenticates the user to Redpanda SQL; per-user data access is enforced 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 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. + +== Obtain a bearer token + +Redpanda SQL accepts bearer tokens issued by any OIDC-compliant identity provider configured on the cluster. The token flow you use depends on your scenario: + +* *Authorization Code flow* — for users connecting interactively (for example, through a developer workstation). +* *Client Credentials flow* — for service-to-service connections (for example, a scheduled job or BI tool service account). + +// TODO: Confirm the validated IdP coverage with engineering (qa-questions.md #16). +// E2E tests use Keycloak; Okta, Microsoft Entra ID, Auth0, and Google have not +// yet been confirmed as explicitly tested for Redpanda SQL bearer-token auth. +// List validated IdPs here once confirmed. + +Refer to your identity provider's documentation for the exact token request. The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) so Redpanda SQL can verify it. + +== Connect with psql + +Pass the bearer token in place of the SCRAM password when you connect: + +// TODO: Confirm the exact `psql` connection-string format with engineering. Some +// engines accept the token via the `password` field over a TLS connection; +// others require an explicit OAUTHBEARER mechanism. Document the supported +// pattern once confirmed. + +[source,bash] +---- +PGPASSWORD="$BEARER_TOKEN" psql "host= port= dbname=oxla user= sslmode=require" +---- + +The `` value is the user identifier from your OIDC token (typically the `sub` or `preferred_username` claim, depending on your IdP). + +== Connect with a PostgreSQL client driver + +For language clients, set the connection password to the bearer token. The example below uses Python's `psycopg2`: + +[source,python] +---- +import os +import psycopg2 + +conn = psycopg2.connect( + host="", + port=, + dbname="oxla", + user="", + password=os.environ["BEARER_TOKEN"], + sslmode="require", +) +---- + +For more language-client examples, see xref:sql:connect-to-sql/index.adoc[Connect to Redpanda SQL]. + +== Token refresh + +OIDC bearer tokens expire. When a token expires, Redpanda SQL closes the connection. Your client must obtain a fresh token from the identity provider and reconnect. + +// TODO: Confirm whether Redpanda SQL supports any in-session token refresh +// (for example, re-presenting a new token on an existing connection) or whether +// reconnection is always required. + +== 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. diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc new file mode 100644 index 000000000..4b69c55ae --- /dev/null +++ b/modules/sql/pages/manage/manage-access.adoc @@ -0,0 +1,75 @@ += 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. + +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 ''; +---- + +. 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. From b59e971f113fa8fa73550a70a75a284d0ff3163a Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Thu, 14 May 2026 16:08:59 -0700 Subject: [PATCH 02/12] Update draft with source findings and TODO --- .../connect-to-sql/connect-with-oidc.adoc | 109 +++++++++++++----- modules/sql/pages/manage/manage-access.adoc | 22 ++++ 2 files changed, 99 insertions(+), 32 deletions(-) diff --git a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc index 65a91483e..5c5761d55 100644 --- a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc +++ b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc @@ -1,11 +1,11 @@ = Connect to Redpanda SQL with OIDC -:description: Authenticate to Redpanda SQL using a bearer token issued by your OIDC identity provider. +:description: Authenticate to Redpanda SQL using a bearer token or client credentials issued by your OIDC identity provider. :page-topic-type: how-to :personas: app_developer, data_engineer, platform_admin -:learning-objective-1: Obtain an OIDC bearer token from your identity provider -:learning-objective-2: Connect to Redpanda SQL with the token using psql or a PostgreSQL client driver +: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 a bearer token issued by your OIDC identity provider. OIDC authenticates the user to Redpanda SQL; per-user data access is enforced separately. See xref:sql:manage/manage-access.adoc[] for the access model. +Authenticate to Redpanda SQL using OIDC instead of a SCRAM password. The cluster validates the credential locally against the configured identity provider, and the session identity is set from the principal claim in the token (not from the `user=` field in the connection string). Per-user data access is granted separately by the cluster admin. See xref:sql:manage/manage-access.adoc[] for the access model. After completing these steps, you will be able to: @@ -17,41 +17,50 @@ After completing these steps, you will be able to: * A Redpanda 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 ` for each user, where `` 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. -== Obtain a bearer token +== Authentication modes -Redpanda SQL accepts bearer tokens issued by any OIDC-compliant identity provider configured on the cluster. The token flow you use depends on your scenario: +Redpanda SQL accepts two OIDC authentication modes, selected by the connection-string `options` parameter: -* *Authorization Code flow* — for users connecting interactively (for example, through a developer workstation). -* *Client Credentials flow* — for service-to-service connections (for example, a scheduled job or BI tool service account). +[cols="<25%,<30%,<45%",options="header"] +|=== +|Mode |`options` value |When to use -// TODO: Confirm the validated IdP coverage with engineering (qa-questions.md #16). -// E2E tests use Keycloak; Okta, Microsoft Entra ID, Auth0, and Google have not -// yet been confirmed as explicitly tested for Redpanda SQL bearer-token auth. -// List validated IdPs here once confirmed. +|Bearer token +|`auth_method=bearer` +|You already hold a 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). -Refer to your identity provider's documentation for the exact token request. The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) so Redpanda SQL can verify it. +|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. +|=== -== Connect with psql +If `options` is omitted, Redpanda SQL defaults to SCRAM password authentication. A bearer token presented in the password field without `auth_method=bearer` is treated as a SCRAM password and the connection fails. -Pass the bearer token in place of the SCRAM password when you connect: +The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) and must be signed with one of the algorithms Redpanda SQL accepts: `RS256`, `RS384`, `RS512`, or `ES256`. Tokens signed with `alg: none` are rejected. -// TODO: Confirm the exact `psql` connection-string format with engineering. Some -// engines accept the token via the `password` field over a TLS connection; -// others require an explicit OAUTHBEARER mechanism. Document the supported -// pattern once confirmed. +// 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. -[source,bash] ----- -PGPASSWORD="$BEARER_TOKEN" psql "host= port= dbname=oxla user= sslmode=require" ----- +// 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. -The `` value is the user identifier from your OIDC token (typically the `sub` or `preferred_username` claim, depending on your IdP). +== Connect with a bearer token -== Connect with a PostgreSQL client driver +Set `options=auth_method=bearer` in the connection string and pass the token in the password field. The `user=` field is ignored — Redpanda SQL sets the session identity from the principal claim in the token. -For language clients, set the connection password to the bearer token. The example below uses Python's `psycopg2`: +.psql +[source,bash] +---- +PGPASSWORD="$BEARER_TOKEN" \ + psql "host= port= dbname=oxla user=ignored options='auth_method=bearer' sslmode=require" +---- +.Python (psycopg2) [source,python] ---- import os @@ -61,21 +70,57 @@ conn = psycopg2.connect( host="", port=, dbname="oxla", - user="", + 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]. -== Token refresh +[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= port= dbname=oxla user= 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. + +== TLS + +Bearer tokens and client secrets are transmitted in the password field of the PostgreSQL startup message. To prevent these credentials from being captured 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. If you want OIDC connections to be rejected when they aren't using TLS, configure the cluster so that non-TLS connections are rejected for all clients. 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. + +== Token expiry -OIDC bearer tokens expire. When a token expires, Redpanda SQL closes the connection. Your client must obtain a fresh token from the identity provider and reconnect. +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; new connections must present a fresh token. Clients are responsible for obtaining a new token from the identity provider and reconnecting. -// TODO: Confirm whether Redpanda SQL supports any in-session token refresh -// (for example, re-presenting a new token on an existing connection) or whether -// reconnection is always required. +// 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 diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index 4b69c55ae..82b6bc123 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -46,6 +46,28 @@ This means: // 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. From da74bd4b42c9ea3e340cd95e296ee8a5c4dc0292 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Thu, 14 May 2026 16:34:14 -0700 Subject: [PATCH 03/12] Review pass --- .../connect-to-sql/connect-with-oidc.adoc | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc index 5c5761d55..a29baf24f 100644 --- a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc +++ b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc @@ -1,11 +1,11 @@ = Connect to Redpanda SQL with OIDC -:description: Authenticate to Redpanda SQL using a bearer token or client credentials issued by your OIDC identity provider. +: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 OIDC instead of a SCRAM password. The cluster validates the credential locally against the configured identity provider, and the session identity is set from the principal claim in the token (not from the `user=` field in the connection string). Per-user data access is granted separately by the cluster admin. See xref:sql:manage/manage-access.adoc[] for the access model. +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: @@ -14,7 +14,7 @@ After completing these steps, you will be able to: == Prerequisites -* A Redpanda BYOC cluster on AWS with Redpanda SQL enabled. See xref:sql:get-started/deploy-sql-cluster.adoc[Enable Redpanda SQL]. +* 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 ` for each user, where `` 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. @@ -29,16 +29,16 @@ Redpanda SQL accepts two OIDC authentication modes, selected by the connection-s |Bearer token |`auth_method=bearer` -|You already hold a 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). +|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 `options` is omitted, Redpanda SQL defaults to SCRAM password authentication. A bearer token presented in the password field without `auth_method=bearer` is treated as a SCRAM password and the connection fails. +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 be signed with one of the algorithms Redpanda SQL accepts: `RS256`, `RS384`, `RS512`, or `ES256`. Tokens signed with `alg: none` are rejected. +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/); @@ -51,7 +51,7 @@ The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) and == Connect with a bearer token -Set `options=auth_method=bearer` in the connection string and pass the token in the password field. The `user=` field is ignored — Redpanda SQL sets the session identity from the principal claim in the 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] @@ -104,18 +104,18 @@ PGPASSWORD="$CLIENT_SECRET" \ // oxla/src/network/leader_factory.cpp:15. The RFC quotes 5s. Document the correct // value once verified with SME. -== TLS +== Use TLS on OIDC connections -Bearer tokens and client secrets are transmitted in the password field of the PostgreSQL startup message. To prevent these credentials from being captured in transit, set `sslmode=require` on every OIDC connection. +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. If you want OIDC connections to be rejected when they aren't using TLS, configure the cluster so that non-TLS connections are rejected for all clients. See xref:security:authorization/gbac/gbac_dp.adoc[]. +* 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. -== Token expiry +== 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; new connections must present a fresh token. Clients are responsible for obtaining a new token from the identity provider and reconnecting. +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 From 0b415545230daa8587794b28876c95b3d6c13975 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 12:13:36 -0700 Subject: [PATCH 04/12] Review pass --- .../connect-to-sql/connect-with-oidc.adoc | 31 ++++-- modules/sql/pages/manage/manage-access.adoc | 94 ++++++++++--------- 2 files changed, 74 insertions(+), 51 deletions(-) diff --git a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc index a29baf24f..19cf35a90 100644 --- a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc +++ b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc @@ -5,7 +5,7 @@ :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. +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]. The session identity comes 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: @@ -14,10 +14,10 @@ After completing these steps, you will be able to: == Prerequisites -* A Redpanda glossterm:BYOC[] cluster on AWS with Redpanda SQL enabled. See xref:sql:get-started/deploy-sql-cluster.adoc[Enable Redpanda SQL]. +* A Redpanda 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 ` for each user, where `` 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. +* A user or service account assigned a role with the *SQL: Access* or *SQL: Manage* permission in Redpanda Cloud's data-plane RBAC. Redpanda Cloud provisions a corresponding user in the SQL engine when the role is assigned. To assign roles, go to *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. == Authentication modes @@ -29,7 +29,7 @@ Redpanda SQL accepts two OIDC authentication modes, selected by the connection-s |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). +|You already hold a JSON Web Token (JWT) issued by the identity provider (for example, from an Authorization Code flow or a cluster-side workflow). |Client credentials |`auth_method=client_secret` @@ -51,6 +51,8 @@ The token must include the standard OIDC claims (`sub`, `aud`, `iss`, `exp`) and == Connect with a bearer token +Use bearer-token authentication for human users who hold a JWT issued by your identity provider. For Redpanda Cloud users, `rpk cloud auth token` returns a token you can pass directly; see xref:sql:get-started/sql-quickstart.adoc[Quickstart] for the end-to-end setup. + 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 @@ -83,13 +85,26 @@ cur.execute("SELECT current_user") 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. -==== +// TODO: OXLA-9382 (concurrent first-time login via connection pool produces +// duplicate role entries in the distributed catalog) is marked Done in Jira +// but has no fixVersions set. Confirm with SME the fix is in the GA 2026-05-22 +// build before publishing this note. If confirmed in GA, delete this comment. +// If NOT confirmed, restore the user-facing NOTE below: +// +// [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 +Use client-credentials authentication for service-to-service connections: scheduled jobs, BI tools, or other automated clients that can't perform interactive sign-in. Each service account has an OIDC client ID and client secret issued by your identity provider; Redpanda SQL exchanges those credentials for a token and validates it. + 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] diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index 82b6bc123..3d9bae81f 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -1,29 +1,20 @@ -= 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. += Manage Access to Redpanda SQL +:description: Authentication and authorization model for Redpanda SQL: OIDC, deny-all by default, admin GRANT for per-user access to topics and catalogs. :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. +* *Authorization* (the data a user can read after they authenticate) is enforced inside Redpanda SQL by `GRANT` statements that an admin issues on tables, Redpanda catalogs, and schemas. 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. +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. -==== +When a user is assigned a role with the *SQL: Access* or *SQL: Manage* permission in Redpanda Cloud's data-plane RBAC, Redpanda Cloud provisions a corresponding user in the SQL engine. No manual `CREATE USER` is required. To assign roles, go to *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. // TODO: Confirm validated IdP coverage with engineering (qa-questions.md #16). // Add an "IdPs validated for Redpanda SQL" section listing the providers @@ -32,20 +23,15 @@ Concurrent first-time sign-ins from a connection pool can trigger duplicate role == 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. +All Redpanda SQL queries connect to the underlying Redpanda cluster as a single super-user SASL credential associated with the default Redpanda catalog (`default_redpanda_catalog`), regardless of which user issued the query. 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. +* 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`. == 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 @@ -53,42 +39,64 @@ This means: // 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. +Redpanda SQL access is controlled by two role permissions in Redpanda Cloud's data-plane RBAC: -// 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. +* *SQL: Manage*: superuser access to the SQL engine. A user with this role can read all topics, create catalogs and tables, and grant access to other users. +* *SQL: Access*: regular user access. A user with this role can connect to the SQL engine but has no access to any catalog or table until a *SQL: Manage* user grants it. -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: +When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual `CREATE USER` is required. A *SQL: Manage* user then uses standard SQL `GRANT` statements to give the user access to the data they need. -. Create a role for the user. +. In Redpanda Cloud, assign a role with the *SQL: Access* permission to the user. Roles are managed in *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. + +. As a *SQL: Manage* user, grant `SELECT` on a topic surfaced through a Redpanda catalog. The user identifier is the email on the user's Redpanda Cloud account: + [source,sql] ---- -CREATE ROLE analyst LOGIN PASSWORD ''; +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' TO "alice@example.com"; ---- - -. Grant the role `SELECT` on the table. ++ +Or grant `SELECT` on multiple topics that match a wildcard pattern. The wildcard `*` is only allowed at the end of the pattern: ++ +[source,sql] +---- +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' TO "alice@example.com"; +---- ++ +To grant `SELECT` on every topic in a catalog, omit the relation pattern: + [source,sql] ---- -GRANT SELECT ON TABLE default_redpanda_connection=>orders TO analyst; +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog TO "alice@example.com"; ---- -. To remove access, revoke the privilege. +. To remove access, revoke the privilege: + [source,sql] ---- -REVOKE SELECT ON TABLE default_redpanda_connection=>orders FROM analyst; +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' FROM "alice@example.com"; +---- + +=== Grant behavior for Redpanda catalogs + +A few details affect how grants on Redpanda catalogs behave: + +* *Privilege type.* `SELECT` is the only privilege type that has effect on a Redpanda catalog. `GRANT ALL PRIVILEGES` on a catalog resolves to `SELECT` only. +* *REVOKE on a non-matching pattern.* `REVOKE SELECT ... \=> '_pattern_'` errors if the pattern matches no existing grant for the role. The catalog-level form (no pattern) is idempotent and silently no-ops if no grants exist, so cleanup scripts can safely run it. +* *Inspecting current grants.* To see which roles have grants on which catalogs and relations, query `information_schema.role_external_relation_grants`. Catalog-level grants also appear as rows in `information_schema.role_table_grants`, where `table_name` is the catalog name. + +=== Schema-level privileges for Redpanda catalogs and SQL storage + +Redpanda catalogs and SQL storage definitions live in a schema (`public` by default). To work with them, a user needs schema-level privileges in addition to any per-relation grants: + +* `USAGE` on the schema: required to see catalogs in `system.catalogs` and `SHOW CATALOGS`, and to reference any object in the schema by name. Without `USAGE`, the catalog is hidden from the user. +* `CREATE` on the schema: required for a non-superuser to run `CREATE REDPANDA CATALOG` or `CREATE STORAGE` in that schema. + +Grant schema-level privileges with the `ON SCHEMA` form: + +[source,sql] +---- +GRANT USAGE ON SCHEMA public TO "alice@example.com"; +GRANT CREATE ON SCHEMA public TO "alice@example.com"; ---- == Next steps From 58b473f3afeaa41264bec1928c34b4b816fa581c Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 12:31:36 -0700 Subject: [PATCH 05/12] Add reference docs for GRANT, REVOKE, ROLE/USER --- modules/ROOT/nav.adoc | 5 + .../pages/sql/sql-statements/alter-role.adoc | 51 ++++++++ .../pages/sql/sql-statements/create-role.adoc | 43 +++++++ .../pages/sql/sql-statements/drop-role.adoc | 48 ++++++++ .../pages/sql/sql-statements/grant.adoc | 116 ++++++++++++++++++ .../pages/sql/sql-statements/revoke.adoc | 82 +++++++++++++ modules/sql/pages/manage/manage-access.adoc | 17 +-- 7 files changed, 354 insertions(+), 8 deletions(-) create mode 100644 modules/reference/pages/sql/sql-statements/alter-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/create-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/drop-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/grant.adoc create mode 100644 modules/reference/pages/sql/sql-statements/revoke.adoc diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 2dc2961ab..c1d0d93c3 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -541,14 +541,19 @@ *** xref:reference:sql/sql-statements/index.adoc[Statements] **** xref:reference:sql/sql-statements/keywords.adoc[] **** xref:reference:sql/sql-statements/alter-redpanda-catalog.adoc[] +**** xref:reference:sql/sql-statements/alter-role.adoc[] **** xref:reference:sql/sql-statements/alter-storage.adoc[] **** xref:reference:sql/sql-statements/alter-table.adoc[] **** xref:reference:sql/sql-statements/create-redpanda-catalog.adoc[] +**** xref:reference:sql/sql-statements/create-role.adoc[] **** xref:reference:sql/sql-statements/create-storage.adoc[] **** xref:reference:sql/sql-statements/create-table.adoc[] **** xref:reference:sql/sql-statements/drop-redpanda-catalog.adoc[] +**** xref:reference:sql/sql-statements/drop-role.adoc[] **** xref:reference:sql/sql-statements/drop-storage.adoc[] **** xref:reference:sql/sql-statements/drop-table.adoc[] +**** xref:reference:sql/sql-statements/grant.adoc[] +**** xref:reference:sql/sql-statements/revoke.adoc[] **** xref:reference:sql/sql-statements/select.adoc[] **** xref:reference:sql/sql-statements/copy-to.adoc[] **** xref:reference:sql/sql-statements/describe.adoc[] diff --git a/modules/reference/pages/sql/sql-statements/alter-role.adoc b/modules/reference/pages/sql/sql-statements/alter-role.adoc new file mode 100644 index 000000000..9de7be18c --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/alter-role.adoc @@ -0,0 +1,51 @@ += ALTER ROLE +:description: The ALTER ROLE statement changes the password or superuser status of an existing role. +:page-topic-type: reference + +The `ALTER ROLE` statement changes the password or superuser status of an existing role. `ALTER USER` is a synonym for `ALTER ROLE`. + +A superuser can alter any role. A non-superuser can alter their own role (for example, to change their own password) but cannot change their own superuser status. + +== Syntax + +[source,sql] +---- +ALTER { ROLE | USER } role_name [WITH] + [ PASSWORD 'password' ] + [ SUPERUSER | NOSUPERUSER ]; +---- + +* `role_name`: Name of the existing role to alter. `CURRENT_USER` and `CURRENT_ROLE` are allowed and refer to the current session role. +* `PASSWORD '_password_'`: Optional. The new password. Must be a non-empty string literal if specified. +* `SUPERUSER`: Optional. Promotes the role to superuser. Requires superuser privileges on the current session. +* `NOSUPERUSER`: Optional. Removes superuser status from the role. The protected system superuser cannot be demoted. +* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. + +== Examples + +Change the password for an existing role: + +[source,sql] +---- +ALTER ROLE alice WITH PASSWORD 'new_secret'; +---- + +Change your own password (as the current user): + +[source,sql] +---- +ALTER USER CURRENT_USER WITH PASSWORD 'new_secret'; +---- + +Promote a regular user to superuser: + +[source,sql] +---- +ALTER ROLE alice SUPERUSER; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] +* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/create-role.adoc b/modules/reference/pages/sql/sql-statements/create-role.adoc new file mode 100644 index 000000000..374d4cebd --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/create-role.adoc @@ -0,0 +1,43 @@ += CREATE ROLE +:description: The CREATE ROLE statement creates a new role (user) in Redpanda SQL. Only a superuser can create roles. +:page-topic-type: reference + +The `CREATE ROLE` statement creates a new role in Redpanda SQL. `CREATE USER` is a synonym for `CREATE ROLE`. Only a superuser can run this statement. + +A password is required when creating a role. + +== Syntax + +[source,sql] +---- +CREATE { ROLE | USER } role_name [WITH] PASSWORD 'password' [SUPERUSER | NOSUPERUSER]; +---- + +* `role_name`: Name of the new role. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. +* `PASSWORD '_password_'`: Required. The password must be a non-empty string literal. +* `SUPERUSER`: Optional. Grants superuser privileges to the new role. Superusers bypass authorization checks. +* `NOSUPERUSER`: Optional. Explicitly marks the role as a non-superuser. This is the default if neither `SUPERUSER` nor `NOSUPERUSER` is specified. +* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. + +== Examples + +Create a regular user with a password: + +[source,sql] +---- +CREATE ROLE alice WITH PASSWORD 'secret123'; +---- + +Create a superuser: + +[source,sql] +---- +CREATE USER admin_user WITH PASSWORD 'admin_secret' SUPERUSER; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] +* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] +* xref:reference:sql/sql-statements/grant.adoc[GRANT] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/drop-role.adoc b/modules/reference/pages/sql/sql-statements/drop-role.adoc new file mode 100644 index 000000000..570c41ca0 --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/drop-role.adoc @@ -0,0 +1,48 @@ += DROP ROLE +:description: The DROP ROLE statement removes an existing role. The role cannot own objects or hold grants when dropped. +:page-topic-type: reference + +The `DROP ROLE` statement removes an existing role from Redpanda SQL. `DROP USER` is a synonym for `DROP ROLE`. Only a superuser can run this statement. + +A role cannot be dropped while it owns objects or holds privilege grants. Reassign or remove those objects and revoke the grants first, then drop the role. + +== Syntax + +[source,sql] +---- +DROP { ROLE | USER } [IF EXISTS] role_name; +---- + +* `role_name`: Name of the role to drop. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. The role running the statement cannot drop itself, and the protected system superuser cannot be dropped. +* `IF EXISTS`: Optional. Prevents an error if the role does not exist. + +== Examples + +Drop an existing role: + +[source,sql] +---- +DROP ROLE alice; +---- + +Drop a role only if it exists: + +[source,sql] +---- +DROP USER IF EXISTS legacy_account; +---- + +If the role has dependent grants or owned objects, the statement fails with an error listing the objects. Reassign or remove those objects first: + +[source,sql] +---- +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; +DROP ROLE alice; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] +* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] +* xref:reference:sql/sql-statements/revoke.adoc[REVOKE] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/grant.adoc b/modules/reference/pages/sql/sql-statements/grant.adoc new file mode 100644 index 000000000..ff106bee8 --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/grant.adoc @@ -0,0 +1,116 @@ += GRANT +:description: The GRANT statement assigns privileges on a database object to a role. Only a superuser can grant privileges. +:page-topic-type: reference + +The `GRANT` statement assigns privileges on a database object to a role. Only a superuser can grant privileges. + +Redpanda SQL is deny-all by default. A role has no access to any object until a superuser grants it. For the broader access model, see xref:sql:manage/manage-access.adoc[]. + +== Privilege levels + +A privilege is associated with a level. Each level supports a specific set of privilege types: + +[cols="<25%,<40%,<35%",options="header"] +|=== +|Level |Object |Privilege types + +|Database +|The Redpanda SQL database +|`CONNECT` + +|Schema +|A schema in the database +|`USAGE`, `CREATE` + +|Table +|A native SQL table +|`SELECT`, `INSERT`, `UPDATE`, `DELETE` + +|External source +|A Redpanda catalog or SQL storage definition +|`SELECT` +|=== + +`ALL PRIVILEGES` resolves to the full set of privilege types at the given level. For external sources, `ALL PRIVILEGES` resolves to `SELECT` only. + +== Syntax + +=== Grant on a table + +[source,sql] +---- +GRANT { privilege [, ...] | ALL [PRIVILEGES] } ON TABLE table_name TO role_name; +---- + +=== Grant on an external source + +A Redpanda catalog (the object created by `CREATE REDPANDA CATALOG`) and a SQL storage definition (the object created by `CREATE STORAGE`) are both external sources. + +The catalog-level form grants the privilege on every relation reachable through the source. The pattern form scopes the grant to relations whose name matches the pattern. + +[source,sql] +---- +GRANT { SELECT | ALL [PRIVILEGES] } ON EXTERNAL SOURCE source_name TO role_name; +GRANT { SELECT | ALL [PRIVILEGES] } ON EXTERNAL SOURCE source_name => 'pattern' TO role_name; +---- + +* `pattern`: A string literal that matches a relation name. The wildcard `*` is only allowed at the end of the pattern (for example, `'orders_*'`). + +=== Grant on a schema + +[source,sql] +---- +GRANT { privilege [, ...] | ALL [PRIVILEGES] } ON SCHEMA schema_name TO role_name; +---- + +Schema-level privileges affect visibility and creation rights for objects in the schema. Without `USAGE` on a schema, a user cannot see catalogs in that schema or reference objects in it by name. + +=== Grant on the database + +[source,sql] +---- +GRANT CONNECT ON DATABASE database_name TO role_name; +---- + +== Examples + +Grant `SELECT` on a topic surfaced through a Redpanda catalog: + +[source,sql] +---- +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' TO alice; +---- + +Grant `SELECT` on every topic in a Redpanda catalog: + +[source,sql] +---- +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog TO alice; +---- + +Grant `SELECT` on every topic whose name starts with `orders_`: + +[source,sql] +---- +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' TO alice; +---- + +Grant `USAGE` on a schema so the user can see the catalogs and storage in it: + +[source,sql] +---- +GRANT USAGE ON SCHEMA public TO alice; +---- + +Grant `SELECT` and `INSERT` on a native SQL table: + +[source,sql] +---- +GRANT SELECT, INSERT ON TABLE summary_data TO alice; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/revoke.adoc[REVOKE] +* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/revoke.adoc b/modules/reference/pages/sql/sql-statements/revoke.adoc new file mode 100644 index 000000000..e13e3fe02 --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/revoke.adoc @@ -0,0 +1,82 @@ += REVOKE +:description: The REVOKE statement removes privileges that were previously granted to a role. Only a superuser can revoke privileges. +:page-topic-type: reference + +The `REVOKE` statement removes privileges that were previously granted to a role with xref:reference:sql/sql-statements/grant.adoc[GRANT]. Only a superuser can revoke privileges. + +For the privilege levels and types that apply to each object, see xref:reference:sql/sql-statements/grant.adoc#_privilege_levels[GRANT > Privilege levels]. + +== Syntax + +=== Revoke on a table + +[source,sql] +---- +REVOKE { privilege [, ...] | ALL [PRIVILEGES] } ON TABLE table_name FROM role_name; +---- + +=== Revoke on an external source + +[source,sql] +---- +REVOKE { SELECT | ALL [PRIVILEGES] } ON EXTERNAL SOURCE source_name FROM role_name; +REVOKE { SELECT | ALL [PRIVILEGES] } ON EXTERNAL SOURCE source_name => 'pattern' FROM role_name; +---- + +* `pattern`: A string literal that matches a relation name. The wildcard `*` is only allowed at the end of the pattern. + +=== Revoke on a schema + +[source,sql] +---- +REVOKE { privilege [, ...] | ALL [PRIVILEGES] } ON SCHEMA schema_name FROM role_name; +---- + +=== Revoke on the database + +[source,sql] +---- +REVOKE CONNECT ON DATABASE database_name FROM role_name; +---- + +== Behavior + +* *Pattern that matches no existing grant.* When revoking on an external source with a non-wildcard pattern, the statement errors if the pattern does not match any existing grant for the role. List current grants with `SELECT * FROM information_schema.role_external_relation_grants`. +* *Catalog-level revoke is idempotent.* The catalog-level form (no pattern) is idempotent and silently no-ops if no grants exist for the role on that source. Cleanup scripts can safely run it. +* *Wildcard grants cannot be partially revoked.* If a role has a wildcard grant (for example `'*'` or `'orders_*'`), you cannot punch a hole in it. Revoke the wildcard grant in full, then re-grant the narrower pattern you want. + +== Examples + +Revoke `SELECT` on a single topic: + +[source,sql] +---- +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' FROM alice; +---- + +Revoke a wildcard grant: + +[source,sql] +---- +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' FROM alice; +---- + +Revoke all grants on a catalog: + +[source,sql] +---- +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; +---- + +Revoke `USAGE` on a schema: + +[source,sql] +---- +REVOKE USAGE ON SCHEMA public FROM alice; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/grant.adoc[GRANT] +* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index 3d9bae81f..c32040a40 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -32,19 +32,12 @@ This means: == Authorization -// 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. - Redpanda SQL access is controlled by two role permissions in Redpanda Cloud's data-plane RBAC: * *SQL: Manage*: superuser access to the SQL engine. A user with this role can read all topics, create catalogs and tables, and grant access to other users. * *SQL: Access*: regular user access. A user with this role can connect to the SQL engine but has no access to any catalog or table until a *SQL: Manage* user grants it. -When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual `CREATE USER` is required. A *SQL: Manage* user then uses standard SQL `GRANT` statements to give the user access to the data they need. +When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual xref:reference:sql/sql-statements/create-role.adoc[CREATE USER] is required. A *SQL: Manage* user then uses standard SQL xref:reference:sql/sql-statements/grant.adoc[GRANT] statements to give the user access to the data they need. . In Redpanda Cloud, assign a role with the *SQL: Access* permission to the user. Roles are managed in *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. @@ -103,3 +96,11 @@ GRANT CREATE ON SCHEMA public TO "alice@example.com"; * 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. + +== Suggested reading + +* xref:reference:sql/sql-statements/grant.adoc[GRANT] +* xref:reference:sql/sql-statements/revoke.adoc[REVOKE] +* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] +* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] +* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] From fef34e8922e36b47ad8115b0e87ff5db5c5a3bfd Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 12:40:03 -0700 Subject: [PATCH 06/12] Preference for USER instead of ROLE --- modules/ROOT/nav.adoc | 6 +-- .../pages/sql/sql-statements/alter-role.adoc | 51 ------------------- .../pages/sql/sql-statements/alter-user.adoc | 51 +++++++++++++++++++ .../pages/sql/sql-statements/create-role.adoc | 43 ---------------- .../pages/sql/sql-statements/create-user.adoc | 48 +++++++++++++++++ .../pages/sql/sql-statements/drop-role.adoc | 48 ----------------- .../pages/sql/sql-statements/drop-user.adoc | 48 +++++++++++++++++ .../pages/sql/sql-statements/grant.adoc | 2 +- .../pages/sql/sql-statements/revoke.adoc | 4 +- modules/sql/pages/manage/manage-access.adoc | 8 +-- 10 files changed, 157 insertions(+), 152 deletions(-) delete mode 100644 modules/reference/pages/sql/sql-statements/alter-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/alter-user.adoc delete mode 100644 modules/reference/pages/sql/sql-statements/create-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/create-user.adoc delete mode 100644 modules/reference/pages/sql/sql-statements/drop-role.adoc create mode 100644 modules/reference/pages/sql/sql-statements/drop-user.adoc diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index c1d0d93c3..8980a9fea 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -541,17 +541,17 @@ *** xref:reference:sql/sql-statements/index.adoc[Statements] **** xref:reference:sql/sql-statements/keywords.adoc[] **** xref:reference:sql/sql-statements/alter-redpanda-catalog.adoc[] -**** xref:reference:sql/sql-statements/alter-role.adoc[] **** xref:reference:sql/sql-statements/alter-storage.adoc[] **** xref:reference:sql/sql-statements/alter-table.adoc[] +**** xref:reference:sql/sql-statements/alter-user.adoc[] **** xref:reference:sql/sql-statements/create-redpanda-catalog.adoc[] -**** xref:reference:sql/sql-statements/create-role.adoc[] **** xref:reference:sql/sql-statements/create-storage.adoc[] **** xref:reference:sql/sql-statements/create-table.adoc[] +**** xref:reference:sql/sql-statements/create-user.adoc[] **** xref:reference:sql/sql-statements/drop-redpanda-catalog.adoc[] -**** xref:reference:sql/sql-statements/drop-role.adoc[] **** xref:reference:sql/sql-statements/drop-storage.adoc[] **** xref:reference:sql/sql-statements/drop-table.adoc[] +**** xref:reference:sql/sql-statements/drop-user.adoc[] **** xref:reference:sql/sql-statements/grant.adoc[] **** xref:reference:sql/sql-statements/revoke.adoc[] **** xref:reference:sql/sql-statements/select.adoc[] diff --git a/modules/reference/pages/sql/sql-statements/alter-role.adoc b/modules/reference/pages/sql/sql-statements/alter-role.adoc deleted file mode 100644 index 9de7be18c..000000000 --- a/modules/reference/pages/sql/sql-statements/alter-role.adoc +++ /dev/null @@ -1,51 +0,0 @@ -= ALTER ROLE -:description: The ALTER ROLE statement changes the password or superuser status of an existing role. -:page-topic-type: reference - -The `ALTER ROLE` statement changes the password or superuser status of an existing role. `ALTER USER` is a synonym for `ALTER ROLE`. - -A superuser can alter any role. A non-superuser can alter their own role (for example, to change their own password) but cannot change their own superuser status. - -== Syntax - -[source,sql] ----- -ALTER { ROLE | USER } role_name [WITH] - [ PASSWORD 'password' ] - [ SUPERUSER | NOSUPERUSER ]; ----- - -* `role_name`: Name of the existing role to alter. `CURRENT_USER` and `CURRENT_ROLE` are allowed and refer to the current session role. -* `PASSWORD '_password_'`: Optional. The new password. Must be a non-empty string literal if specified. -* `SUPERUSER`: Optional. Promotes the role to superuser. Requires superuser privileges on the current session. -* `NOSUPERUSER`: Optional. Removes superuser status from the role. The protected system superuser cannot be demoted. -* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. - -== Examples - -Change the password for an existing role: - -[source,sql] ----- -ALTER ROLE alice WITH PASSWORD 'new_secret'; ----- - -Change your own password (as the current user): - -[source,sql] ----- -ALTER USER CURRENT_USER WITH PASSWORD 'new_secret'; ----- - -Promote a regular user to superuser: - -[source,sql] ----- -ALTER ROLE alice SUPERUSER; ----- - -== Suggested reading - -* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] -* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] -* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/alter-user.adoc b/modules/reference/pages/sql/sql-statements/alter-user.adoc new file mode 100644 index 000000000..bc6008812 --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/alter-user.adoc @@ -0,0 +1,51 @@ += ALTER USER +:description: The ALTER USER statement changes the password or superuser status of an existing user. +:page-topic-type: reference + +The `ALTER USER` statement changes the password or superuser status of an existing user. `ALTER ROLE` is a synonym for `ALTER USER`, provided for PostgreSQL compatibility. + +A superuser can alter any user. A non-superuser can alter their own user (for example, to change their own password) but cannot change their own superuser status. + +== Syntax + +[source,sql] +---- +ALTER { USER | ROLE } user_name [WITH] + [ PASSWORD 'password' ] + [ SUPERUSER | NOSUPERUSER ]; +---- + +* `user_name`: Name of the existing user to alter. Use the reserved keyword `CURRENT_USER` or `CURRENT_ROLE` to alter the user running the statement. +* `PASSWORD 'password'`: Optional. The new password. Must be a non-empty string literal if specified. +* `SUPERUSER`: Optional. Promotes the user to superuser. Requires superuser privileges on the current session. +* `NOSUPERUSER`: Optional. Removes superuser status from the user. The protected system superuser cannot be demoted. +* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. + +== Examples + +Change the password for an existing user: + +[source,sql] +---- +ALTER USER alice WITH PASSWORD 'new_secret'; +---- + +Change your own password (as the current user): + +[source,sql] +---- +ALTER USER CURRENT_USER WITH PASSWORD 'new_secret'; +---- + +Promote a regular user to superuser: + +[source,sql] +---- +ALTER USER alice SUPERUSER; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] +* xref:reference:sql/sql-statements/drop-user.adoc[DROP USER] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/create-role.adoc b/modules/reference/pages/sql/sql-statements/create-role.adoc deleted file mode 100644 index 374d4cebd..000000000 --- a/modules/reference/pages/sql/sql-statements/create-role.adoc +++ /dev/null @@ -1,43 +0,0 @@ -= CREATE ROLE -:description: The CREATE ROLE statement creates a new role (user) in Redpanda SQL. Only a superuser can create roles. -:page-topic-type: reference - -The `CREATE ROLE` statement creates a new role in Redpanda SQL. `CREATE USER` is a synonym for `CREATE ROLE`. Only a superuser can run this statement. - -A password is required when creating a role. - -== Syntax - -[source,sql] ----- -CREATE { ROLE | USER } role_name [WITH] PASSWORD 'password' [SUPERUSER | NOSUPERUSER]; ----- - -* `role_name`: Name of the new role. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. -* `PASSWORD '_password_'`: Required. The password must be a non-empty string literal. -* `SUPERUSER`: Optional. Grants superuser privileges to the new role. Superusers bypass authorization checks. -* `NOSUPERUSER`: Optional. Explicitly marks the role as a non-superuser. This is the default if neither `SUPERUSER` nor `NOSUPERUSER` is specified. -* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. - -== Examples - -Create a regular user with a password: - -[source,sql] ----- -CREATE ROLE alice WITH PASSWORD 'secret123'; ----- - -Create a superuser: - -[source,sql] ----- -CREATE USER admin_user WITH PASSWORD 'admin_secret' SUPERUSER; ----- - -== Suggested reading - -* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] -* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] -* xref:reference:sql/sql-statements/grant.adoc[GRANT] -* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/create-user.adoc b/modules/reference/pages/sql/sql-statements/create-user.adoc new file mode 100644 index 000000000..e08ae5d2c --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/create-user.adoc @@ -0,0 +1,48 @@ += CREATE USER +:description: The CREATE USER statement creates a new user in Redpanda SQL with a required password. Only a superuser can create users. +:page-topic-type: reference + +The `CREATE USER` statement creates a new user in Redpanda SQL. `CREATE ROLE` is a synonym for `CREATE USER`, provided for PostgreSQL compatibility. Only a superuser can run this statement. + +A password is required when creating a user. + +[NOTE] +==== +Error messages from the SQL engine refer to users as "roles" (for example, `role "alice" does not exist`). This is consistent with PostgreSQL terminology and refers to the same object that `CREATE USER` produces. +==== + +== Syntax + +[source,sql] +---- +CREATE { USER | ROLE } user_name [WITH] PASSWORD 'password' [SUPERUSER | NOSUPERUSER]; +---- + +* `user_name`: Name of the new user. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. +* `PASSWORD 'password'`: Required. The password must be a non-empty string literal. +* `SUPERUSER`: Optional. Grants superuser privileges to the new user. Superusers bypass authorization checks. +* `NOSUPERUSER`: Optional. Explicitly marks the user as a non-superuser. Default when neither `SUPERUSER` nor `NOSUPERUSER` is specified. +* `WITH`: Optional. Has no effect; provided for PostgreSQL compatibility. + +== Examples + +Create a regular user with a password: + +[source,sql] +---- +CREATE USER alice WITH PASSWORD 'secret123'; +---- + +Create a superuser: + +[source,sql] +---- +CREATE USER admin_user WITH PASSWORD 'admin_secret' SUPERUSER; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/alter-user.adoc[ALTER USER] +* xref:reference:sql/sql-statements/drop-user.adoc[DROP USER] +* xref:reference:sql/sql-statements/grant.adoc[GRANT] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/drop-role.adoc b/modules/reference/pages/sql/sql-statements/drop-role.adoc deleted file mode 100644 index 570c41ca0..000000000 --- a/modules/reference/pages/sql/sql-statements/drop-role.adoc +++ /dev/null @@ -1,48 +0,0 @@ -= DROP ROLE -:description: The DROP ROLE statement removes an existing role. The role cannot own objects or hold grants when dropped. -:page-topic-type: reference - -The `DROP ROLE` statement removes an existing role from Redpanda SQL. `DROP USER` is a synonym for `DROP ROLE`. Only a superuser can run this statement. - -A role cannot be dropped while it owns objects or holds privilege grants. Reassign or remove those objects and revoke the grants first, then drop the role. - -== Syntax - -[source,sql] ----- -DROP { ROLE | USER } [IF EXISTS] role_name; ----- - -* `role_name`: Name of the role to drop. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. The role running the statement cannot drop itself, and the protected system superuser cannot be dropped. -* `IF EXISTS`: Optional. Prevents an error if the role does not exist. - -== Examples - -Drop an existing role: - -[source,sql] ----- -DROP ROLE alice; ----- - -Drop a role only if it exists: - -[source,sql] ----- -DROP USER IF EXISTS legacy_account; ----- - -If the role has dependent grants or owned objects, the statement fails with an error listing the objects. Reassign or remove those objects first: - -[source,sql] ----- -REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; -DROP ROLE alice; ----- - -== Suggested reading - -* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] -* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] -* xref:reference:sql/sql-statements/revoke.adoc[REVOKE] -* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/drop-user.adoc b/modules/reference/pages/sql/sql-statements/drop-user.adoc new file mode 100644 index 000000000..2cb31e74a --- /dev/null +++ b/modules/reference/pages/sql/sql-statements/drop-user.adoc @@ -0,0 +1,48 @@ += DROP USER +:description: The DROP USER statement removes an existing user. The user cannot own objects or hold grants when dropped. +:page-topic-type: reference + +The `DROP USER` statement removes an existing user from Redpanda SQL. `DROP ROLE` is a synonym for `DROP USER`, provided for PostgreSQL compatibility. Only a superuser can run this statement. + +A user cannot be dropped while they own objects or hold privilege grants. Reassign or remove those objects and revoke the grants first, then drop the user. If the user also owns objects (for example, a catalog or table created by that user), reassign or drop those before running `DROP USER`. + +== Syntax + +[source,sql] +---- +DROP { USER | ROLE } [IF EXISTS] user_name; +---- + +* `user_name`: Name of the user to drop. Cannot be `CURRENT_USER` or `CURRENT_ROLE`. The user running the statement cannot drop themselves, and the protected system superuser cannot be dropped. +* `IF EXISTS`: Optional. Prevents an error if the user does not exist. + +== Examples + +Drop an existing user: + +[source,sql] +---- +DROP USER alice; +---- + +Drop a user only if it exists: + +[source,sql] +---- +DROP USER IF EXISTS legacy_account; +---- + +If the user has dependent grants or owned objects, the statement fails with an error listing the objects. Revoke the grants and reassign or drop owned objects first: + +[source,sql] +---- +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; +DROP USER alice; +---- + +== Suggested reading + +* xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] +* xref:reference:sql/sql-statements/alter-user.adoc[ALTER USER] +* xref:reference:sql/sql-statements/revoke.adoc[REVOKE] +* xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/grant.adoc b/modules/reference/pages/sql/sql-statements/grant.adoc index ff106bee8..888a112b9 100644 --- a/modules/reference/pages/sql/sql-statements/grant.adoc +++ b/modules/reference/pages/sql/sql-statements/grant.adoc @@ -112,5 +112,5 @@ GRANT SELECT, INSERT ON TABLE summary_data TO alice; == Suggested reading * xref:reference:sql/sql-statements/revoke.adoc[REVOKE] -* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] +* xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] * xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/reference/pages/sql/sql-statements/revoke.adoc b/modules/reference/pages/sql/sql-statements/revoke.adoc index e13e3fe02..607350de3 100644 --- a/modules/reference/pages/sql/sql-statements/revoke.adoc +++ b/modules/reference/pages/sql/sql-statements/revoke.adoc @@ -4,7 +4,7 @@ The `REVOKE` statement removes privileges that were previously granted to a role with xref:reference:sql/sql-statements/grant.adoc[GRANT]. Only a superuser can revoke privileges. -For the privilege levels and types that apply to each object, see xref:reference:sql/sql-statements/grant.adoc#_privilege_levels[GRANT > Privilege levels]. +For the privilege levels and types that apply to each object, see xref:reference:sql/sql-statements/grant.adoc#privilege-levels[GRANT > Privilege levels]. == Syntax @@ -78,5 +78,5 @@ REVOKE USAGE ON SCHEMA public FROM alice; == Suggested reading * xref:reference:sql/sql-statements/grant.adoc[GRANT] -* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] +* xref:reference:sql/sql-statements/drop-user.adoc[DROP USER] * xref:sql:manage/manage-access.adoc[Manage access to Redpanda SQL] diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index c32040a40..18ae0c5f2 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -37,7 +37,7 @@ Redpanda SQL access is controlled by two role permissions in Redpanda Cloud's da * *SQL: Manage*: superuser access to the SQL engine. A user with this role can read all topics, create catalogs and tables, and grant access to other users. * *SQL: Access*: regular user access. A user with this role can connect to the SQL engine but has no access to any catalog or table until a *SQL: Manage* user grants it. -When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual xref:reference:sql/sql-statements/create-role.adoc[CREATE USER] is required. A *SQL: Manage* user then uses standard SQL xref:reference:sql/sql-statements/grant.adoc[GRANT] statements to give the user access to the data they need. +When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] is required. A *SQL: Manage* user then uses standard SQL xref:reference:sql/sql-statements/grant.adoc[GRANT] statements to give the user access to the data they need. . In Redpanda Cloud, assign a role with the *SQL: Access* permission to the user. Roles are managed in *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. @@ -101,6 +101,6 @@ GRANT CREATE ON SCHEMA public TO "alice@example.com"; * xref:reference:sql/sql-statements/grant.adoc[GRANT] * xref:reference:sql/sql-statements/revoke.adoc[REVOKE] -* xref:reference:sql/sql-statements/create-role.adoc[CREATE ROLE] -* xref:reference:sql/sql-statements/alter-role.adoc[ALTER ROLE] -* xref:reference:sql/sql-statements/drop-role.adoc[DROP ROLE] +* xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] +* xref:reference:sql/sql-statements/alter-user.adoc[ALTER USER] +* xref:reference:sql/sql-statements/drop-user.adoc[DROP USER] From a9c84a74e00f2bf00d4bda9861c0f34cacda2a4c Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 12:46:31 -0700 Subject: [PATCH 07/12] Review pass --- modules/reference/pages/sql/sql-statements/drop-user.adoc | 2 +- modules/reference/pages/sql/sql-statements/grant.adoc | 4 +++- modules/reference/pages/sql/sql-statements/revoke.adoc | 6 ++++-- modules/sql/pages/manage/manage-access.adoc | 6 +++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/reference/pages/sql/sql-statements/drop-user.adoc b/modules/reference/pages/sql/sql-statements/drop-user.adoc index 2cb31e74a..8fdc05072 100644 --- a/modules/reference/pages/sql/sql-statements/drop-user.adoc +++ b/modules/reference/pages/sql/sql-statements/drop-user.adoc @@ -4,7 +4,7 @@ The `DROP USER` statement removes an existing user from Redpanda SQL. `DROP ROLE` is a synonym for `DROP USER`, provided for PostgreSQL compatibility. Only a superuser can run this statement. -A user cannot be dropped while they own objects or hold privilege grants. Reassign or remove those objects and revoke the grants first, then drop the user. If the user also owns objects (for example, a catalog or table created by that user), reassign or drop those before running `DROP USER`. +A user cannot be dropped while they own objects (for example, a catalog or table created by that user) or hold privilege grants. Reassign or drop the owned objects and revoke the grants first, then drop the user. == Syntax diff --git a/modules/reference/pages/sql/sql-statements/grant.adoc b/modules/reference/pages/sql/sql-statements/grant.adoc index 888a112b9..50a771745 100644 --- a/modules/reference/pages/sql/sql-statements/grant.adoc +++ b/modules/reference/pages/sql/sql-statements/grant.adoc @@ -67,9 +67,11 @@ Schema-level privileges affect visibility and creation rights for objects in the === Grant on the database +Redpanda SQL exposes a single database, `oxla`. + [source,sql] ---- -GRANT CONNECT ON DATABASE database_name TO role_name; +GRANT CONNECT ON DATABASE oxla TO role_name; ---- == Examples diff --git a/modules/reference/pages/sql/sql-statements/revoke.adoc b/modules/reference/pages/sql/sql-statements/revoke.adoc index 607350de3..6b909202f 100644 --- a/modules/reference/pages/sql/sql-statements/revoke.adoc +++ b/modules/reference/pages/sql/sql-statements/revoke.adoc @@ -4,7 +4,7 @@ The `REVOKE` statement removes privileges that were previously granted to a role with xref:reference:sql/sql-statements/grant.adoc[GRANT]. Only a superuser can revoke privileges. -For the privilege levels and types that apply to each object, see xref:reference:sql/sql-statements/grant.adoc#privilege-levels[GRANT > Privilege levels]. +For the privilege levels and types that apply to each object, see xref:reference:sql/sql-statements/grant.adoc#privilege-levels[Privilege levels]. == Syntax @@ -34,9 +34,11 @@ REVOKE { privilege [, ...] | ALL [PRIVILEGES] } ON SCHEMA schema_name FROM role_ === Revoke on the database +Redpanda SQL exposes a single database, `oxla`. + [source,sql] ---- -REVOKE CONNECT ON DATABASE database_name FROM role_name; +REVOKE CONNECT ON DATABASE oxla FROM role_name; ---- == Behavior diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index 18ae0c5f2..b557c1ac7 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -73,9 +73,9 @@ REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' FROM "alic A few details affect how grants on Redpanda catalogs behave: -* *Privilege type.* `SELECT` is the only privilege type that has effect on a Redpanda catalog. `GRANT ALL PRIVILEGES` on a catalog resolves to `SELECT` only. -* *REVOKE on a non-matching pattern.* `REVOKE SELECT ... \=> '_pattern_'` errors if the pattern matches no existing grant for the role. The catalog-level form (no pattern) is idempotent and silently no-ops if no grants exist, so cleanup scripts can safely run it. -* *Inspecting current grants.* To see which roles have grants on which catalogs and relations, query `information_schema.role_external_relation_grants`. Catalog-level grants also appear as rows in `information_schema.role_table_grants`, where `table_name` is the catalog name. +* Privilege type: `SELECT` is the only privilege type that has effect on a Redpanda catalog. `GRANT ALL PRIVILEGES` on a catalog resolves to `SELECT` only. +* `REVOKE` on a non-matching pattern: `REVOKE SELECT ... \=> 'pattern'` errors if the pattern matches no existing grant for the role. The catalog-level form (no pattern) is idempotent and silently no-ops if no grants exist, so cleanup scripts can safely run it. +* Inspecting current grants: To see which roles have grants on which catalogs and relations, query `information_schema.role_external_relation_grants`. Catalog-level grants also appear as rows in `information_schema.role_table_grants`, where `table_name` is the catalog name. === Schema-level privileges for Redpanda catalogs and SQL storage From 2970485ad68bc3b642a8a0865ea1dc7a6049cfd5 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 13:00:59 -0700 Subject: [PATCH 08/12] Move Connect with OIDC up in nav --- modules/ROOT/nav.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 8980a9fea..e4185dbe1 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -347,11 +347,11 @@ **** xref:sql:get-started/oltp-vs-olap.adoc[] **** xref:sql:get-started/redpanda-sql-vs-postgresql.adoc[] ** xref:sql:connect-to-sql/index.adoc[Connect to Redpanda SQL] +*** xref:sql:connect-to-sql/connect-with-oidc.adoc[Connect with OIDC] *** xref:sql:connect-to-sql/language-clients/psycopg2.adoc[] *** 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] From 3816f779ae0c41e599ee534331e6b09d57ebafd5 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 13:17:48 -0700 Subject: [PATCH 09/12] Clarify "deny-all" --- modules/sql/pages/manage/manage-access.adoc | 27 +++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index b557c1ac7..f425ec6ea 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -1,14 +1,16 @@ = Manage Access to Redpanda SQL -:description: Authentication and authorization model for Redpanda SQL: OIDC, deny-all by default, admin GRANT for per-user access to topics and catalogs. +:description: Authentication and authorization model for Redpanda SQL: OIDC authentication and admin GRANT for per-user access to topics and catalogs. :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 `GRANT` statements that an admin issues on tables, Redpanda catalogs, and schemas. Redpanda SQL is deny-all by default. +* *Authentication*: Your OIDC identity provider authenticates the user, configured at the cluster level. For the client-side connection guide, see xref:sql:connect-to-sql/connect-with-oidc.adoc[]. +* *Authorization*: Two roles control what a user can do once they authenticate: +** *SQL: Manage*: SQL engine superuser. Can read every topic, create catalogs and tables, and grant access to other users. +** *SQL: Access*: Regular user. Can connect to the SQL engine but cannot read any catalog or table they don't own. By default, a *SQL: Access* user owns nothing; a *SQL: Manage* user grants `SELECT` on specific resources to give them access. -This page describes the admin-side model. For the client-side connection guide, see xref:sql:connect-to-sql/connect-with-oidc.adoc[]. +This page focuses on the admin-side authorization model. == Authentication @@ -23,25 +25,20 @@ When a user is assigned a role with the *SQL: Access* or *SQL: Manage* permissio == How queries reach the underlying topics -All Redpanda SQL queries connect to the underlying Redpanda cluster as a single super-user SASL credential associated with the default Redpanda catalog (`default_redpanda_catalog`), regardless of which user issued the query. The super-user credential is provisioned automatically when Redpanda SQL is enabled. +All Redpanda SQL queries connect to the underlying Redpanda cluster as a single internal SASL credential associated with the default Redpanda catalog (`default_redpanda_catalog`), regardless of which SQL user issued the query. The internal credential is provisioned automatically when Redpanda SQL is enabled and is not a user-facing role. 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`. +* Kafka ACLs do not gate query-time access. Every query reaches the topics under the internal SASL credential. +* The boundary that prevents users from reading data they should not see is enforced inside Redpanda SQL by `GRANT` and `REVOKE` against the SQL-level roles. == Authorization -Redpanda SQL access is controlled by two role permissions in Redpanda Cloud's data-plane RBAC: +A *SQL: Manage* user uses standard SQL xref:reference:sql/sql-statements/grant.adoc[GRANT] statements to give a *SQL: Access* user access to specific topics, catalogs, or schemas. The user identifier is the email on the user's Redpanda Cloud account. -* *SQL: Manage*: superuser access to the SQL engine. A user with this role can read all topics, create catalogs and tables, and grant access to other users. -* *SQL: Access*: regular user access. A user with this role can connect to the SQL engine but has no access to any catalog or table until a *SQL: Manage* user grants it. +. Assign the user a role with the *SQL: Access* permission (see <>). -When you assign one of these roles to a user in Redpanda Cloud, the cluster provisions a corresponding user in the SQL engine. No manual xref:reference:sql/sql-statements/create-user.adoc[CREATE USER] is required. A *SQL: Manage* user then uses standard SQL xref:reference:sql/sql-statements/grant.adoc[GRANT] statements to give the user access to the data they need. - -. In Redpanda Cloud, assign a role with the *SQL: Access* permission to the user. Roles are managed in *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. - -. As a *SQL: Manage* user, grant `SELECT` on a topic surfaced through a Redpanda catalog. The user identifier is the email on the user's Redpanda Cloud account: +. As a *SQL: Manage* user, grant `SELECT` on a topic surfaced through a Redpanda catalog: + [source,sql] ---- From 30bf342bd526ccf92f21f22c383738f6b5547b8e Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 19:08:31 -0700 Subject: [PATCH 10/12] Change name and title to broaden scope --- modules/ROOT/nav.adoc | 2 +- .../pages/connect-to-sql/authenticate.adoc | 162 ++++++++++++++++++ .../connect-to-sql/connect-with-oidc.adoc | 143 ---------------- modules/sql/pages/manage/manage-access.adoc | 8 +- 4 files changed, 167 insertions(+), 148 deletions(-) create mode 100644 modules/sql/pages/connect-to-sql/authenticate.adoc delete mode 100644 modules/sql/pages/connect-to-sql/connect-with-oidc.adoc diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index e4185dbe1..038cede58 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -347,7 +347,7 @@ **** xref:sql:get-started/oltp-vs-olap.adoc[] **** xref:sql:get-started/redpanda-sql-vs-postgresql.adoc[] ** xref:sql:connect-to-sql/index.adoc[Connect to Redpanda SQL] -*** xref:sql:connect-to-sql/connect-with-oidc.adoc[Connect with OIDC] +*** xref:sql:connect-to-sql/authenticate.adoc[Authenticate] *** xref:sql:connect-to-sql/language-clients/psycopg2.adoc[] *** xref:sql:connect-to-sql/language-clients/java-jdbc.adoc[] *** xref:sql:connect-to-sql/language-clients/php-pdo.adoc[] diff --git a/modules/sql/pages/connect-to-sql/authenticate.adoc b/modules/sql/pages/connect-to-sql/authenticate.adoc new file mode 100644 index 000000000..968afef64 --- /dev/null +++ b/modules/sql/pages/connect-to-sql/authenticate.adoc @@ -0,0 +1,162 @@ += Authenticate to Redpanda SQL +:description: Authenticate to Redpanda SQL with an OIDC bearer token, OIDC client credentials, or a SCRAM username and password for legacy clients. +:page-topic-type: how-to +:personas: app_developer, data_engineer, platform_admin +:learning-objective-1: Connect to Redpanda SQL with an OIDC bearer token or client credentials +:learning-objective-2: Set up a SCRAM username and password so a legacy client can connect to Redpanda SQL + +Authenticate to Redpanda SQL by glossterm:OpenID Connect (OIDC)[], which is the default for most clients, or by SCRAM username and password for clients that don't support token-based authentication. Redpanda Cloud handles the cluster-side OIDC configuration: when the SQL engine is enabled, the cluster is preconfigured to validate bearer tokens minted by Redpanda Cloud, regardless of whether you sign in to Redpanda Cloud with email and password or SSO. 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 BYOC cluster on AWS with Redpanda SQL enabled. See xref:sql:get-started/deploy-sql-cluster.adoc[Enable Redpanda SQL]. +* https://www.postgresql.org/download/[`psql`^] or another PostgreSQL-compatible client. +* A user or service account assigned a role with the *SQL: Access* or *SQL: Manage* permission in Redpanda Cloud's data-plane RBAC. Redpanda Cloud provisions a corresponding user in the SQL engine when the role is assigned. To assign roles, go to *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[Configure RBAC in the Data Plane]. + +== Authentication modes + +Redpanda SQL supports three 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 Redpanda Cloud (for example, returned by `rpk cloud auth token`). + +|Client credentials +|`auth_method=client_secret` +|Service-to-service connections (scheduled jobs, BI tools). Redpanda SQL exchanges a Redpanda Cloud service account's client ID and client secret for a token against Redpanda Cloud's token endpoint, then validates the returned token. + +|SCRAM password +|(omit `options`) +|Legacy clients that don't support bearer-token or client-credentials authentication. The username is the Redpanda Cloud account or service account email; the password is set by a *SQL: Manage* user with `ALTER USER`. See <>. +|=== + +Redpanda SQL treats a glossterm:bearer token[] in the password field without `auth_method=bearer` as a SCRAM password, and the connection fails. To use a bearer token, you must set `options=auth_method=bearer`. + +For OIDC tokens, the token must include the standard 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: At Cloud GA the IdP is Auth0 (single-IdP architecture per RFC + SME +// comments). External IdP federation and customer-owned IdPs are not supported. +// Once federation lands, document the validated external IdPs here. + +== Connect with a bearer token + +Use bearer-token authentication for human users who hold a JWT issued by Redpanda Cloud. Run `rpk cloud auth token` to obtain a token you can pass directly; see xref:sql:get-started/sql-quickstart.adoc[Quickstart] for the end-to-end setup. + +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= port= dbname=oxla user=ignored options='auth_method=bearer' sslmode=require" +---- + +.Python (psycopg2) +[source,python] +---- +import os +import psycopg2 + +conn = psycopg2.connect( + host="", + 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]. + +// TODO: OXLA-9382 (concurrent first-time login via connection pool produces +// duplicate role entries in the distributed catalog) is marked Done in Jira +// but has no fixVersions set. Confirm with SME the fix is in the GA 2026-05-22 +// build before publishing this note. If confirmed in GA, delete this comment. +// If NOT confirmed, restore the user-facing NOTE below: +// +// [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 + +Use client-credentials authentication for service-to-service connections: scheduled jobs, BI tools, or other automated clients that can't perform interactive sign-in. Each Redpanda Cloud service account has a client ID and client secret; Redpanda SQL exchanges those credentials for a token against Redpanda Cloud's token endpoint and validates it. + +Set `options=auth_method=client_secret`, pass the Redpanda Cloud service account's client ID in `user=`, and the client secret in the password field. The resolved principal becomes the session identity. + +[source,bash] +---- +PGPASSWORD="$CLIENT_SECRET" \ + psql "host= port= dbname=oxla user= options='auth_method=client_secret' sslmode=require" +---- + +// TODO: Reconcile token-endpoint timeout. The RFC says 5s +// ("Token Endpoint Client — HTTP POST for client credentials exchange. 5s timeout.") +// but oxla/src/net/http/http_client.h defaults to 10s. Confirm with SME which is +// authoritative for GA, then document the correct value here. + +== Connect with SCRAM for legacy clients + +For applications and tools that don't support OIDC, set a SCRAM username and password directly on the user's account in Redpanda SQL. The legacy client then connects with that username and password. + +This path still relies on Redpanda Cloud to provision the user in the SQL engine. Cloud's auto-provisioning generates an internal password that is not exposed to you, so a *SQL: Manage* user must explicitly set a known password with `ALTER USER` before the legacy client can sign in. + +. In Redpanda Cloud, create or designate a service account for the legacy client, then assign it the *SQL: Access* (or *SQL: Manage*) data-plane RBAC permission. Redpanda Cloud provisions a corresponding user in the SQL engine. See xref:security:authorization/rbac/rbac_dp.adoc[Configure RBAC in the Data Plane]. + +. As a *SQL: Manage* user, set a known password on the provisioned account. The username is the email on the service account: ++ +[source,sql] +---- +ALTER USER "service-account@example.com" WITH PASSWORD 'shared_secret'; +---- + +. Configure the legacy client to connect with that username and password. Do not set the `auth_method` option: ++ +[source,bash] +---- +PGPASSWORD='shared_secret' \ + psql "host= port= dbname=oxla user=service-account@example.com sslmode=require" +---- + +`ALTER USER ... WITH PASSWORD` persists across cluster operations: Redpanda Cloud's user reconciler only changes a role's superuser attribute or revokes access, never resets the password. If the service account loses its *SQL: Access* (or *SQL: Manage*) role assignment in Redpanda Cloud, however, the reconciler revokes `CONNECT` and the legacy client can no longer sign in. + +== Use TLS on connections + +Credentials travel in the password field of the PostgreSQL startup message, whether you authenticate with a bearer token, client credentials, or a SCRAM password. To protect them in transit, set `sslmode=require` on every connection. + +Two distinct cluster settings affect TLS: + +* The cluster's SSL mode controls TLS on the `psql` connection to Redpanda SQL itself. To reject connections that aren't using TLS, configure the cluster to reject all non-TLS connections. ++ +// TODO: Confirm the correct cross-link for the cluster SSL mode setting in Redpanda Cloud. The previous reference to `security:authorization/gbac/gbac_dp.adoc` was misdirected (GBAC covers group-claim mapping, not SSL mode). +* `oidc.require_tls` (default `true`) controls whether Redpanda SQL uses HTTPS when contacting Redpanda Cloud's 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. Run `rpk cloud auth token` to obtain a new token, then reconnect. + +== 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. diff --git a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc b/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc deleted file mode 100644 index 19cf35a90..000000000 --- a/modules/sql/pages/connect-to-sql/connect-with-oidc.adoc +++ /dev/null @@ -1,143 +0,0 @@ -= 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]. The session identity comes 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 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 user or service account assigned a role with the *SQL: Access* or *SQL: Manage* permission in Redpanda Cloud's data-plane RBAC. Redpanda Cloud provisions a corresponding user in the SQL engine when the role is assigned. To assign roles, go to *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. - -== 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, from an Authorization Code flow or 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 - -Use bearer-token authentication for human users who hold a JWT issued by your identity provider. For Redpanda Cloud users, `rpk cloud auth token` returns a token you can pass directly; see xref:sql:get-started/sql-quickstart.adoc[Quickstart] for the end-to-end setup. - -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= port= dbname=oxla user=ignored options='auth_method=bearer' sslmode=require" ----- - -.Python (psycopg2) -[source,python] ----- -import os -import psycopg2 - -conn = psycopg2.connect( - host="", - 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]. - -// TODO: OXLA-9382 (concurrent first-time login via connection pool produces -// duplicate role entries in the distributed catalog) is marked Done in Jira -// but has no fixVersions set. Confirm with SME the fix is in the GA 2026-05-22 -// build before publishing this note. If confirmed in GA, delete this comment. -// If NOT confirmed, restore the user-facing NOTE below: -// -// [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 - -Use client-credentials authentication for service-to-service connections: scheduled jobs, BI tools, or other automated clients that can't perform interactive sign-in. Each service account has an OIDC client ID and client secret issued by your identity provider; Redpanda SQL exchanges those credentials for a token and validates it. - -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= port= dbname=oxla user= 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. diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index f425ec6ea..1c67738e4 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -5,7 +5,7 @@ Redpanda SQL separates authentication and authorization: -* *Authentication*: Your OIDC identity provider authenticates the user, configured at the cluster level. For the client-side connection guide, see xref:sql:connect-to-sql/connect-with-oidc.adoc[]. +* *Authentication*: Redpanda Cloud validates the user with OIDC (default) or SCRAM password (for legacy clients), against the engine's preconfigured OIDC settings. For the client-side guide, see xref:sql:connect-to-sql/authenticate.adoc[]. * *Authorization*: Two roles control what a user can do once they authenticate: ** *SQL: Manage*: SQL engine superuser. Can read every topic, create catalogs and tables, and grant access to other users. ** *SQL: Access*: Regular user. Can connect to the SQL engine but cannot read any catalog or table they don't own. By default, a *SQL: Access* user owns nothing; a *SQL: Manage* user grants `SELECT` on specific resources to give them access. @@ -14,7 +14,7 @@ This page focuses on the admin-side authorization model. == 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. +Redpanda Cloud preconfigures the SQL engine's OIDC settings when SQL is enabled on the cluster, so you do not need to configure an external identity provider for the SQL engine. The engine validates bearer tokens minted by Redpanda Cloud, regardless of whether you sign in to Redpanda Cloud with email and password or SSO. When a user is assigned a role with the *SQL: Access* or *SQL: Manage* permission in Redpanda Cloud's data-plane RBAC, Redpanda Cloud provisions a corresponding user in the SQL engine. No manual `CREATE USER` is required. To assign roles, go to *Organization IAM > Roles*; SQL permissions are under the *Data Plane* tab when you create or edit a role. See xref:security:authorization/rbac/rbac_dp.adoc[]. @@ -91,8 +91,8 @@ GRANT CREATE ON SCHEMA public TO "alice@example.com"; == 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. +* xref:sql:connect-to-sql/authenticate.adoc[Authenticate to Redpanda SQL]: how a user connects with a bearer token, client credentials, or a SCRAM password. +* xref:security:authorization/rbac/rbac_dp.adoc[Configure RBAC in the Data Plane]: assign the data-plane RBAC roles that gate SQL engine access. == Suggested reading From a0b796f5c840ddafa112126df68e030fc419bf06 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 19:13:56 -0700 Subject: [PATCH 11/12] Update user names --- .../reference/pages/sql/sql-statements/alter-user.adoc | 4 ++-- .../pages/sql/sql-statements/create-user.adoc | 6 +++--- .../reference/pages/sql/sql-statements/drop-user.adoc | 8 ++++---- modules/reference/pages/sql/sql-statements/grant.adoc | 10 +++++----- modules/reference/pages/sql/sql-statements/revoke.adoc | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/reference/pages/sql/sql-statements/alter-user.adoc b/modules/reference/pages/sql/sql-statements/alter-user.adoc index bc6008812..e5e52ec79 100644 --- a/modules/reference/pages/sql/sql-statements/alter-user.adoc +++ b/modules/reference/pages/sql/sql-statements/alter-user.adoc @@ -27,7 +27,7 @@ Change the password for an existing user: [source,sql] ---- -ALTER USER alice WITH PASSWORD 'new_secret'; +ALTER USER "alice@example.com" WITH PASSWORD 'new_secret'; ---- Change your own password (as the current user): @@ -41,7 +41,7 @@ Promote a regular user to superuser: [source,sql] ---- -ALTER USER alice SUPERUSER; +ALTER USER "alice@example.com" SUPERUSER; ---- == Suggested reading diff --git a/modules/reference/pages/sql/sql-statements/create-user.adoc b/modules/reference/pages/sql/sql-statements/create-user.adoc index e08ae5d2c..1f9f55e11 100644 --- a/modules/reference/pages/sql/sql-statements/create-user.adoc +++ b/modules/reference/pages/sql/sql-statements/create-user.adoc @@ -8,7 +8,7 @@ A password is required when creating a user. [NOTE] ==== -Error messages from the SQL engine refer to users as "roles" (for example, `role "alice" does not exist`). This is consistent with PostgreSQL terminology and refers to the same object that `CREATE USER` produces. +Error messages from the SQL engine refer to users as "roles" (for example, `role "alice@example.com" does not exist`). This is consistent with PostgreSQL terminology and refers to the same object that `CREATE USER` produces. ==== == Syntax @@ -30,14 +30,14 @@ Create a regular user with a password: [source,sql] ---- -CREATE USER alice WITH PASSWORD 'secret123'; +CREATE USER "alice@example.com" WITH PASSWORD 'secret123'; ---- Create a superuser: [source,sql] ---- -CREATE USER admin_user WITH PASSWORD 'admin_secret' SUPERUSER; +CREATE USER "admin@example.com" WITH PASSWORD 'admin_secret' SUPERUSER; ---- == Suggested reading diff --git a/modules/reference/pages/sql/sql-statements/drop-user.adoc b/modules/reference/pages/sql/sql-statements/drop-user.adoc index 8fdc05072..7c1c1c4f9 100644 --- a/modules/reference/pages/sql/sql-statements/drop-user.adoc +++ b/modules/reference/pages/sql/sql-statements/drop-user.adoc @@ -22,22 +22,22 @@ Drop an existing user: [source,sql] ---- -DROP USER alice; +DROP USER "alice@example.com"; ---- Drop a user only if it exists: [source,sql] ---- -DROP USER IF EXISTS legacy_account; +DROP USER IF EXISTS "legacy-account@example.com"; ---- If the user has dependent grants or owned objects, the statement fails with an error listing the objects. Revoke the grants and reassign or drop owned objects first: [source,sql] ---- -REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; -DROP USER alice; +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM "alice@example.com"; +DROP USER "alice@example.com"; ---- == Suggested reading diff --git a/modules/reference/pages/sql/sql-statements/grant.adoc b/modules/reference/pages/sql/sql-statements/grant.adoc index 50a771745..f39fd5e7b 100644 --- a/modules/reference/pages/sql/sql-statements/grant.adoc +++ b/modules/reference/pages/sql/sql-statements/grant.adoc @@ -80,35 +80,35 @@ Grant `SELECT` on a topic surfaced through a Redpanda catalog: [source,sql] ---- -GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' TO alice; +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' TO "alice@example.com"; ---- Grant `SELECT` on every topic in a Redpanda catalog: [source,sql] ---- -GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog TO alice; +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog TO "alice@example.com"; ---- Grant `SELECT` on every topic whose name starts with `orders_`: [source,sql] ---- -GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' TO alice; +GRANT SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' TO "alice@example.com"; ---- Grant `USAGE` on a schema so the user can see the catalogs and storage in it: [source,sql] ---- -GRANT USAGE ON SCHEMA public TO alice; +GRANT USAGE ON SCHEMA public TO "alice@example.com"; ---- Grant `SELECT` and `INSERT` on a native SQL table: [source,sql] ---- -GRANT SELECT, INSERT ON TABLE summary_data TO alice; +GRANT SELECT, INSERT ON TABLE summary_data TO "alice@example.com"; ---- == Suggested reading diff --git a/modules/reference/pages/sql/sql-statements/revoke.adoc b/modules/reference/pages/sql/sql-statements/revoke.adoc index 6b909202f..a4d06c2b6 100644 --- a/modules/reference/pages/sql/sql-statements/revoke.adoc +++ b/modules/reference/pages/sql/sql-statements/revoke.adoc @@ -53,28 +53,28 @@ Revoke `SELECT` on a single topic: [source,sql] ---- -REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' FROM alice; +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders' FROM "alice@example.com"; ---- Revoke a wildcard grant: [source,sql] ---- -REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' FROM alice; +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog => 'orders_*' FROM "alice@example.com"; ---- Revoke all grants on a catalog: [source,sql] ---- -REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM alice; +REVOKE SELECT ON EXTERNAL SOURCE default_redpanda_catalog FROM "alice@example.com"; ---- Revoke `USAGE` on a schema: [source,sql] ---- -REVOKE USAGE ON SCHEMA public FROM alice; +REVOKE USAGE ON SCHEMA public FROM "alice@example.com"; ---- == Suggested reading From ccb45aa26a219867bec10218b6959e6633ca5099 Mon Sep 17 00:00:00 2001 From: Kat Batuigas Date: Tue, 19 May 2026 20:51:54 -0700 Subject: [PATCH 12/12] Add learning objectives --- modules/sql/pages/connect-to-sql/authenticate.adoc | 2 +- modules/sql/pages/manage/manage-access.adoc | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/sql/pages/connect-to-sql/authenticate.adoc b/modules/sql/pages/connect-to-sql/authenticate.adoc index 968afef64..ad8416c75 100644 --- a/modules/sql/pages/connect-to-sql/authenticate.adoc +++ b/modules/sql/pages/connect-to-sql/authenticate.adoc @@ -5,7 +5,7 @@ :learning-objective-1: Connect to Redpanda SQL with an OIDC bearer token or client credentials :learning-objective-2: Set up a SCRAM username and password so a legacy client can connect to Redpanda SQL -Authenticate to Redpanda SQL by glossterm:OpenID Connect (OIDC)[], which is the default for most clients, or by SCRAM username and password for clients that don't support token-based authentication. Redpanda Cloud handles the cluster-side OIDC configuration: when the SQL engine is enabled, the cluster is preconfigured to validate bearer tokens minted by Redpanda Cloud, regardless of whether you sign in to Redpanda Cloud with email and password or SSO. The cluster admin grants per-user data access separately. See xref:sql:manage/manage-access.adoc[] for the access model. +Authenticate to Redpanda SQL with an glossterm:OpenID Connect (OIDC)[] bearer token, OIDC client credentials, or a SCRAM password for clients that don't support OIDC. For how an admin grants users access to topics and catalogs, see xref:sql:manage/manage-access.adoc[]. After completing these steps, you will be able to: diff --git a/modules/sql/pages/manage/manage-access.adoc b/modules/sql/pages/manage/manage-access.adoc index 1c67738e4..98baa79ff 100644 --- a/modules/sql/pages/manage/manage-access.adoc +++ b/modules/sql/pages/manage/manage-access.adoc @@ -2,6 +2,9 @@ :description: Authentication and authorization model for Redpanda SQL: OIDC authentication and admin GRANT for per-user access to topics and catalogs. :page-topic-type: concept :personas: platform_admin +:learning-objective-1: Distinguish between the SQL: Manage and SQL: Access data-plane RBAC permissions +:learning-objective-2: Choose the right privilege level when granting access to a Redpanda topic, catalog, or schema +:learning-objective-3: Recognize how grants on Redpanda catalogs differ from grants on native SQL tables Redpanda SQL separates authentication and authorization: @@ -10,7 +13,11 @@ Redpanda SQL separates authentication and authorization: ** *SQL: Manage*: SQL engine superuser. Can read every topic, create catalogs and tables, and grant access to other users. ** *SQL: Access*: Regular user. Can connect to the SQL engine but cannot read any catalog or table they don't own. By default, a *SQL: Access* user owns nothing; a *SQL: Manage* user grants `SELECT` on specific resources to give them access. -This page focuses on the admin-side authorization model. +After reading this page, you will be able to: + +* [ ] {learning-objective-1} +* [ ] {learning-objective-2} +* [ ] {learning-objective-3} == Authentication