diff --git a/src/current/v25.4/authentication.md b/src/current/v25.4/authentication.md index fe0a4d4b192..b7a7a417dad 100644 --- a/src/current/v25.4/authentication.md +++ b/src/current/v25.4/authentication.md @@ -105,7 +105,9 @@ CockroachDB offers the following methods for client authentication: Enter password: ~~~ -- [**Single sign-on authentication to DB Console**]({% link {{ page.version.version }}/sso-db-console.md %}). +- [**Single sign-on authentication to DB Console**]({% link {{ page.version.version }}/sso-db-console.md %}). CockroachDB supports OpenID Connect (OIDC) for authenticating users to the DB Console. New in v25.4: You can also enable [automatic role synchronization]({% link {{ page.version.version }}/oidc-authorization.md %}) based on group memberships from your identity provider. + +- [**JWT authentication for SQL clients**]({% link {{ page.version.version }}/sso-sql.md %}). CockroachDB supports JSON Web Token (JWT) authentication for SQL client connections. New in v25.4: You can enable [automatic user provisioning]({% link {{ page.version.version }}/sso-sql.md %}#configure-user-provisioning) and [automatic role synchronization]({% link {{ page.version.version }}/jwt-authorization.md %}) based on group claims in JWT tokens. - [**GSSAPI authentication**]({% link {{ page.version.version }}/gssapi_authentication.md %}). @@ -335,5 +337,10 @@ The following cipher suites are rejected by default because they are not recomme - [`cockroach cert`]({% link {{ page.version.version }}/cockroach-cert.md %}) - [`cockroach auth-session`]({% link {{ page.version.version }}/cockroach-auth-session.md %}) - [GSSAPI Authentication]({% link {{ page.version.version }}/gssapi_authentication.md %}) +- [Single Sign-on (SSO) for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) +- [Cluster Single Sign-on (SSO) using JWTs]({% link {{ page.version.version }}/sso-sql.md %}) +- [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) +- [OIDC Authorization]({% link {{ page.version.version }}/oidc-authorization.md %}) +- [LDAP Authorization]({% link {{ page.version.version }}/ldap-authorization.md %}) - [SQL Authentication]({% link {{ page.version.version }}/security-reference/authentication.md %}) - [Cloud Storage Authentication]({% link {{ page.version.version }}/cloud-storage-authentication.md %}) diff --git a/src/current/v25.4/jwt-authorization.md b/src/current/v25.4/jwt-authorization.md new file mode 100644 index 00000000000..c8d0b3067ab --- /dev/null +++ b/src/current/v25.4/jwt-authorization.md @@ -0,0 +1,297 @@ +--- +title: Configure JWT Authorization +summary: Learn how to configure role-based access control (authorization) using JWT tokens for SQL client connections. +toc: true +docs_area: manage +--- + +If you manage users through an identity provider (IdP) that supports JSON Web Tokens (JWT), you can configure CockroachDB to automatically assign [roles]({% link {{ page.version.version }}/security-reference/authorization.md %}) to users based on group claims in their JWT tokens, simplifying access control. + +If JWT authorization is enabled: + +1. When a client connects to the cluster using a JWT token, the cluster extracts the groups claim from the token. +1. If the groups claim is not present in the token, the cluster queries the IdP's userinfo endpoint as a fallback. +1. Each group is mapped to a cluster role by matching the group name to a role name. +1. The user is granted each corresponding role, and roles that no longer match the user's groups are revoked. +1. In conjunction with [automatic user provisioning]({% link {{ page.version.version }}/sso-sql.md %}#configure-user-provisioning) if enabled, users are created automatically during their first authentication and simultaneously receive specified role memberships. + +## Prerequisites + +- Enable [JWT Authentication]({% link {{ page.version.version }}/sso-sql.md %}). +- Understand the structure of JWT tokens issued by your identity provider. +- Know which claim in your JWT tokens contains group memberships. + +## Configuration + +Before you begin, it may be useful to enable authentication logging, which can help you confirm successful configuration or troubleshoot issues. For details, refer to [Troubleshooting](#troubleshooting). + +### Step 1: Enable JWT authorization + +Enable JWT authorization and configure the groups claim: + +{% include_cached copy-clipboard.html %} +~~~ sql +-- Enable JWT authentication (if not already enabled) +SET CLUSTER SETTING server.jwt_authentication.enabled = true; + +-- Enable JWT authorization +SET CLUSTER SETTING server.jwt_authentication.authorization.enabled = true; + +-- Configure the JWT claim containing groups (default: 'groups') +SET CLUSTER SETTING server.jwt_authentication.group_claim = 'groups'; + +-- (Optional) Configure the userinfo endpoint JSON key for groups fallback +SET CLUSTER SETTING server.jwt_authentication.userinfo_group_key = 'groups'; +~~~ + +{{site.data.alerts.callout_info}} +The `userinfo_group_key` setting is only used when the groups claim is missing from the JWT token. CockroachDB will query the IdP's userinfo endpoint using this key to retrieve group memberships. +{{site.data.alerts.end}} + +### Step 2: Configure IdP-specific settings + +The configuration varies by identity provider: + +#### Okta + +Okta typically includes groups in the default `groups` claim: + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.jwt_authentication.group_claim = 'groups'; +SET CLUSTER SETTING server.jwt_authentication.userinfo_group_key = 'groups'; +~~~ + +Example JWT token from Okta: + +~~~json +{ + "iss": "https://your-okta-domain.okta.com", + "sub": "00u1abc2def3ghi4jkl", + "aud": "your_client_id", + "email": "alice@example.com", + "groups": ["developers", "team-alpha"] +} +~~~ + +#### Keycloak + +For Keycloak Groups (default mapping): + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.jwt_authentication.group_claim = 'groups'; +~~~ + +Example JWT token: + +~~~json +{ + "iss": "https://keycloak.example.com/realms/myrealm", + "sub": "user123", + "email": "alice@example.com", + "groups": ["developers", "team-alpha"] +} +~~~ + +{{site.data.alerts.callout_info}} +**For Keycloak realm roles**: CockroachDB does not support nested JSON paths like `realm_access.roles`. If you need to use realm roles, create a Keycloak protocol mapper to flatten the roles into a top-level claim: + +1. In Keycloak, go to your client settings +1. Navigate to **Mappers** > **Create** +1. Choose **User Realm Role** mapper type +1. Set the **Token Claim Name** to `roles` (or another simple name) +1. Configure CockroachDB to use this claim: + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.jwt_authentication.group_claim = 'roles'; +~~~ +{{site.data.alerts.end}} + +#### Azure AD / Microsoft Entra ID + +Azure AD typically uses the `groups` claim: + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.jwt_authentication.group_claim = 'groups'; +~~~ + +{{site.data.alerts.callout_info}} +In Azure AD, you may need to configure group claims in your app registration. Refer to [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/how-to-connect-fed-group-claims) for details. +{{site.data.alerts.end}} + +### Step 3: Create matching roles + +Create CockroachDB roles that match your IdP group names and grant appropriate privileges to each role. Remember that role names must comply with CockroachDB's [identifier requirements]({% link {{ page.version.version }}/create-user.md %}#user-names). + +{{site.data.alerts.callout_info}} +Group names from the IdP are normalized using case folding and Unicode normalization (NFC) before matching to role names. This means that group names are typically converted to lowercase for matching purposes. +{{site.data.alerts.end}} + +For example, if your JWT tokens contain groups named `developers` and `analysts`: + +{% include_cached copy-clipboard.html %} +~~~ sql +-- Create role for developers +CREATE ROLE developers; +GRANT ALL ON DATABASE app TO developers; + +-- Create role for analysts +CREATE ROLE analysts; +GRANT SELECT ON DATABASE analytics TO analysts; +~~~ + +{{site.data.alerts.callout_info}} +If you are going to use [automatic user provisioning]({% link {{ page.version.version }}/sso-sql.md %}#configure-user-provisioning) in conjunction with JWT authorization, be sure to complete the creation of group roles before enabling automatic user provisioning. Auto-provisioned users will only receive roles for groups that already exist as CockroachDB roles. +{{site.data.alerts.end}} + +### Step 4: Confirm configuration + +1. On your identity provider, set up test users with memberships in groups that should be synced to CockroachDB roles. + +1. If [automatic user provisioning]({% link {{ page.version.version }}/sso-sql.md %}#configure-user-provisioning) is not enabled, create the matching test users when logged in as an admin to CockroachDB: + + {% include_cached copy-clipboard.html %} + ~~~ sql + CREATE ROLE username1 LOGIN; + CREATE ROLE username2 LOGIN; + CREATE ROLE username3 LOGIN; + ~~~ + + If automatic user provisioning is enabled, users will be created automatically during their first login. + +1. Obtain a JWT token from your identity provider and connect to CockroachDB using the token. Refer to [Authenticate to your cluster]({% link {{ page.version.version }}/sso-sql.md %}#authenticate-to-your-cluster). + +1. Using your `admin` credentials, log in to the CockroachDB SQL shell and verify the user's role assignments: + + {% include_cached copy-clipboard.html %} + ~~~ sql + -- View roles granted to a specific user + SHOW GRANTS FOR username1; + + -- Check if user has a specific role + SELECT pg_has_role('username1', 'developers', 'member'); + ~~~ + + For auto-provisioned users, you can identify them by their `PROVISIONSRC` role option: + + {% include_cached copy-clipboard.html %} + ~~~ sql + -- View all users and their provisioning source + SELECT rolname, rolprovisionsrc FROM pg_roles + WHERE rolprovisionsrc LIKE 'jwt_token:%'; + ~~~ + +## How it works + +### Group extraction process + +When a user authenticates with a JWT token and JWT authorization is enabled: + +1. **Token validation**: CockroachDB first validates the JWT token signature, issuer, and claims. + +1. **Group extraction**: + - CockroachDB looks for the configured `group_claim` (default: `groups`) in the JWT token. + - If the claim is missing or cannot be parsed, CockroachDB queries the IdP's userinfo endpoint and looks for the `userinfo_group_key` (default: `groups`). + +1. **Normalization**: Group names are normalized using `MakeSQLUsernameFromUserInput`, which performs case folding and Unicode normalization (NFC). + +1. **Role matching**: Each normalized group name is compared against existing CockroachDB roles. + +### Role synchronization + +On each login, CockroachDB synchronizes the user's role memberships: + +1. **Grant new roles**: If a group matches an existing role name and the user doesn't already have that role, it is granted. + +1. **Revoke stale roles**: If the user has roles that don't match any current groups, those roles are revoked. + +1. **Skip non-existent roles**: If a group doesn't match any existing role, it is silently skipped (no error is raised). + +{{site.data.alerts.callout_info}} +IdP groups that don't correspond to CockroachDB roles are silently ignored. You must pre-create roles in CockroachDB for them to be granted. +{{site.data.alerts.end}} + +### Empty groups behavior + +If the groups claim exists but contains an empty array (`[]`): + +1. All existing role memberships are revoked from the user. +1. Login is **rejected** with error: `JWT authorization: empty group list` + +This behavior ensures that users without group memberships cannot access the cluster, which is a security feature to prevent unauthorized access. + +### Userinfo endpoint fallback + +If the JWT token does not contain the configured groups claim, CockroachDB will attempt to query the IdP's userinfo endpoint: + +1. CockroachDB makes an HTTP GET request to the userinfo endpoint using the access token. +1. The response is parsed as JSON, and CockroachDB looks for the `userinfo_group_key`. +1. If the userinfo lookup fails, login is rejected with error: `JWT authorization: userinfo lookup failed` + +## Troubleshooting + +Enable [`SESSION` logging]({% link {{ page.version.version }}/logging.md %}#sessions) to preserve data that will help troubleshoot JWT authorization issues: + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.auth_log.sql_sessions.enabled = true; +~~~ + +{{site.data.alerts.callout_info}} +Once all functionality is configured and tested successfully, we recommend disabling session logging to conserve system resources. +{{site.data.alerts.end}} + +To view the logs, open `cockroach-session.log` from your [logging directory]({% link {{ page.version.version }}/configure-logs.md %}#logging-directory). + +Potential issues to investigate may pertain to: + +- **JWT token validation**: Ensure the token is properly signed and issued by a trusted issuer. +- **Missing groups claim**: Check if the token contains the configured claim name. Use a JWT decoder tool to inspect the token. +- **Claim name mismatch**: Verify that `server.jwt_authentication.group_claim` matches the actual claim name in your tokens. +- **Userinfo endpoint**: If relying on userinfo fallback, ensure the endpoint is accessible and returns the expected JSON structure. +- **Role name mismatches**: Remember that group names are normalized (typically lowercased). Check that your role names match the normalized group names. +- **Empty groups**: Verify that users have group memberships in the IdP. + +### Common errors + +**Error**: `JWT authorization: empty group list` + +- **Cause**: The groups claim exists but contains an empty array. +- **Solution**: Ensure users have appropriate group memberships in your identity provider. + +**Error**: `JWT authorization: userinfo lookup failed` + +- **Cause**: The token doesn't contain the groups claim, and the userinfo endpoint query failed. +- **Solution**: Either include groups in the JWT token or ensure the userinfo endpoint is accessible and configured correctly. + +**Error**: User can log in but has no privileges + +- **Cause**: Groups from the IdP don't match any existing CockroachDB roles. +- **Solution**: Create roles with names matching the normalized group names from your IdP. + +## Security considerations + +1. **Maintain backup authentication**: Always keep a backup authentication method (like password or client certificate) for administrative users in case of IdP outages. + +1. **Validate token issuers**: Ensure `server.jwt_authentication.issuers` is properly configured to accept only trusted issuers. + +1. **Pre-create roles with minimal privileges**: Create roles before enabling authorization and grant only the necessary privileges following the principle of least privilege. + +1. **Monitor role synchronization**: Regularly audit role assignments and changes. Enable audit logging if available to track when roles are granted or revoked. + +1. **Secure the userinfo endpoint**: If using userinfo fallback, ensure the endpoint requires proper authentication and is only accessible over HTTPS. + +1. **Review empty groups policy**: Understand that empty groups will block login. Ensure this aligns with your security requirements. + +1. **Regularly audit IdP groups**: Review and clean up group memberships in your identity provider to ensure they reflect current access requirements. + +## See also + +- [Cluster Single Sign-on (SSO) using JWTs]({% link {{ page.version.version }}/sso-sql.md %}) +- [LDAP Authorization]({% link {{ page.version.version }}/ldap-authorization.md %}) +- [OIDC Authorization]({% link {{ page.version.version }}/oidc-authorization.md %}) +- [Authorization]({% link {{ page.version.version }}/security-reference/authorization.md %}) +- [Security Reference: Authorization]({% link {{ page.version.version }}/security-reference/authorization.md %}) diff --git a/src/current/v25.4/oidc-authorization.md b/src/current/v25.4/oidc-authorization.md new file mode 100644 index 00000000000..b3ef6f6528d --- /dev/null +++ b/src/current/v25.4/oidc-authorization.md @@ -0,0 +1,212 @@ +--- +title: Configure OIDC Authorization for DB Console +summary: Learn how to configure role-based access control for users logging into DB Console via OIDC. +toc: true +docs_area: manage +--- + +If you manage users through an identity provider (IdP) that supports OpenID Connect (OIDC), you can configure CockroachDB to automatically assign [roles]({% link {{ page.version.version }}/security-reference/authorization.md %}) to users based on group claims when they log into the DB Console, simplifying access control. + +If OIDC authorization is enabled: + +1. When a user logs into the DB Console using OIDC, the cluster extracts the groups claim from the ID token. +1. If the groups claim is not present in the ID token, the cluster checks the access token (if it's a JWT). +1. If still not found, the cluster queries the IdP's userinfo endpoint as a fallback. +1. Each group is mapped to a cluster role by matching the group name to a role name. +1. The user is granted each corresponding role, and roles that no longer match the user's groups are revoked. + +## Prerequisites + +- Enable [OIDC Authentication for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}). +- Understand the structure of tokens issued by your identity provider. +- Know which claim in your tokens contains group memberships. + +## Configuration + +Before you begin, it may be useful to enable authentication logging, which can help you confirm successful configuration or troubleshoot issues. For details, refer to [Troubleshooting](#troubleshooting). + +### Step 1: Enable OIDC authorization + +Enable OIDC authorization and configure the groups claim: + +{% include_cached copy-clipboard.html %} +~~~ sql +-- Enable OIDC authorization +SET CLUSTER SETTING server.oidc_authentication.authorization.enabled = true; + +-- Configure the claim containing groups (default: 'groups') +SET CLUSTER SETTING server.oidc_authentication.group_claim = 'groups'; + +-- (Optional) Configure the userinfo endpoint JSON key for groups fallback +SET CLUSTER SETTING server.oidc_authentication.userinfo_group_key = 'groups'; +~~~ + +{{site.data.alerts.callout_info}} +The `userinfo_group_key` setting is only used when the groups claim is missing from both the ID token and access token. CockroachDB will query the IdP's userinfo endpoint using this key to retrieve group memberships. +{{site.data.alerts.end}} + +### Step 2: Create matching roles + +[Create CockroachDB roles]({% link {{ page.version.version }}/create-user.md %}) that match your IdP group names and grant appropriate privileges to each role. Remember that role names must comply with CockroachDB's [identifier requirements]({% link {{ page.version.version }}/create-user.md %}#user-names). + +{{site.data.alerts.callout_info}} +Group names from the IdP are normalized using case folding and Unicode normalization (NFC) before matching to role names. This means that group names are typically converted to lowercase for matching purposes. +{{site.data.alerts.end}} + +For example, if your OIDC tokens contain groups named `developers` and `analysts`: + +{% include_cached copy-clipboard.html %} +~~~ sql +-- Create role for developers +CREATE ROLE developers; +GRANT ALL ON DATABASE app TO developers; + +-- Create role for analysts +CREATE ROLE analysts; +GRANT SELECT ON DATABASE analytics TO analysts; +~~~ + +### Step 3: Ensure users exist in CockroachDB + +Users logging into the DB Console via OIDC must be pre-created in CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE ROLE alice LOGIN; +CREATE ROLE bob LOGIN; +~~~ + +{{site.data.alerts.callout_info}} +Automatic user provisioning for OIDC is planned for a future release. Currently, users must be created via SQL before they can log in to the DB Console with OIDC. Automatic user provisioning using JWTs is currently supported. +{{site.data.alerts.end}} + +### Step 4: Confirm configuration + +1. On your identity provider, set up test users with memberships in groups that should be synced to CockroachDB roles. + +1. Navigate to the DB Console in your web browser and log in using OIDC. Refer to [Log in to a cluster's DB Console with SSO]({% link {{ page.version.version }}/sso-db-console.md %}#log-in-to-a-clusters-db-console-with-sso). + +1. Using your `admin` credentials in a SQL shell, verify the user's role assignments: + + {% include_cached copy-clipboard.html %} + ~~~ sql + -- View roles granted to a specific user + SHOW GRANTS FOR alice; + + -- Check if user has a specific role + SELECT pg_has_role('alice', 'developers', 'member'); + ~~~ + +## How it works + +### Group extraction process + +When a user authenticates with OIDC and OIDC authorization is enabled: + +1. **Token validation**: CockroachDB validates the ID token signature, issuer, and claims. + +1. **Group extraction from ID token**: CockroachDB looks for the configured `group_claim` (default: `groups`) in the ID token. + +1. **Group extraction from access token**: If the groups claim is not found in the ID token, CockroachDB checks the access token (if it's a JWT format) for the same claim. + +1. **Userinfo endpoint fallback**: If the groups claim is still not found, CockroachDB queries the IdP's userinfo endpoint and looks for the `userinfo_group_key` (default: `groups`). + +1. **Combine and deduplicate**: Groups from the ID token and access token are combined and deduplicated. Groups from the userinfo endpoint are processed separately. + +1. **Normalization**: Group names are normalized using `MakeSQLUsernameFromUserInput`, which performs case folding and Unicode normalization (NFC). + +1. **Role matching**: Each normalized group name is compared against existing CockroachDB roles. + +{{site.data.alerts.callout_info}} +OIDC authorization checks three sources for groups: ID token, access token, and userinfo endpoint. Groups from the ID token and access token are combined into a single list, while userinfo groups are treated as a separate fallback. +{{site.data.alerts.end}} + +### Role synchronization + +On each DB Console login, CockroachDB synchronizes the user's role memberships: + +1. **Grant new roles**: If a group matches an existing role name and the user doesn't already have that role, it is granted. + +1. **Revoke stale roles**: If the user has roles that don't match any current groups, those roles are revoked. + +1. **Skip non-existent roles**: If a group doesn't match any existing role, it is silently skipped (no error is raised). + +{{site.data.alerts.callout_info}} +IdP groups that don't correspond to CockroachDB roles are silently ignored. You must pre-create roles in CockroachDB for them to be granted. +{{site.data.alerts.end}} + +### Empty groups behavior + +If the groups claim exists but contains an empty array (`[]`): + +1. All existing role memberships are revoked from the user. +1. Login is **rejected** with an authorization error. + +This behavior ensures that users without group memberships cannot access the cluster, which is a security feature to prevent unauthorized access. + +## Troubleshooting + +Enable [`SESSION` logging]({% link {{ page.version.version }}/logging.md %}#sessions) to preserve data that will help troubleshoot OIDC authorization issues: + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING server.auth_log.sql_sessions.enabled = true; +~~~ + +{{site.data.alerts.callout_info}} +Once all functionality is configured and tested successfully, we recommend disabling session logging to conserve system resources. +{{site.data.alerts.end}} + +To view the logs, open `cockroach-session.log` from your [logging directory]({% link {{ page.version.version }}/configure-logs.md %}#logging-directory). + +Potential issues to investigate may pertain to: + +- **Token validation**: Ensure the ID token is properly signed and issued by a trusted issuer. +- **Missing groups claim**: Check if the ID token or access token contains the configured claim name. Use a JWT decoder tool to inspect the tokens. +- **Claim name mismatch**: Verify that `server.oidc_authentication.group_claim` matches the actual claim name in your tokens. +- **Userinfo endpoint**: If relying on userinfo fallback, ensure the endpoint is accessible and returns the expected JSON structure. +- **Role name mismatches**: Remember that group names are normalized (typically lowercased). Check that your role names match the normalized group names. +- **Empty groups**: Verify that users have group memberships in the IdP. +- **User doesn't exist**: Ensure the user has been created in CockroachDB before attempting to log in. + +### Common errors + +**Error**: Authorization failure with empty groups + +- **Cause**: The groups claim exists but contains an empty array. +- **Solution**: Ensure users have appropriate group memberships in your identity provider. + +**Error**: User can log in but has no privileges + +- **Cause**: Groups from the IdP don't match any existing CockroachDB roles. +- **Solution**: Create roles with names matching the normalized group names from your IdP. + +**Error**: User not found + +- **Cause**: The user doesn't exist in CockroachDB. +- **Solution**: Create the user in CockroachDB before they attempt to log into the DB Console. + +## Security considerations + +1. **Maintain backup authentication**: Always keep a backup authentication method (like password) for administrative users in case of IdP outages. + +1. **Validate token issuers**: Ensure your OIDC configuration only accepts tokens from trusted issuers. + +1. **Pre-create roles with minimal privileges**: Create roles before enabling authorization and grant only the necessary privileges following the principle of least privilege. + +1. **Monitor role synchronization**: Regularly audit role assignments and changes. Enable audit logging if available to track when roles are granted or revoked. + +1. **Secure the userinfo endpoint**: If using userinfo fallback, ensure the endpoint requires proper authentication and is only accessible over HTTPS. + +1. **Review empty groups policy**: Understand that empty groups will block login. Ensure this aligns with your security requirements. + +1. **Regularly audit IdP groups**: Review and clean up group memberships in your identity provider to ensure they reflect current access requirements. + +1. **Pre-create users**: Since automatic user provisioning is not yet available for OIDC, ensure all users are created in CockroachDB before they need access to the DB Console. + +## See also + +- [Single sign-on (SSO) to DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) +- [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) +- [LDAP Authorization]({% link {{ page.version.version }}/ldap-authorization.md %}) +- [Authorization]({% link {{ page.version.version }}/security-reference/authorization.md %}) diff --git a/src/current/v25.4/security-reference/authorization.md b/src/current/v25.4/security-reference/authorization.md index ceb08f21540..323012d28b5 100644 --- a/src/current/v25.4/security-reference/authorization.md +++ b/src/current/v25.4/security-reference/authorization.md @@ -58,6 +58,30 @@ A new user must be granted the required privileges for each database and table t By default, a new user belongs to the `public` role and has no privileges other than those assigned to the `public` role. {{site.data.alerts.end}} +### Automatic role synchronization with external identity providers + +New in v25.4: + +CockroachDB can automatically synchronize user role memberships based on group claims from external identity providers (IdPs). This feature is available for: + +- **JWT authentication**: When users authenticate via JWT tokens for SQL client connections, CockroachDB can extract group claims from the token and automatically grant or revoke role memberships based on those groups. For details, refer to [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}). + +- **OIDC authentication**: When users authenticate via OIDC to the DB Console, CockroachDB can extract group claims from the ID token, access token, or userinfo endpoint and automatically manage role memberships. For details, refer to [OIDC Authorization]({% link {{ page.version.version }}/oidc-authorization.md %}). + +When authorization is enabled: + +1. On each login, CockroachDB extracts the groups claim from the authentication token or queries the IdP's userinfo endpoint. +1. Each group name is normalized using case folding and Unicode normalization (NFC). +1. Each normalized group name is matched against existing CockroachDB role names. +1. Roles corresponding to matching groups are automatically granted to the user. +1. Roles that no longer match any current groups are automatically revoked. + +{{site.data.alerts.callout_info}} +Groups from the IdP that don't correspond to existing CockroachDB roles are silently ignored. You must pre-create roles in CockroachDB for them to be granted through IdP group synchronization. +{{site.data.alerts.end}} + +This automatic role synchronization simplifies access management by delegating group membership management to your identity provider while maintaining CockroachDB's granular privilege system. + ### Reserved identities These identities are reserved within CockroachDB. These identities are created automatically and cannot be removed. diff --git a/src/current/v25.4/security-reference/security-overview.md b/src/current/v25.4/security-reference/security-overview.md index 24997d8a6a5..83bd54f47b1 100644 --- a/src/current/v25.4/security-reference/security-overview.md +++ b/src/current/v25.4/security-reference/security-overview.md @@ -41,7 +41,7 @@ For more information, see the [licensing FAQ]({% link {{ page.version.version }} - Authentication + Authentication ✓ ✓ ✓ @@ -76,6 +76,13 @@ For more information, see the [licensing FAQ]({% link {{ page.version.version }} ✓ Web console authentication with third-party Single Sign-on (SSO) using OpenID Connect OIDC + +   +   + ✓ + ✓ + New in v25.4: SQL client identity authentication with JSON Web Tokens (JWT) +     @@ -83,6 +90,13 @@ For more information, see the [licensing FAQ]({% link {{ page.version.version }} ✓ Client identity authentication with GSSAPI and Kerberos + +   +   + ✓ + ✓ + New in v25.4: Automatic user provisioning for JWT authentication +     @@ -134,7 +148,7 @@ For more information, see the [licensing FAQ]({% link {{ page.version.version }} Cockroach Labs's proprietary storage-level {{ site.data.products.enterprise }} Encryption At Rest service implementing the Advanced Encryption Standard (AES) - Authorization + Authorization ✓ ✓ ✓ @@ -148,6 +162,20 @@ For more information, see the [licensing FAQ]({% link {{ page.version.version }} ✓ Role-based access control (RBAC) + +   +   + ✓ + ✓ + New in v25.4: Automatic role synchronization based on JWT group claims + + +   +   + ✓ + ✓ + New in v25.4: Automatic role synchronization based on OIDC group claims for DB Console + Network Security ✓ diff --git a/src/current/v25.4/sso-db-console.md b/src/current/v25.4/sso-db-console.md index a51515c64cc..15b334cabce 100644 --- a/src/current/v25.4/sso-db-console.md +++ b/src/current/v25.4/sso-db-console.md @@ -30,6 +30,9 @@ This SSO implementation uses the [authorization code grant type](https://tools.i - A {{ site.data.products.core }} cluster enabled with a valid [CockroachDB Enterprise license]({% link {{ page.version.version }}/licensing-faqs.md %}#types-of-licenses). - A [CockroachDB {{ site.data.products.advanced }} cluster]({% link cockroachcloud/create-your-cluster.md %}). +{{site.data.alerts.callout_info}} +CockroachDB {{ site.data.products.cloud }} {{ site.data.products.standard }} and {{ site.data.products.basic }} clusters do not have access to the DB Console. For SQL client authentication on these tiers, refer to [Cluster Single Sign-on (SSO) using the Cloud Console]({% link cockroachcloud/cloud-sso-sql.md %}). +{{site.data.alerts.end}} ## Log in to a cluster's DB Console with SSO @@ -152,7 +155,18 @@ Cluster Setting | Description You can optionally enable the [`server.oidc_authentication.autologin` cluster setting]({% link {{ page.version.version }}/cluster-settings.md %}) to automatically log in an authenticated user who visits the DB Console. {{site.data.alerts.end}} +## Configure role-based access control + +New in v25.4: + +Once OIDC authentication is configured, you can optionally enable automatic role synchronization based on group memberships from your identity provider. This simplifies access control by automatically granting and revoking CockroachDB roles based on IdP groups. + +For detailed instructions on configuring OIDC authorization, refer to [Configure OIDC Authorization for DB Console]({% link {{ page.version.version }}/oidc-authorization.md %}). + ## See also - [DB Console Overview]({% link {{ page.version.version }}/ui-overview.md %}) - [Cluster Single Sign-on (SSO) using JSON web tokens (JWTs)]({% link {{ page.version.version }}/sso-sql.md %}) +- [Configure OIDC Authorization for DB Console]({% link {{ page.version.version }}/oidc-authorization.md %}) +- [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) +- [LDAP Authorization]({% link {{ page.version.version }}/ldap-authorization.md %}) diff --git a/src/current/v25.4/sso-sql.md b/src/current/v25.4/sso-sql.md index 0d1cff4128d..8475ee2faf2 100644 --- a/src/current/v25.4/sso-sql.md +++ b/src/current/v25.4/sso-sql.md @@ -7,28 +7,30 @@ docs_area: manage CockroachDB clusters allow users to authenticate with Single Sign-on (SSO), both to the [DB Console]({% link {{ page.version.version }}/ui-overview.md %}), and for SQL client access. -Cluster single sign-on (SSO) enables users to access the SQL interface of a CockroachDB cluster (whether provisioned on CockroachDB {{ site.data.products.cloud }} or {{ site.data.products.core }}) with the full security of single sign-on (SSO), and the choice of a variety of cloud-based or customer-managed identity providers (IdPs). +Cluster single sign-on (SSO) enables users to access the SQL interface of a CockroachDB cluster (whether provisioned on CockroachDB {{ site.data.products.cloud }} or {{ site.data.products.core }}) with the full security of single sign-on (SSO), using JSON Web Tokens (JWTs) from external identity providers (IdPs) such as Okta, Google, Azure AD, or Keycloak. -{{ site.data.products.advanced }} clusters can provision their users with Java Web Tokens (JWTs) via the DB Console. This allows users to authenticate to a cluster by signing in to their IdP (for example, Okta or Google) with a link embedded in the DB Console. This flow provisions a JWT that a user can copy out of the DB Console UI and use in a SQL connection string to authenticate to the cluster. +Users can obtain JWTs directly from their IdP and use them to authenticate to SQL clients. Optionally, CockroachDB {{ site.data.products.cloud }} {{ site.data.products.advanced }} clusters and {{ site.data.products.core }} clusters can also generate JWTs via the DB Console as a convenience feature. When DB Console JWT generation is enabled, users can sign in to their IdP through a link embedded in the DB Console, then copy the generated JWT and use it in a SQL connection string to authenticate to the cluster. -{{site.data.alerts.callout_info}} -Cluster single sign-on for the DB Console is supported on CockroachDB [{{ site.data.products.enterprise }}]({% link {{ page.version.version }}/licensing-faqs.md %}#types-of-licenses) and {{ site.data.products.advanced }} clusters. CockroachDB {{ site.data.products.standard }} and {{ site.data.products.basic }} clusters do not support cluster single sign-on and do not have access to the DB Console. However, both CockroachDB {{ site.data.products.standard }} and CockroachDB {{ site.data.products.basic }} clusters can use [Cluster Single Sign-on (SSO) to authenticate to the `ccloud` command-line interface and to the CockroachDB {{ site.data.products.cloud }} Console]({% link cockroachcloud/cloud-sso-sql.md %}). -{{site.data.alerts.end}} +New in v25.4: JWT authentication supports automatic role synchronization and user provisioning. When [JWT authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) is enabled, users' role memberships are automatically synchronized based on group claims from the IdP on each login. Additionally, [automatic user provisioning](#configure-user-provisioning) can automatically create SQL users on first authentication, eliminating the need to pre-create users. -The page describes how to configure a cluster for cluster single sign-on using JWTs and then how users can authenticate using the JWTs. If you're a user ready to sign in to the DB Console with JWTs, you can skip the configuration section: +This page describes how to configure a cluster for cluster single sign-on using JWTs and then how users can authenticate using the JWTs. If you're a user ready to sign in to the DB Console with JWTs, you can skip the configuration section: - [Configure a cluster for cluster single sign-on using JWTs](#configure-your-cluster-for-sso) - [Authenticate to your cluster](#authenticate-to-your-cluster) **Prerequisites** -- You must have your cluster pre-configured for OIDC/SSO authentication for DB Console. Use the [Single Sign-on (SSO) for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) guide to set this up. +- **Identity Provider (IdP)**: You must have access to an identity provider that supports JWT tokens, such as Okta, Google, Azure AD, or Keycloak. + +- **Cluster Settings Access**: You must have the ability to update your cluster settings. Refer to [`SET CLUSTER SETTING`: Required permissions]({% link {{ page.version.version }}/set-cluster-setting.md %}#required-privileges). + +- **SQL User Provisioning**: + - If you are using [automatic user provisioning](#configure-user-provisioning), SQL users will be created automatically on first authentication. + - If automatic user provisioning is disabled, a SQL user that corresponds with your external identity must be pre-created on the cluster. To create users, you must have access to the [`admin` role]({% link {{ page.version.version }}/security-reference/authorization.md %}#admin-role). -- SQL users/credentials: +- **(Optional) DB Console JWT Generation**: To use the DB Console to generate JWTs (instead of obtaining them directly from your IdP), you must have your cluster pre-configured for OIDC/SSO authentication for DB Console. Use the [Single Sign-on (SSO) for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) guide to set this up. - - You must have the ability to update your cluster settings, which can be achieved in several ways. Refer to [`SET CLUSTER SETTING`: Required permissions]({% link {{ page.version.version }}/set-cluster-setting.md %}#required-privileges) -. - - A SQL user that corresponds with your external identity must be pre-provisioned on the cluster. To provision such users, you must have access to the [`admin` role]({% link {{ page.version.version }}/security-reference/authorization.md %}#admin-role). +- **(Optional) JWT Authorization**: To enable automatic role synchronization based on IdP group claims, see [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}). ## Configure your cluster for SSO @@ -46,6 +48,10 @@ Cluster Setting | Description `server.jwt_authentication.client.timeout` | An optional HTTP client timeout for external calls made during JWT authentication, in seconds. Defaults to `15` seconds. `server.jwt_authentication.audience` | This must match `server.oidc_authentication.client_id`; refer to [Single Sign-on (SSO) for DB Console](sso-db-console.html). `server.jwt_authentication.claim` | The JWT field that will be used to determine the user identity in CockroachDB; normally set either to `email`, or `sub` (subject). +`server.jwt_authentication.authorization.enabled` | New in v25.4: Enables automatic role synchronization based on JWT groups claim. See [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}). Defaults to `false`. +`server.jwt_authentication.group_claim` | New in v25.4: JWT field containing groups for authorization. Defaults to `groups`. See [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}). +`server.jwt_authentication.userinfo_group_key` | New in v25.4: Userinfo endpoint JSON key for groups fallback. Defaults to `groups`. See [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}). +`security.provisioning.jwt.enabled` | New in v25.4: Enables automatic user creation on first JWT login. Defaults to `false`. See [Configure user provisioning](#configure-user-provisioning). `server.oidc_authentication.generate_cluster_sso_token.enabled` | Enables token generation; must be set to `true`. `server.oidc_authentication.generate_cluster_sso_token.use_token`| Selects which part of the received OIDC credentials to display. `server.identity_map.configuration`| Takes an [Identity Map configuration](#identity-map-configuration). @@ -211,9 +217,70 @@ Examples: Maps each GCP-provisioned service account to a SQL user named `gcp_{ GCP user ID }`. For example, `gcp_1234567` for a service account with ID `1234567`. +## Configure user provisioning + +New in v25.4: + +CockroachDB can automatically create users on their first JWT authentication, eliminating the need to pre-create user accounts. + +### Enable user provisioning + +{% include_cached copy-clipboard.html %} +~~~ sql +SET CLUSTER SETTING security.provisioning.jwt.enabled = true; +~~~ + +### How it works + +1. A user presents a valid JWT token during authentication. +1. If the user doesn't exist in CockroachDB, the user is created automatically. +1. The user is tagged with the `PROVISIONSRC` role option: `jwt_token:`, where `` is the JWT issuer URL. +1. If [JWT authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) is also enabled, roles are synchronized immediately after user creation. + +### Auditing provisioned users + +You can identify automatically provisioned users by viewing their role options: + +{% include_cached copy-clipboard.html %} +~~~ sql +SHOW ROLES; +~~~ + +Example output: + +~~~txt + username | options | member_of +------------+------------------------------------------------------+----------- + alice | {PROVISIONSRC=jwt_token:https://auth.example.com} | {developers} + bob | {PROVISIONSRC=jwt_token:https://auth.example.com} | {admins} +~~~ + +Users provisioned via JWT will have `PROVISIONSRC=jwt_token:` in their options column. + +### Security considerations + +- **Validate JWT issuers carefully**: Ensure `server.jwt_authentication.issuers.configuration` only includes trusted issuers, as any valid JWT from these issuers can create new users. +- **Monitor provisioned users**: Regularly review automatically created users to ensure only authorized users are being provisioned. +- **Combine with JWT authorization**: Consider enabling [JWT authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) to automatically grant appropriate roles to provisioned users based on their IdP group memberships. +- **Password management**: Provisioned users cannot change their own passwords, as authentication is managed through the IdP. + +{{site.data.alerts.callout_info}} +If you are going to use JWT user provisioning in conjunction with [JWT authorization]({% link {{ page.version.version }}/jwt-authorization.md %}), be sure to create the necessary roles in CockroachDB before enabling user provisioning. Auto-provisioned users will only receive roles for groups that already exist as CockroachDB roles. +{{site.data.alerts.end}} + ## Authenticate to your cluster -Once ConsoleDB SSO and Cluster SSO with JWTs are enabled and your cluster is [properly configured](#) (including mapping authorized external users to SQL roles), users can self-provision auth tokens through a sign-in flow embedded in the DB Console. These tokens (JWTs) are intended as short-lived credentials, and although their expiry depends on the IdP configuration, it is usually 1 hour. +JWT authentication supports two methods for obtaining tokens: + +1. **Obtain JWTs directly from your IdP**: Use your identity provider's API or SDK to generate JWT tokens (e.g., via Okta APIs, Google OAuth, Azure AD). This is the primary method and requires only the JWT authentication cluster settings configured above. + +2. **Generate JWTs via DB Console**: If you have [OIDC authentication for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) configured, users can obtain JWT tokens through the DB Console UI. + +This section describes the DB Console method. For obtaining JWTs directly from your IdP, refer to your identity provider's documentation. + +### Authenticate using DB Console-generated JWTs + +Once DB Console SSO and Cluster SSO with JWTs are enabled and your cluster is [properly configured](#configure-your-cluster-for-sso) (including mapping authorized external users to SQL roles), users can self-provision auth tokens through a sign-in flow embedded in the DB Console. These tokens (JWTs) are intended as short-lived credentials. The expiry is set based on the OIDC token from your identity provider, which is typically 1 hour. {{site.data.alerts.callout_success}} This example uses [`cockroach sql`]({% link {{ page.version.version }}/cockroach-sql.md %}), but you can use any SQL client that supports sufficiently long passwords. @@ -243,3 +310,6 @@ This example uses [`cockroach sql`]({% link {{ page.version.version }}/cockroach - [DB Console Overview]({% link {{ page.version.version }}/ui-overview.md %}) - [Single Sign-on (SSO) for DB Console]({% link {{ page.version.version }}/sso-db-console.md %}) +- [JWT Authorization]({% link {{ page.version.version }}/jwt-authorization.md %}) +- [OIDC Authorization]({% link {{ page.version.version }}/oidc-authorization.md %}) +- [LDAP Authorization]({% link {{ page.version.version }}/ldap-authorization.md %})