From f75efa380e3e53f0a28d9d437773afee34d9225b Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Fri, 1 Mar 2024 14:30:31 +0800 Subject: [PATCH] Add description for `tidb_auth_token` authentication (#15818) (#16711) --- basic-features.md | 2 +- security-compatibility-with-mysql.md | 123 +++++++++++++++++++- sql-statements/sql-statement-alter-user.md | 6 + sql-statements/sql-statement-create-user.md | 6 + system-variables.md | 1 - tidb-configuration-file.md | 12 +- 6 files changed, 136 insertions(+), 14 deletions(-) diff --git a/basic-features.md b/basic-features.md index eff3e053bcb7..4c2fb3a3da49 100644 --- a/basic-features.md +++ b/basic-features.md @@ -188,7 +188,7 @@ summary: 了解 TiDB 的功能概览。 | [证书鉴权](/certificate-authentication.md) | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | | [`caching_sha2_password` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | Y | Y | Y | N | N | N | | [`tidb_sm3_password` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N | -| [`tidb_auth_token` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N | +| [`tidb_auth_token` 认证](/security-compatibility-with-mysql.md#tidb_auth_token) | Y | Y | Y | N | N | N | N | N | N | N | | [`authentication_ldap_sasl` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N | | [`authentication_ldap_simple` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N | | [密码管理](/password-management.md) | Y | Y | Y | N | N | N | N | N | N | N | diff --git a/security-compatibility-with-mysql.md b/security-compatibility-with-mysql.md index 7c8d372fb78f..d99c18411d33 100644 --- a/security-compatibility-with-mysql.md +++ b/security-compatibility-with-mysql.md @@ -107,9 +107,9 @@ TiDB 的密码重用策略功能与 MySQL 一致,在实现密码重用策略 ## 可用的身份验证插件 -TiDB 支持多种身份验证方式。通过使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 语句和 [`ALTER USER`](/sql-statements/sql-statement-create-user.md) 语句,即可创建新用户或更改 TiDB 权限系统内的已有用户。TiDB 身份验证方式与 MySQL 兼容,其名称与 MySQL 保持一致。 +TiDB 支持多种身份验证方式。通过使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 语句和 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) 语句,即可创建新用户或更改 TiDB 权限系统内的已有用户。TiDB 身份验证方式与 MySQL 兼容,其名称与 MySQL 保持一致。 -TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务器和客户端建立连接时,如要指定服务器对外通告的默认验证方式,可通过 [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) 变量进行设置。`tidb_sm3_password` 为仅在 TiDB 支持的 SM3 身份验证方式,使用该方式登录的用户需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3)。`tidb_auth_token` 为仅用于 TiDB Cloud 内部的基于 JSON Web Token (JWT) 的认证方式。 +TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务器和客户端建立连接时,如要指定服务器对外通告的默认验证方式,可通过 [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) 变量进行设置。`tidb_sm3_password` 为仅在 TiDB 支持的 SM3 身份验证方式,使用该方式登录的用户需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3)。`tidb_auth_token` 用于 TiDB Cloud 内部的基于 JSON Web Token (JWT) 的认证,用户通过配置也可以用于自托管环境。 针对 TLS 身份验证,TiDB 目前采用不同的配置方案。具体情况请参见[为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md)。 @@ -129,3 +129,122 @@ TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务 | ed25519 (MariaDB) | 否 | | GSSAPI (MariaDB) | 否 | | FIDO | 否 | + +### `tidb_auth_token` + +`tidb_auth_token` 是一种基于 [JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) 的无密码认证方式。在 v6.4.0 中,`tidb_auth_token` 仅用于 TiDB Cloud 内部的用户认证,从 v6.5.0 起,你也可以将 `tidb_auth_token` 配置为 TiDB 自托管环境中用户的认证方式。不同于 `mysql_native_passsword`、`caching_sha2_password` 等使用密码的认证方式,`tidb_auth_token` 认证方式在创建用户时无需设置并保存自定义密码,在用户登录时只需使用一个签发的 token,从而简化用户的认证过程并提升安全性。 + +#### JWT + +JWT 由 Header、Payload 和 Signature 三部分组成。这三部分分别通过 base64 编码后,使用点号(`.`)拼接成一个字符串,以便在客户端和服务器之间传输。 + +Header 描述 JWT 的元数据,包含 3 个属性: + +* `alg`:表示签名使用的算法,默认为 `RS256`。 +* `typ`:表示 token 的类型,为 `JWT`。 +* `kid`:表示用于生成 token 签名的 key ID。 + +Header 示例: + +```json +{ + "alg": "RS256", + "kid": "the-key-id-0", + "typ": "JWT" +} +``` + +Payload 是 JWT 的主体部分,用于保存用户的信息。Payload 中的每个字段称为一个 claim(声明)。TiDB 用户认证要求提供的声明如下: + +* `iss`:如果[创建用户](/sql-statements/sql-statement-create-user.md)时未指定 `TOKEN_ISSUER` 或者将其设置为了空字符串,则可以不包含该声明;否则 `iss` 应该与 `TOKEN_ISSUER` 设置值相同。 +* `sub`:TiDB 中要求该值与待认证的用户名相同。 +* `iat`:发布 token 的时间戳。TiDB 中要求该值不得晚于认证时的时间,也不得早于认证前 15 分钟。 +* `exp`:token 到期的时间戳。如果 token 在认证时已经过期,则认证失败。 +* `email`:邮件地址。创建用户时可以通过 `ATTRIBUTE '{"email": "xxxx@pingcap.com"}'` 指定 email 信息。如果创建用户时未指定 email 信息,则该声明应设置为空字符串;否则该声明应该与创建用户时的设置值相同。 + +Payload 示例: + +```json +{ + "email": "user@pingcap.com", + "exp": 1703305494, + "iat": 1703304594, + "iss": "issuer-abc", + "sub": "user@pingcap.com" +} +``` + +Signature 用于对 Header 和 Payload 这两部分数据进行签名。 + +> **警告:** +> +> - Header 与 Payload 使用 base64 进行编码的过程是可逆的,请勿在 Payload 中携带敏感数据。 +> - `tidb_auth_token` 认证方式要求客户端支持 [`mysql_clear_password`](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html) 插件,并将 token 以明文的方式发送至 TiDB,因此请[为 TiDB 开启加密传输](/enable-tls-between-clients-and-servers.md) 后再使用 `tidb_auth_token` 进行认证。 + +#### 使用方法 + +配置并使用 `tidb_auth_token` 作为 TiDB 自托管环境中用户的认证方式,有以下几个步骤: + +1. 在 TiDB 配置文件中设置 [`auth-token-jwks`](/tidb-configuration-file.md#auth-token-jwks-从-v640-版本开始引入) 和 [`auth-token-refresh-interval`](/tidb-configuration-file.md#auth-token-refresh-interval-从-v640-版本开始引入)。 + + 例如,可以通过下列命令获取示例 JWKS: + + ```bash + wget https://raw.githubusercontent.com/CbcWestwolf/generate_jwt/master/JWKS.json + ``` + + 然后在 TiDB 的配置文件 `config.toml` 中配置上述 JWKS 文件的路径: + + ```toml + [security] + auth-token-jwks = "JWKS.json" + ``` + +2. 启动 `tidb-server`,并定期更新保存 JWKS 至 `auth-token-jwks` 指定的路径。 + +3. 创建使用 `tidb_auth_token` 认证的用户,并根据需要通过 `REQUIRE TOKEN_ISSUER` 和 `ATTRIBUTE '{"email": "xxxx@pingcap.com"}` 指定 `iss` 与 `email` 信息。 + + 例如,创建一个使用 `tidb_auth_token` 认证的用户 `user@pingcap.com`: + + ```sql + CREATE USER 'user@pingcap.com' IDENTIFIED WITH 'tidb_auth_token' REQUIRE TOKEN_ISSUER 'issuer-abc' ATTRIBUTE '{"email": "user@pingcap.com"}'; + ``` + +4. 生成并签发用于认证的 token,通过 mysql 客户端的 `mysql_clear_text` 插件进行认证。 + + 通过 `go install github.com/cbcwestwolf/generate_jwt` 安装 JWT 生成工具。该工具仅用于生成测试 `tidb_auth_token` 的 JWT。例如: + + ```text + generate_jwt --kid "the-key-id-0" --sub "user@pingcap.com" --email "user@pingcap.com" --iss "issuer-abc" + ``` + + 打印公钥和 token 形式如下: + + ```text + -----BEGIN PUBLIC KEY----- + MIIBCgKCAQEAq8G5n9XBidxmBMVJKLOBsmdOHrCqGf17y9+VUXingwDUZxRp2Xbu + LZLbJtLgcln1lC0L9BsogrWf7+pDhAzWovO6Ai4Aybu00tJ2u0g4j1aLiDdsy0gy + vSb5FBoL08jFIH7t/JzMt4JpF487AjzvITwZZcnsrB9a9sdn2E5B/aZmpDGi2+Is + f5osnlw0zvveTwiMo9ba416VIzjntAVEvqMFHK7vyHqXbfqUPAyhjLO+iee99Tg5 + AlGfjo1s6FjeML4xX7sAMGEy8FVBWNfpRU7ryTWoSn2adzyA/FVmtBvJNQBCMrrA + hXDTMJ5FNi8zHhvzyBKHU0kBTS1UNUbP9wIDAQAB + -----END PUBLIC KEY----- + + eyJhbGciOiJSUzI1NiIsImtpZCI6InRoZS1rZXktaWQtMCIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAcGluZ2NhcC5jb20iLCJleHAiOjE3MDMzMDU0OTQsImlhdCI6MTcwMzMwNDU5NCwiaXNzIjoiaXNzdWVyLWFiYyIsInN1YiI6InVzZXJAcGluZ2NhcC5jb20ifQ.T4QPh2hTB5on5xCuvtWiZiDTuuKvckggNHtNaovm1F4RvwUv15GyOqj9yMstE-wSoV5eLEcPC2HgE6eN1C6yH_f4CU-A6n3dm9F1w-oLbjts7aYCl8OHycVYnq609fNnb8JLsQAmd1Zn9C0JW899-WSOQtvjLqVSPe9prH-cWaBVDQXzUJKxwywQzk9v-Z1Njt9H3Rn9vvwwJEEPI16VnaNK38I7YG-1LN4fAG9jZ6Zwvz7vb_s4TW7xccFf3dIhWTEwOQ5jDPCeYkwraRXU8NC6DPF_duSrYJc7d7Nu9Z2cr-E4i1Rt_IiRTuIIzzKlcQGg7jd9AGEfGe_SowsA-w + ``` + + 复制上面最后一行的 token 用于登录: + + ```Shell + mycli -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p '' + ``` + + 注意这里使用的 mysql 客户端必须支持 `mysql_clear_password` 插件。[mycli](https://www.mycli.net/) 默认开启这一插件,如果使用 [mysql 命令行客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html) 则需要 `--enable-cleartext-plugin` 选项来开启这个插件: + + ```Shell + mysql -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p'' --enable-cleartext-plugin + ``` + + 如果在生成 token 的时候指定了错误的 `--sub`(比如 `--sub "wronguser@pingcap.com"`),则无法使用该 token 进行认证。 + +可以使用 [jwt.io](https://jwt.io/) 提供的 debugger 对 token 进行编解码。 diff --git a/sql-statements/sql-statement-alter-user.md b/sql-statements/sql-statement-alter-user.md index 06804a15d47f..e23e2f278ea0 100644 --- a/sql-statements/sql-statement-alter-user.md +++ b/sql-statements/sql-statement-alter-user.md @@ -19,6 +19,12 @@ UserSpecList ::= UserSpec ::= Username AuthOption +RequireClauseOpt ::= + ( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )? + +RequireList ::= + ( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )* + Username ::= StringName ('@' StringName | singleAtIdentifier)? | 'CURRENT_USER' OptionalBraces diff --git a/sql-statements/sql-statement-create-user.md b/sql-statements/sql-statement-create-user.md index c0e9acf0027b..d1d45322a48f 100644 --- a/sql-statements/sql-statement-create-user.md +++ b/sql-statements/sql-statement-create-user.md @@ -19,6 +19,12 @@ IfNotExists ::= UserSpecList ::= UserSpec ( ',' UserSpec )* +RequireClauseOpt ::= + ( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )? + +RequireList ::= + ( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )* + UserSpec ::= Username AuthOption diff --git a/system-variables.md b/system-variables.md index e3aa814b7009..e49c0a456bd4 100644 --- a/system-variables.md +++ b/system-variables.md @@ -414,7 +414,6 @@ mysql> SELECT * FROM t1; - 类型:枚举型 - 默认值:`mysql_native_password` - 可选值:`mysql_native_password`,`caching_sha2_password`,`tidb_sm3_password`,`tidb_auth_token`,`authentication_ldap_sasl` 或 `authentication_ldap_simple`。 -- `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要设置为该值**。 - 服务器和客户端建立连接时,这个变量用于设置服务器对外通告的默认身份验证方式。如要了解该变量的其他可选值,参见[可用的身份验证插件](/security-compatibility-with-mysql.md#可用的身份验证插件)。 - 若要在用户登录时使用 `tidb_sm3_password` 插件,需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3) 进行连接。 diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 89bb46134306..313a84a1d36c 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -414,20 +414,12 @@ TiDB 配置文件比命令行参数支持更多的选项。你可以在 [config/ ### `auth-token-jwks` 从 v6.4.0 版本开始引入 -> **警告:** -> -> `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要修改该配置**。 - -+ 设置 `tidb_auth_token` 认证方式的 JSON Web Key Sets (JWKS) 的本地文件路径。 ++ 设置 [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) 认证方式的 JSON Web Key Sets (JWKS) 的本地文件路径。 + 默认值:"" ### `auth-token-refresh-interval` 从 v6.4.0 版本开始引入 -> **警告:** -> -> `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要修改该配置**。 - -+ 设置 `tidb_auth_token` 认证方式的 JWKS 刷新时间间隔。 ++ 设置 [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) 认证方式的 JWKS 刷新时间间隔。 + 默认值:1h ### `disconnect-on-expired-password` 从 v6.5.0 版本开始引入