From 00b50a30314c5470ea5f029235d2b2bba9e01a3f Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 11 May 2023 16:11:21 +0800 Subject: [PATCH] privilege, server: support LDAP authentication (#43582) (#43696) close pingcap/tidb#43580 --- DEPS.bzl | 36 +- bindinfo/bind_test.go | 4 +- bindinfo/capture_test.go | 38 +- bindinfo/session_handle_test.go | 4 +- br/pkg/lightning/config/config_test.go | 2 +- ddl/db_cache_test.go | 2 +- ddl/db_integration_test.go | 2 +- ddl/db_test.go | 2 +- ddl/fktest/foreign_key_test.go | 4 +- ddl/sequence_test.go | 10 +- ddl/tiflash_replica_test.go | 2 +- domain/extract_test.go | 2 +- executor/cluster_table_test.go | 14 +- executor/executor_test.go | 4 +- executor/explain_test.go | 4 +- executor/explainfor_test.go | 6 +- executor/fktest/foreign_key_test.go | 4 +- executor/grant_test.go | 6 +- executor/infoschema_cluster_table_test.go | 6 +- executor/infoschema_reader_test.go | 18 +- executor/issuetest/executor_issue_test.go | 2 +- .../passwordtest/password_management_test.go | 126 +++--- executor/prepared_test.go | 4 +- executor/recover_test.go | 6 +- executor/show_placement_test.go | 6 +- executor/showtest/show_test.go | 42 +- executor/simple.go | 6 +- executor/simple_test.go | 6 +- executor/simpletest/BUILD.bazel | 2 +- executor/simpletest/simple_test.go | 57 ++- executor/slow_query_sql_test.go | 2 +- extension/function_test.go | 22 +- extension/registry_test.go | 8 +- go.mod | 6 +- go.sum | 16 +- infoschema/cluster_tables_test.go | 36 +- infoschema/tables_test.go | 20 +- parser/ast/misc.go | 10 + parser/mysql/const.go | 2 + planner/core/binary_plan_test.go | 10 +- planner/core/integration_partition_test.go | 4 +- planner/core/integration_test.go | 8 +- planner/core/prepare_test.go | 4 +- privilege/BUILD.bazel | 1 + privilege/conn/BUILD.bazel | 8 + privilege/conn/conn.go | 30 ++ privilege/privilege.go | 3 +- privilege/privileges/BUILD.bazel | 2 + privilege/privileges/ldap/BUILD.bazel | 28 ++ privilege/privileges/ldap/const.go | 24 ++ privilege/privileges/ldap/ldap_common.go | 374 +++++++++++++++++ privilege/privileges/ldap/ldap_common_test.go | 29 ++ privilege/privileges/ldap/sasl.go | 119 ++++++ privilege/privileges/ldap/simple.go | 65 +++ privilege/privileges/privileges.go | 22 +- privilege/privileges/privileges_test.go | 380 +++++++++--------- server/BUILD.bazel | 2 + server/conn.go | 51 ++- server/conn_test.go | 43 +- server/mock_conn.go | 2 +- session/BUILD.bazel | 1 + session/bootstrap_test.go | 6 +- session/session.go | 7 +- session/sessiontest/session_test.go | 22 +- sessionctx/variable/BUILD.bazel | 1 + sessionctx/variable/sysvar.go | 165 +++++++- sessionctx/variable/tidb_vars.go | 134 ++++-- sessiontxn/staleread/externalts_test.go | 6 +- table/tables/cache_test.go | 2 +- table/tables/tables_test.go | 4 +- table/temptable/intergration_test.go | 2 +- .../pessimistictest/pessimistic_test.go | 4 +- util/stmtsummary/v2/tests/table_test.go | 8 +- 73 files changed, 1606 insertions(+), 514 deletions(-) create mode 100644 privilege/conn/BUILD.bazel create mode 100644 privilege/conn/conn.go create mode 100644 privilege/privileges/ldap/BUILD.bazel create mode 100644 privilege/privileges/ldap/const.go create mode 100644 privilege/privileges/ldap/ldap_common.go create mode 100644 privilege/privileges/ldap/ldap_common_test.go create mode 100644 privilege/privileges/ldap/sasl.go create mode 100644 privilege/privileges/ldap/simple.go diff --git a/DEPS.bzl b/DEPS.bzl index 04e17ad83dfd5..58aafbd39378a 100644 --- a/DEPS.bzl +++ b/DEPS.bzl @@ -111,6 +111,13 @@ def go_deps(): sum = "h1:4QctJBgXEkbzeKz6PJy6bt3JSPNSN4I2mITYW+eKUoQ=", version = "v1.0.0", ) + go_repository( + name = "com_github_alexbrainman_sspi", + build_file_proto_mode = "disable", + importpath = "github.com/alexbrainman/sspi", + sum = "h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=", + version = "v0.0.0-20210105120005-909beea2cc74", + ) go_repository( name = "com_github_alexkohler_prealloc", @@ -294,6 +301,14 @@ def go_deps(): sum = "h1:Q2feRPMlcfVcqz3pF87PJzkm5lZrL+x6BDtzhODzNJM=", version = "v11.2.8+incompatible", ) + go_repository( + name = "com_github_azure_go_ntlmssp", + build_file_proto_mode = "disable", + importpath = "github.com/Azure/go-ntlmssp", + sum = "h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=", + version = "v0.0.0-20221128193559-754e69321358", + ) + go_repository( name = "com_github_bazelbuild_buildtools", build_file_proto_mode = "disable", @@ -1217,6 +1232,14 @@ def go_deps(): sum = "h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=", version = "v1.4.0", ) + go_repository( + name = "com_github_go_asn1_ber_asn1_ber", + build_file_proto_mode = "disable", + importpath = "github.com/go-asn1-ber/asn1-ber", + sum = "h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=", + version = "v1.5.4", + ) + go_repository( name = "com_github_go_check_check", build_file_proto_mode = "disable_global", @@ -1282,6 +1305,15 @@ def go_deps(): sum = "h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=", version = "v0.2.1", ) + go_repository( + name = "com_github_go_ldap_ldap_v3", + build_file_proto_mode = "disable", + importpath = "github.com/go-ldap/ldap/v3", + replace = "github.com/YangKeao/ldap/v3", + sum = "h1:+OqGGFc2YHFd82aSHmjlILVt1t4JWJjrNIfV8cVEPow=", + version = "v3.4.5-0.20230421065457-369a3bab1117", + ) + go_repository( name = "com_github_go_logfmt_logfmt", build_file_proto_mode = "disable_global", @@ -1372,8 +1404,8 @@ def go_deps(): name = "com_github_go_sql_driver_mysql", build_file_proto_mode = "disable_global", importpath = "github.com/go-sql-driver/mysql", - sum = "h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=", - version = "v1.7.0", + sum = "h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=", + version = "v1.7.1", ) go_repository( name = "com_github_go_stack_stack", diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index cb8e62687df8f..44713331b43c1 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -762,11 +762,11 @@ func TestPrivileges(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, index idx(a))") tk.MustExec("create global binding for select * from t using select * from t use index(idx)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 1) tk.MustExec("create user test@'%'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test", Hostname: "%"}, nil, nil, nil)) rows = tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) } diff --git a/bindinfo/capture_test.go b/bindinfo/capture_test.go index 21b31c883e582..dc0215203b255 100644 --- a/bindinfo/capture_test.go +++ b/bindinfo/capture_test.go @@ -64,7 +64,7 @@ func TestDMLCapturePlanBaseline(t *testing.T) { rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("delete from t where b = 1 and c > 1") tk.MustExec("delete from t where b = 1 and c > 1") tk.MustExec("update t set a = 1 where b = 1 and c > 1") @@ -111,7 +111,7 @@ func TestCapturePlanBaseline(t *testing.T) { rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t where a > 10") tk.MustExec("select * from t where a > 10") tk.MustExec("admin capture bindings") @@ -143,7 +143,7 @@ func TestCapturePlanBaseline4DisabledStatus(t *testing.T) { rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t where a > 10") tk.MustExec("select * from t where a > 10") tk.MustExec("admin capture bindings") @@ -191,7 +191,7 @@ func TestCaptureDBCaseSensitivity(t *testing.T) { tk.MustExec("use SPM") tk.MustExec("create table t(a int, b int, key(b))") tk.MustExec("create global binding for select * from t using select /*+ use_index(t) */ * from t") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select /*+ use_index(t,b) */ * from t") tk.MustExec("select /*+ use_index(t,b) */ * from t") tk.MustExec("admin capture bindings") @@ -217,7 +217,7 @@ func TestCaptureBaselinesDefaultDB(t *testing.T) { tk.MustExec("drop database if exists spm") tk.MustExec("create database spm") tk.MustExec("create table spm.t(a int, index idx_a(a))") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from spm.t ignore index(idx_a) where a > 10") tk.MustExec("select * from spm.t ignore index(idx_a) where a > 10") tk.MustExec("admin capture bindings") @@ -244,7 +244,7 @@ func TestCapturePreparedStmt(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, c int, key idx_b(b), key idx_c(c))") @@ -279,7 +279,7 @@ func TestCapturePlanBaselineIgnoreTiFlash(t *testing.T) { tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int, key(a), key(b))") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t") tk.MustExec("select * from t") // Create virtual tiflash replica info. @@ -354,7 +354,7 @@ func TestBindingSource(t *testing.T) { tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t ignore index(idx_a) where a < 10") tk.MustExec("select * from t ignore index(idx_a) where a < 10") tk.MustExec("admin capture bindings") @@ -374,7 +374,7 @@ func TestCapturedBindingCharset(t *testing.T) { tk := testkit.NewTestKit(t, store) stmtsummary.StmtSummaryByDigestMap.Clear() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t(name varchar(25), index idx(name))") @@ -407,7 +407,7 @@ func TestConcurrentCapture(t *testing.T) { tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, b int)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t") tk.MustExec("select * from t") tk.MustExec("admin capture bindings") @@ -427,7 +427,7 @@ func TestUpdateSubqueryCapture(t *testing.T) { tk.MustExec("create table t1(a int, b int, c int, key idx_b(b))") tk.MustExec("create table t2(a int, b int)") stmtsummary.StmtSummaryByDigestMap.Clear() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("update t1 set b = 1 where b = 2 and (a in (select a from t2 where b = 1) or c in (select a from t2 where b = 1))") tk.MustExec("update t1 set b = 1 where b = 2 and (a in (select a from t2 where b = 1) or c in (select a from t2 where b = 1))") tk.MustExec("admin capture bindings") @@ -481,7 +481,7 @@ func TestIssue20417(t *testing.T) { stmtsummary.StmtSummaryByDigestMap.Clear() tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = on") dom.BindHandle().CaptureBaselines() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t where b=2 and c=213124") tk.MustExec("select * from t where b=2 and c=213124") tk.MustExec("admin capture bindings") @@ -526,7 +526,7 @@ func TestCaptureWithZeroSlowLogThreshold(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") stmtsummary.StmtSummaryByDigestMap.Clear() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("set tidb_slow_log_threshold = 0") tk.MustExec("select * from t") tk.MustExec("select * from t") @@ -552,7 +552,7 @@ func TestIssue25505(t *testing.T) { tk.MustExec("create table t (a int(11) default null,b int(11) default null,key b (b),key ba (b))") tk.MustExec("create table t1 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") tk.MustExec("create table t2 (a int(11) default null,b int(11) default null,key idx_ab (a,b),key idx_a (a),key idx_b (b))") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) spmMap := map[string]string{} spmMap["with recursive `cte` ( `a` ) as ( select ? union select `a` + ? from `test` . `t1` where `a` < ? ) select * from `cte`"] = @@ -619,7 +619,7 @@ func TestCaptureUserFilter(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t where a > 10") tk.MustExec("select * from t where a > 10") tk.MustExec("admin capture bindings") @@ -642,7 +642,7 @@ func TestCaptureUserFilter(t *testing.T) { tk.MustExec(`grant all on *.* to usr1 with grant option`) tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "usr1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "usr1", Hostname: "%"}, nil, nil, nil)) tk2.MustExec("select * from t where a > 10") tk2.MustExec("select * from t where a > 10") tk2.MustExec("admin capture bindings") @@ -707,7 +707,7 @@ func TestCaptureWildcardFilter(t *testing.T) { tk.MustExec("SET GLOBAL tidb_capture_plan_baselines = off") }() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) dbs := []string{"db11", "db12", "db2"} tbls := []string{"t11", "t12", "t2"} for _, db := range dbs { @@ -813,7 +813,7 @@ func TestCaptureFilter(t *testing.T) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("select * from t where a > 10") tk.MustExec("select * from t where a > 10") tk.MustExec("admin capture bindings") @@ -965,7 +965,7 @@ func TestCaptureHints(t *testing.T) { tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(pk int primary key, a int, b int, key(a), key(b))") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) captureCases := []struct { query string diff --git a/bindinfo/session_handle_test.go b/bindinfo/session_handle_test.go index a9b05c03eda18..1da00a925247c 100644 --- a/bindinfo/session_handle_test.go +++ b/bindinfo/session_handle_test.go @@ -179,7 +179,7 @@ func TestBaselineDBLowerCase(t *testing.T) { tk.MustExec("create database SPM") tk.MustExec("use SPM") tk.MustExec("create table t(a int, b int)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("update t set a = a + 1") tk.MustExec("update t set a = a + 1") tk.MustExec("admin capture bindings") @@ -269,7 +269,7 @@ func TestShowGlobalBindings(t *testing.T) { tk.MustExec("use SPM") tk.MustExec("create table t(a int, b int, key(a))") tk.MustExec("create table t0(a int, b int, key(a))") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) rows := tk.MustQuery("show global bindings").Rows() require.Len(t, rows, 0) // Simulate existing bindings in the mysql.bind_info. diff --git a/br/pkg/lightning/config/config_test.go b/br/pkg/lightning/config/config_test.go index 7ca3856c535fe..bf2feed43c9bc 100644 --- a/br/pkg/lightning/config/config_test.go +++ b/br/pkg/lightning/config/config_test.go @@ -783,7 +783,7 @@ func TestLoadConfig(t *testing.T) { err = taskCfg.Adjust(context.Background()) require.NoError(t, err) equivalentDSN := taskCfg.Checkpoint.MySQLParam.ToDriverConfig().FormatDSN() - expectedDSN := "guest:12345@tcp(172.16.30.11:4001)/?maxAllowedPacket=67108864&charset=utf8mb4&sql_mode=%27ONLY_FULL_GROUP_BY%2CSTRICT_TRANS_TABLES%2CNO_ZERO_IN_DATE%2CNO_ZERO_DATE%2CERROR_FOR_DIVISION_BY_ZERO%2CNO_AUTO_CREATE_USER%2CNO_ENGINE_SUBSTITUTION%27" + expectedDSN := "guest:12345@tcp(172.16.30.11:4001)/?charset=utf8mb4&sql_mode=%27ONLY_FULL_GROUP_BY%2CSTRICT_TRANS_TABLES%2CNO_ZERO_IN_DATE%2CNO_ZERO_DATE%2CERROR_FOR_DIVISION_BY_ZERO%2CNO_AUTO_CREATE_USER%2CNO_ENGINE_SUBSTITUTION%27" require.Equal(t, expectedDSN, equivalentDSN) result := taskCfg.String() diff --git a/ddl/db_cache_test.go b/ddl/db_cache_test.go index 012ac09ac7375..be2f37e3eb159 100644 --- a/ddl/db_cache_test.go +++ b/ddl/db_cache_test.go @@ -264,7 +264,7 @@ func TestIssue34069(t *testing.T) { defer sem.Disable() tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test;") tk.MustExec("create table t_34069 (t int);") // No error when SEM is enabled. diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 8367362dbec64..85e3021016bec 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -3583,7 +3583,7 @@ func TestAvoidCreateViewOnLocalTemporaryTable(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("drop table if exists tt0") tk.MustExec("drop table if exists tt1") tk.MustExec("drop table if exists tt2") diff --git a/ddl/db_test.go b/ddl/db_test.go index 8ff727a108837..2e76967f121a9 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -804,7 +804,7 @@ func TestForbidCacheTableForSystemTable(t *testing.T) { memOrSysDB := []string{"MySQL", "INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "METRICS_SCHEMA"} for _, db := range memOrSysDB { tk.MustExec("use " + db) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil) rows := tk.MustQuery("show tables").Rows() for i := 0; i < len(rows); i++ { sysTables = append(sysTables, rows[i][0].(string)) diff --git a/ddl/fktest/foreign_key_test.go b/ddl/fktest/foreign_key_test.go index 489e125dc8a3c..436875356ecf9 100644 --- a/ddl/fktest/foreign_key_test.go +++ b/ddl/fktest/foreign_key_test.go @@ -305,7 +305,7 @@ func TestCreateTableWithForeignKeyPrivilegeCheck(t *testing.T) { tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") - tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) err := tk2.ExecToErr("create table t2 (a int, foreign key fk(a) references t1(id));") require.Error(t, err) require.Equal(t, "[planner:1142]REFERENCES command denied to user 'u1'@'%' for table 't1'", err.Error()) @@ -330,7 +330,7 @@ func TestAlterTableWithForeignKeyPrivilegeCheck(t *testing.T) { tk.MustExec("create table t1 (id int key);") tk2 := testkit.NewTestKit(t, store) tk2.MustExec("use test") - tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk2.MustExec("create table t2 (a int)") err := tk2.ExecToErr("alter table t2 add foreign key (a) references t1 (id) on update cascade") require.Error(t, err) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index 9b798c9f45eea..d704626792c0c 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -82,7 +82,7 @@ func TestCreateSequence(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil, nil)) tk1.SetSession(se) // grant the myuser the access to database test. @@ -162,7 +162,7 @@ func TestDropSequence(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil, nil)) tk1.SetSession(se) // grant the myuser the access to database test. @@ -196,7 +196,7 @@ func TestShowCreateSequence(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil, nil)) tk1.SetSession(se) // Grant the myuser the access to table t in database test, but sequence seq. @@ -909,7 +909,7 @@ func TestSequenceFunctionPrivilege(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil, nil)) tk1.SetSession(se) // grant the myuser the create access to the sequence. @@ -1102,7 +1102,7 @@ func TestAlterSequencePrivilege(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil, nil)) tk1.SetSession(se) // grant the myuser the access to database test. diff --git a/ddl/tiflash_replica_test.go b/ddl/tiflash_replica_test.go index abd7275e4669b..eb7dc2be8336e 100644 --- a/ddl/tiflash_replica_test.go +++ b/ddl/tiflash_replica_test.go @@ -218,7 +218,7 @@ func TestSetTableFlashReplicaForSystemTable(t *testing.T) { memOrSysDB := []string{"MySQL", "INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "METRICS_SCHEMA"} for _, db := range memOrSysDB { tk.MustExec("use " + db) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil) rows := tk.MustQuery("show tables").Rows() for i := 0; i < len(rows); i++ { sysTables = append(sysTables, rows[i][0].(string)) diff --git a/domain/extract_test.go b/domain/extract_test.go index d6777380d97ee..c543972ef0c6f 100644 --- a/domain/extract_test.go +++ b/domain/extract_test.go @@ -104,6 +104,6 @@ func newTestKit(t *testing.T, store kv.Storage) *testkit.TestKit { func newTestKitWithRoot(t *testing.T, store kv.Storage) *testkit.TestKit { tk := newTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk } diff --git a/executor/cluster_table_test.go b/executor/cluster_table_test.go index f7497898d54b2..0653a0ad68fc5 100644 --- a/executor/cluster_table_test.go +++ b/executor/cluster_table_test.go @@ -291,7 +291,7 @@ func TestSQLDigestTextRetriever(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("insert into test_sql_digest_text_retriever values (1, 1)") insertNormalized, insertDigest := parser.NormalizeDigest("insert into test_sql_digest_text_retriever values (1, 1)") @@ -315,7 +315,7 @@ func TestFunctionDecodeSQLDigests(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("set global tidb_enable_stmt_summary = 1") tk.MustQuery("select @@global.tidb_enable_stmt_summary").Check(testkit.Rows("1")) tk.MustExec("drop table if exists test_func_decode_sql_digests") @@ -374,21 +374,21 @@ func TestFunctionDecodeSQLDigestsPrivilege(t *testing.T) { defer srv.Stop() dropUserTk := testkit.NewTestKit(t, store) - require.NoError(t, dropUserTk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, dropUserTk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("create user 'testuser'@'localhost'") defer dropUserTk.MustExec("drop user 'testuser'@'localhost'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser", Hostname: "localhost"}, nil, nil, nil)) tk.MustGetErrMsg("select tidb_decode_sql_digests('[\"aa\"]')", "[expression:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") tk = testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("create user 'testuser2'@'localhost'") defer dropUserTk.MustExec("drop user 'testuser2'@'localhost'") tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser2", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("select tidb_decode_sql_digests('[\"aa\"]')") } diff --git a/executor/executor_test.go b/executor/executor_test.go index 1af8c37f74634..0de1c01fc66f4 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -6098,7 +6098,7 @@ func TestSummaryFailedUpdate(t *testing.T) { tk.MustQuery("select variable_value from mysql.GLOBAL_VARIABLES where variable_name = 'tidb_mem_oom_action'").Check(testkit.Rows("LOG")) tk.MustExec("SET GLOBAL tidb_mem_oom_action='CANCEL'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("set @@tidb_mem_quota_query=1") tk.MustMatchErrMsg("update t set t.a = t.a - 1 where t.a in (select a from t where a < 4)", memory.PanicMemoryExceedWarnMsg) tk.MustExec("set @@tidb_mem_quota_query=1000000000") @@ -6203,7 +6203,7 @@ func TestTableLockPrivilege(t *testing.T) { tk.MustExec("use test") tk.MustExec("create table t(a int)") tk.MustExec("create user 'testuser'@'localhost'") - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "testuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "testuser", Hostname: "localhost"}, nil, nil, nil)) tk2.MustGetErrMsg("LOCK TABLE test.t WRITE", "[planner:1044]Access denied for user 'testuser'@'localhost' to database 'test'") tk.MustExec("GRANT LOCK TABLES ON test.* to 'testuser'@'localhost'") tk2.MustGetErrMsg("LOCK TABLE test.t WRITE", "[planner:1142]SELECT command denied to user 'testuser'@'localhost' for table 't'") diff --git a/executor/explain_test.go b/executor/explain_test.go index d5e609d821fa5..aacc852f53582 100644 --- a/executor/explain_test.go +++ b/executor/explain_test.go @@ -38,7 +38,7 @@ func TestExplainPrivileges(t *testing.T) { store := testkit.CreateMockStore(t) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk := testkit.NewTestKit(t, store) tk.SetSession(se) @@ -51,7 +51,7 @@ func TestExplainPrivileges(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err = session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "explain", Hostname: "%"}, nil, nil, nil)) tk1.SetSession(se) tk.MustExec(`grant select on explaindatabase.v to 'explain'@'%'`) diff --git a/executor/explainfor_test.go b/executor/explainfor_test.go index 11271a12698d8..a50b7b988996e 100644 --- a/executor/explainfor_test.go +++ b/executor/explainfor_test.go @@ -40,8 +40,8 @@ func TestExplainFor(t *testing.T) { tkRoot.MustExec("create table t1(c1 int, c2 int)") tkRoot.MustExec("create table t2(c1 int, c2 int)") tkRoot.MustExec("create user tu@'%'") - tkRoot.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) - tkUser.Session().Auth(&auth.UserIdentity{Username: "tu", Hostname: "localhost", CurrentUser: true, AuthUsername: "tu", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tkRoot.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) + tkUser.Session().Auth(&auth.UserIdentity{Username: "tu", Hostname: "localhost", CurrentUser: true, AuthUsername: "tu", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tkRoot.MustExec("set @@tidb_enable_collect_execution_info=0;") tkRoot.MustQuery("select * from t1;") @@ -441,7 +441,7 @@ func TestPointGetUserVarPlanCache(t *testing.T) { tmp := testkit.NewTestKit(t, store) tmp.MustExec("set tidb_enable_prepared_plan_cache=ON") tk := testkit.NewTestKit(t, store) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("use test") tk.MustExec("set tidb_cost_model_version=2") diff --git a/executor/fktest/foreign_key_test.go b/executor/fktest/foreign_key_test.go index a24be95c33d4b..4b0a21e0308d0 100644 --- a/executor/fktest/foreign_key_test.go +++ b/executor/fktest/foreign_key_test.go @@ -2491,7 +2491,7 @@ func TestPrivilegeCheckInForeignKeyCascade(t *testing.T) { for _, sql := range ca.prepares { tk.MustExec(sql) } - err := tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + err := tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) require.NoError(t, err) if ca.err == nil { tk2.MustExec(ca.sql) @@ -2542,7 +2542,7 @@ func TestForeignKeyIssue39732(t *testing.T) { tk.MustExec("use test") tk.MustExec("create user 'u1'@'%' identified by '';") tk.MustExec("GRANT ALL PRIVILEGES ON *.* TO 'u1'@'%'") - err := tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + err := tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) require.NoError(t, err) tk.MustExec("create table t1 (id int key, leader int, index(leader), foreign key (leader) references t1(id) ON DELETE CASCADE);") tk.MustExec("insert into t1 values (1, null), (10, 1), (11, 1), (20, 10)") diff --git a/executor/grant_test.go b/executor/grant_test.go index 8a5a774ce0a3e..d0e413a0d2aab 100644 --- a/executor/grant_test.go +++ b/executor/grant_test.go @@ -471,7 +471,7 @@ func TestGrantOnNonExistTable(t *testing.T) { tk.MustExec("GRANT CREATE, DROP, INSERT ON t29268 TO u29268") // check privilege - tk.Session().Auth(&auth.UserIdentity{Username: "u29268", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "u29268", Hostname: "localhost"}, nil, nil, nil) tk.MustExec("USE d29268") tk.MustExec("CREATE TABLE t29268 (c1 int)") tk.MustExec("INSERT INTO t29268 VALUES (1), (2)") @@ -479,7 +479,7 @@ func TestGrantOnNonExistTable(t *testing.T) { tk.MustExec("DROP TABLE t29268") // check grant all - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil) tk.MustExec("GRANT ALL ON t29268 TO u29268") } @@ -505,7 +505,7 @@ func TestPerformanceSchemaPrivGrant(t *testing.T) { defer func() { tk.MustExec("drop user issue27867;") }() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustGetErrCode("grant all on performance_schema.* to issue27867;", errno.ErrDBaccessDenied) // Check case insensitivity tk.MustGetErrCode("grant all on PERFormanCE_scHemA.* to issue27867;", errno.ErrDBaccessDenied) diff --git a/executor/infoschema_cluster_table_test.go b/executor/infoschema_cluster_table_test.go index 57dd1a65969dd..7e1d9bb01d07c 100644 --- a/executor/infoschema_cluster_table_test.go +++ b/executor/infoschema_cluster_table_test.go @@ -307,7 +307,7 @@ func TestTableStorageStats(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) // User has no access to this schema, so the result set is empty. tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) @@ -315,14 +315,14 @@ func TestTableStorageStats(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser2", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows(strconv.Itoa(result))) require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser3", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows(strconv.Itoa(result))) } diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index cae75d72c35e0..67c3c87eac512 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -102,7 +102,7 @@ func TestSchemataTables(t *testing.T) { require.NoError(t, schemataTester.Session().Auth(&auth.UserIdentity{ Username: "schemata_tester", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) schemataTester.MustQuery("select count(*) from information_schema.SCHEMATA;").Check(testkit.Rows("1")) schemataTester.MustQuery("select * from information_schema.SCHEMATA where schema_name='mysql';").Check( [][]interface{}{}) @@ -243,7 +243,7 @@ func TestDDLJobs(t *testing.T) { require.NoError(t, DDLJobsTester.Session().Auth(&auth.UserIdentity{ Username: "DDL_JOBS_tester", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) // Test the privilege of user for information_schema.ddl_jobs. DDLJobsTester.MustQuery("select DB_NAME, TABLE_NAME from information_schema.DDL_JOBS where DB_NAME = 'test_ddl_jobs' and TABLE_NAME = 't';").Check( @@ -275,7 +275,7 @@ func TestKeyColumnUsage(t *testing.T) { require.NoError(t, keyColumnTester.Session().Auth(&auth.UserIdentity{ Username: "key_column_tester", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) keyColumnTester.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with privilege of mysql.gc_delete_range for information_schema.table_constraints @@ -297,7 +297,7 @@ func TestUserPrivileges(t *testing.T) { require.NoError(t, constraintsTester.Session().Auth(&auth.UserIdentity{ Username: "constraints_tester", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS WHERE TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with privilege of mysql.gc_delete_range for information_schema.table_constraints @@ -316,7 +316,7 @@ func TestUserPrivileges(t *testing.T) { require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{ Username: "tester1", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) tk1.MustQuery("select * from information_schema.STATISTICS WHERE TABLE_NAME != 'CLUSTER_SLOW_QUERY';").Check([][]interface{}{}) // test the privilege of user with some privilege for information_schema @@ -329,7 +329,7 @@ func TestUserPrivileges(t *testing.T) { require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{ Username: "tester2", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) tk2.MustExec("set role r_columns_priv") rows = tk2.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';").Rows() require.Greater(t, len(rows), 0) @@ -346,7 +346,7 @@ func TestUserPrivileges(t *testing.T) { require.NoError(t, tk3.Session().Auth(&auth.UserIdentity{ Username: "tester3", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) tk3.MustExec("set role r_all_priv") rows = tk3.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';").Rows() require.Greater(t, len(rows), 0) @@ -364,7 +364,7 @@ func TestUserPrivilegesTable(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "usageuser", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee="'usageuser'@'%'"`).Check(testkit.Rows("'usageuser'@'%' def USAGE NO")) // the usage row disappears when there is a non-dynamic privilege added tk1.MustExec("GRANT SELECT ON *.* to usageuser") @@ -586,7 +586,7 @@ func TestForAnalyzeStatus(t *testing.T) { require.NoError(t, analyzeTester.Session().Auth(&auth.UserIdentity{ Username: "analyze_tester", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) analyzeTester.MustQuery("show analyze status").Check([][]interface{}{}) analyzeTester.MustQuery("select * from information_schema.ANALYZE_STATUS;").Check([][]interface{}{}) diff --git a/executor/issuetest/executor_issue_test.go b/executor/issuetest/executor_issue_test.go index 3a7cc9318965c..f874a2d8021f8 100644 --- a/executor/issuetest/executor_issue_test.go +++ b/executor/issuetest/executor_issue_test.go @@ -478,7 +478,7 @@ func TestIndexJoin31494(t *testing.T) { dom.ExpensiveQueryHandle().SetSessionManager(sm) defer tk.MustExec("SET GLOBAL tidb_mem_oom_action = DEFAULT") tk.MustExec("SET GLOBAL tidb_mem_oom_action='CANCEL'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("set @@tidb_mem_quota_query=2097152;") // This bug will be reproduced in 10 times. for i := 0; i < 10; i++ { diff --git a/executor/passwordtest/password_management_test.go b/executor/passwordtest/password_management_test.go index b817a8facb965..ec15e0a140474 100644 --- a/executor/passwordtest/password_management_test.go +++ b/executor/passwordtest/password_management_test.go @@ -40,11 +40,11 @@ func TestValidatePassword(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) subtk := testkit.NewTestKit(t, store) - err := tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + err := tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil) require.NoError(t, err) tk.MustExec("CREATE USER ''@'localhost'") tk.MustExec("GRANT ALL PRIVILEGES ON mysql.* TO ''@'localhost';") - err = subtk.Session().Auth(&auth.UserIdentity{Hostname: "localhost"}, nil, nil) + err = subtk.Session().Auth(&auth.UserIdentity{Hostname: "localhost"}, nil, nil, nil) require.NoError(t, err) authPlugins := []string{mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password} @@ -280,7 +280,7 @@ func TestPasswordManagement(t *testing.T) { result = rootTK.MustQuery(`Select authentication_string from mysql.user where user = 'u2' and host = '%'`) result.Check(testkit.Rows(auth.EncodePassword("Uu3@22222"))) // Auto-lock in effect. - err := tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password(""), nil) + err := tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password(""), nil, nil) require.ErrorContains(t, err, "Account is blocked for 1 day(s) (1 day(s) remaining) due to 1 consecutive failed logins.") result = rootTK.MustQuery(`SELECT JSON_UNQUOTE(JSON_EXTRACT(user_attributes, '$.Password_locking.failed_login_count')), @@ -299,10 +299,10 @@ func TestPasswordManagement(t *testing.T) { err = domain.GetDomain(rootTK.Session()).NotifyUpdatePrivilege() require.NoError(t, err) // Password expires and takes effect. - err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22222"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22222"), nil, nil) require.ErrorContains(t, err, "Your password has expired.") variable.IsSandBoxModeEnabled.Store(true) - err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22222"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22222"), nil, nil) require.NoError(t, err) require.True(t, tk.Session().InSandBoxMode()) @@ -321,7 +321,7 @@ func TestPasswordManagement(t *testing.T) { result = rootTK.MustQuery(`Select authentication_string from mysql.user where user = 'u2' and host = '%'`) result.Check(testkit.Rows(auth.EncodePassword("Uu3@22223"))) tk = testkit.NewTestKit(t, store) - err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22223"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "%"}, sha1Password("Uu3@22223"), nil, nil) require.NoError(t, err) } @@ -749,43 +749,43 @@ func TestFailedLoginTracking(t *testing.T) { // Set FAILED_LOGIN_ATTEMPTS to 1, and check error messages after login failure once. createAndCheck(tk, "CREATE USER 'testu1'@'localhost' IDENTIFIED BY 'testu1' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 1", "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}}", "testu1") - err := tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, sha1Password("password"), nil) + err := tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, sha1Password("password"), nil, nil) lds := strconv.FormatInt(1, 10) errTarget := privileges.GenerateAccountAutoLockErr(1, "testu1", "localhost", lds, lds) require.Equal(t, err.Error(), errTarget.Error()) checkAuthUser(t, tk, "testu1", 1, "Y") // Check the login error message after the account is locked. - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, sha1Password("password"), nil, nil) require.Equal(t, err.Error(), errTarget.Error()) checkAuthUser(t, tk, "testu1", 1, "Y") // Set FAILED_LOGIN_ATTEMPTS to 1 and PASSWORD_LOCK_TIME to UNBOUNDED. Check error messages after failed login once. createAndCheck(tk, "CREATE USER 'testu2'@'localhost' IDENTIFIED BY 'testu2' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME UNBOUNDED", "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": -1}}", "testu2") - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu2", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu2", Hostname: "localhost"}, sha1Password("password"), nil, nil) errTarget = privileges.GenerateAccountAutoLockErr(1, "testu2", "localhost", "unlimited", "unlimited") require.Equal(t, err.Error(), errTarget.Error()) checkAuthUser(t, tk, "testu2", 1, "Y") // Check the login error message after the account is locked. - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu2", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu2", Hostname: "localhost"}, sha1Password("password"), nil, nil) require.Equal(t, err.Error(), errTarget.Error()) checkAuthUser(t, tk, "testu2", 1, "Y") // Set FAILED_LOGIN_ATTEMPTS to 0 or PASSWORD_LOCK_TIME to 0. Check error messages after failed login once. createAndCheck(tk, "CREATE USER 'testu3'@'localhost' IDENTIFIED BY 'testu3' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME UNBOUNDED", "{\"Password_locking\": {\"failed_login_attempts\": 0, \"password_lock_time_days\": -1}}", "testu3") - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu3", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu3", Hostname: "localhost"}, sha1Password("password"), nil, nil) require.ErrorContains(t, err, "Access denied for user 'testu3'@'localhost' (using password: YES)") checkAuthUser(t, tk, "testu3", 0, "") createAndCheck(tk, "CREATE USER 'testu4'@'localhost' IDENTIFIED BY 'testu4' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 0", "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 0}}", "testu4") - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu4", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu4", Hostname: "localhost"}, sha1Password("password"), nil, nil) require.ErrorContains(t, err, "Access denied for user 'testu4'@'localhost' (using password: YES)") checkAuthUser(t, tk, "testu4", 0, "") tk.MustExec("CREATE USER 'testu5'@'localhost' IDENTIFIED BY 'testu5' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME 0") - err = tk.Session().Auth(&auth.UserIdentity{Username: "testu5", Hostname: "localhost"}, sha1Password("password"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "testu5", Hostname: "localhost"}, sha1Password("password"), nil, nil) require.ErrorContains(t, err, "Access denied for user 'testu5'@'localhost' (using password: YES)") tk.MustQuery("select user_attributes from mysql.user where user= 'testu5' and host = 'localhost'").Check(testkit.Rows("{}")) @@ -819,12 +819,12 @@ func TestFailedLoginTracking(t *testing.T) { // Confirm the user_attributes value after login failure once. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu5", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu5", "localhost", "2 \"N\" 1 1 {\"comment\": \"testcomment\"}") // After the number of failed login attempts reaches FAILED_LOGIN_ATTEMPTS, check the account lock status. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu5", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu5", "localhost", "2 \"Y\" 2 1 {\"comment\": \"testcomment\"}") // After the account is locked, manually unlock the account and check the user_attributes value. tk.MustExec("alter user testu5@'localhost' account unlock") @@ -836,19 +836,19 @@ func TestFailedLoginTracking(t *testing.T) { "comment 'testcomment'") // Confirm the user_attributes value after login failure once. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu6", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu6", "localhost", "2 \"N\" 1 1 {\"comment\": \"testcomment\"}") // After the number of failed login attempts reaches FAILED_LOGIN_ATTEMPTS, check the account lock status. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu6", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu6", "localhost", "2 \"Y\" 2 1 {\"comment\": \"testcomment\"}") // After the account is automatically locked, change the lock time and check // the user_attributes value after logging in successfully. changeAutoLockedLastChanged(tk, "-72h1s", "testu6") sk1 := testkit.NewTestKit(t, store) - require.NoError(t, sk1.Session().Auth(&auth.UserIdentity{Username: "testu6", Hostname: "localhost"}, nil, nil)) + require.NoError(t, sk1.Session().Auth(&auth.UserIdentity{Username: "testu6", Hostname: "localhost"}, nil, nil, nil)) checkUserUserAttributes(tk, "testu6", "localhost", "3 \"N\" 0 3 {\"comment\": \"testcomment\"}") // Create user specified attributes, FAILED_LOGIN_ATTEMPTS, and PASSWORD_LOCK_TIME, @@ -859,12 +859,12 @@ func TestFailedLoginTracking(t *testing.T) { // Confirm the user_attributes value after login failure once. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu7", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu7", "localhost", "2 \"N\" 1 1 {\"attribute\": \"testattribute\"}") // After the number of failed login attempts reaches FAILED_LOGIN_ATTEMPTS, check the account lock status. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu7", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu7", "localhost", "2 \"Y\" 2 1 {\"attribute\": \"testattribute\"}") // After the account is locked, manually unlock the account and check the user_attributes value. @@ -875,19 +875,19 @@ func TestFailedLoginTracking(t *testing.T) { " ATTRIBUTE '{\"attribute\":\"testattribute\"}'") // Confirm the user_attributes value after login failure once. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu8", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu8", "localhost", "2 \"N\" 1 1 {\"attribute\": \"testattribute\"}") // After the number of failed login attempts reaches FAILED_LOGIN_ATTEMPTS, check the account lock status. require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu8", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu8", "localhost", "2 \"Y\" 2 1 {\"attribute\": \"testattribute\"}") // After the account is automatically locked, change the lock time and check // the user_attributes value after logging in successfully. changeAutoLockedLastChanged(tk, "-72h1s", "testu8") sk2 := testkit.NewTestKit(t, store) - require.NoError(t, sk2.Session().Auth(&auth.UserIdentity{Username: "testu8", Hostname: "localhost"}, nil, nil)) + require.NoError(t, sk2.Session().Auth(&auth.UserIdentity{Username: "testu8", Hostname: "localhost"}, nil, nil, nil)) checkUserUserAttributes(tk, "testu8", "localhost", "3 \"N\" 0 3 {\"attribute\": \"testattribute\"}") // FAILED_LOGIN_ATTEMPTS is set to 2 . check user_attributes value after @@ -895,24 +895,24 @@ func TestFailedLoginTracking(t *testing.T) { tk.MustExec("create user testu9@'localhost' identified by '' FAILED_LOGIN_ATTEMPTS 2 PASSWORD_LOCK_TIME 1" + " comment 'testcomment'") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu9", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu9", "localhost", "2 \"N\" 1 1 {\"comment\": \"testcomment\"}") sk3 := testkit.NewTestKit(t, store) require.NoError(t, sk3.Session().Auth(&auth.UserIdentity{Username: "testu9", Hostname: "localhost"}, - nil, nil)) + nil, nil, nil)) checkUserUserAttributes(tk, "testu9", "localhost", "2 \"N\" 0 1 {\"comment\": \"testcomment\"}") // FAILED_LOGIN_ATTEMPTS or PASSWORD_LOCK_TIME is set to 0. Check user_attributes value after login fail. tk.MustExec("create user testu10@'localhost' identified by '' FAILED_LOGIN_ATTEMPTS 2 PASSWORD_LOCK_TIME 0 " + "comment 'testcomment'") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu10", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu10", "localhost", "2 0 {\"comment\": \"testcomment\"}") tk.MustExec("create user testu11@'localhost' identified by '' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME 2 " + "comment 'testcomment'") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu11", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu11", "localhost", "0 2 {\"comment\": \"testcomment\"}") // The account is automatically locked after the user specifies FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME. @@ -920,15 +920,15 @@ func TestFailedLoginTracking(t *testing.T) { tk.MustExec("create user testu12@'localhost' identified by '' FAILED_LOGIN_ATTEMPTS 2 PASSWORD_LOCK_TIME 1 " + "comment 'testcomment'") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu12", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu12", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu12", "localhost", "2 \"Y\" 2 1 {\"comment\": \"testcomment\"}") tk.MustExec("alter user testu12@'localhost' FAILED_LOGIN_ATTEMPTS 0") checkUserUserAttributes(tk, "testu12", "localhost", "0 \"Y\" 2 1 {\"comment\": \"testcomment\"}") sk4 := testkit.NewTestKit(t, store) require.NoError(t, sk4.Session().Auth(&auth.UserIdentity{Username: "testu12", Hostname: "localhost"}, - nil, nil)) + nil, nil, nil)) rootk := testkit.NewTestKit(t, store) createAndCheck(tk, "CREATE USER 'u6'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3", @@ -936,59 +936,59 @@ func TestFailedLoginTracking(t *testing.T) { createAndCheck(tk, "CREATE USER 'u5'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 60 PASSWORD_LOCK_TIME 3", "{\"Password_locking\": {\"failed_login_attempts\": 60, \"password_lock_time_days\": 3}}", "u5") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, nil, nil, nil)) checkAuthUser(t, rootk, "u6", 0, "N") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 2, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 3, "Y") changeAutoLockedLastChanged(rootk, "-72h1s", "u6") loadUser(t, tk, 1, rootk) checkAuthUser(t, rootk, "u6", 3, "Y") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, nil, nil, nil)) checkAuthUser(t, rootk, "u6", 0, "N") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 2, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 3, "Y") alterAndCheck(t, rootk, "ALTER USER 'u6'@'localhost' ACCOUNT UNLOCK;", "u6", 3, 3, 0) loadUser(t, tk, 2, rootk) checkAuthUser(t, rootk, "u6", 0, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") alterAndCheck(t, rootk, "ALTER USER 'u6'@'localhost' ACCOUNT UNLOCK;", "u6", 3, 3, 0) checkAuthUser(t, rootk, "u6", 0, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 2, "N") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 3, "Y") changeAutoLockedLastChanged(rootk, "-72h1s", "u6") loadUser(t, tk, 3, rootk) checkAuthUser(t, rootk, "u6", 3, "Y") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u6", 1, "N") createAndCheck(rootk, "CREATE USER 'u1'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 3", "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 0}}", "u1") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u1", 0, "") alterAndCheck(t, rootk, "ALTER USER 'u1'@'localhost' PASSWORD_LOCK_TIME 6;", "u1", 3, 6, 0) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u1", 1, "N") } @@ -1061,7 +1061,7 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { tk.MustExec("CREATE USER 'testu7'@'localhost' IDENTIFIED BY 'testu7' FAILED_LOGIN_ATTEMPTS 1 " + "PASSWORD_LOCK_TIME 1 comment 'testcomment'") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu7", Hostname: "localhost"}, - sha1Password("password"), nil)) + sha1Password("password"), nil, nil)) checkUserUserAttributes(tk, "testu7", "localhost", "1 \"Y\" 1 1 {\"comment\": \"testcomment\"}") tk.MustExec("alter user 'testu7'@'localhost' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME 0") tk.MustQuery("select JSON_EXTRACT(user_attributes, '$.Password_locking'),JSON_EXTRACT(user_attributes,'$.metadata') " + @@ -1116,12 +1116,12 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { err := domain.GetDomain(rootTK.Session()).NotifyUpdatePrivilege() require.NoError(t, err) rootTK.MustExec(`CREATE USER test1 IDENTIFIED BY '1234' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3 COMMENT 'test'`) - err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password("1234"), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password("1234"), nil, nil) require.NoError(t, err) sqlexec.MustFormatSQL(sql, checkUserAttributes, "test1", "%") rootTK.MustQuery(sql.String()).Check(testkit.Rows(`3 3 {"comment": "test"}`)) tk = testkit.NewTestKit(t, store) - err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil, nil) require.Error(t, err) rootTK.MustQuery(sql.String()).Check(testkit.Rows(`3 "N" 1 3 {"comment": "test"}`)) @@ -1134,9 +1134,9 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { rootTK.MustExec(`Alter user test1 FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3 COMMENT 'test'`) rootTK.MustQuery(sql.String()).Check(testkit.Rows(`3 "N" 1 3 {"comment": "test"}`)) - err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil, nil) require.Error(t, err) - err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil) + err = tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "%"}, sha1Password(""), nil, nil) require.Error(t, err) rootTK.MustQuery(sql.String()).Check(testkit.Rows(`3 "Y" 3 3 {"comment": "test"}`)) rootTK.MustExec(`Alter user test1 FAILED_LOGIN_ATTEMPTS 4 `) @@ -1166,7 +1166,7 @@ func TestFailedLoginTrackingCheckPrivilges(t *testing.T) { tk := testkit.NewTestKit(t, store) createAndCheck(tk, "CREATE USER 'testu1'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 1", "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}}", "testu1") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, nil, nil, nil)) // Specify FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME attributes when creating user , // Check user privileges after successful login. tk.MustQuery(`show grants`).Check(testkit.Rows("GRANT USAGE ON *.* TO 'testu1'@'localhost'")) @@ -1210,9 +1210,9 @@ func TestUserPassword(t *testing.T) { tk := testkit.NewTestKit(t, store) rootk := testkit.NewTestKit(t, store) createAndCheckToErr(t, rootk, tc.errSQL, tc.user) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: tc.user, Hostname: tc.host}, sha1Password(tc.simplePassword), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: tc.user, Hostname: tc.host}, sha1Password(tc.simplePassword), nil, nil)) createAndCheck(rootk, tc.sucSQL, tc.rsJSON, tc.user) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: tc.user, Hostname: tc.host}, sha1Password(tc.strongPassword), nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: tc.user, Hostname: tc.host}, sha1Password(tc.strongPassword), nil, nil)) } } @@ -1224,16 +1224,16 @@ func TestPasswordExpiredAndTacking(t *testing.T) { tk.MustExec(`set global validate_password.enable = ON`) tk = testkit.NewTestKit(t, store) createAndCheckToErr(t, tk, `CREATE USER 'u3'@'localhost' IDENTIFIED BY 'qwe123' PASSWORD EXPIRE INTERVAL 3 DAY FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 3 COMMENT 'Some statements to test create user'`, user) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("qwe123"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("qwe123"), nil, nil)) tk = testkit.NewTestKit(t, store) createAndCheck(tk, `CREATE USER 'u3'@'localhost' IDENTIFIED BY '!@#HASHhs123' PASSWORD EXPIRE INTERVAL 3 DAY FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 3 COMMENT 'Some statements to test create user'`, "{\"Password_locking\": {\"failed_login_attempts\": 4, \"password_lock_time_days\": 3}, \"metadata\": {\"comment\": \"Some statements to test create user\"}}", user) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil, nil)) tk = testkit.NewTestKit(t, store) tk.MustExec(fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE NEVER", user, host)) tk = testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil, nil)) loginFailedAncCheck(t, store, user, host, "password", 1, "N") loginSucAncCheck(t, store, user, host, "!@#HASHhs123", 0, "N") @@ -1245,24 +1245,24 @@ func TestPasswordExpiredAndTacking(t *testing.T) { tk = testkit.NewTestKit(t, store) tk.MustExec(fmt.Sprintf("ALTER USER '%s'@'%s' PASSWORD EXPIRE", user, host)) tk = testkit.NewTestKit(t, store) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil, nil)) } func loginFailedAncCheck(t *testing.T, store kv.Storage, user, host, password string, failedLoginCount int64, autoAccountLocked string) { tk := testkit.NewTestKit(t, store) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password(password), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password(password), nil, nil)) checkAuthUser(t, tk, user, failedLoginCount, autoAccountLocked) } func loginSucAncCheck(t *testing.T, store kv.Storage, user, host, password string, failedLoginCount int64, autoAccountLocked string) { tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password(password), nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password(password), nil, nil)) tk = testkit.NewTestKit(t, store) checkAuthUser(t, tk, user, failedLoginCount, autoAccountLocked) } func loadUser(t *testing.T, tk *testkit.TestKit, useCount int64, rootk *testkit.TestKit) { - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u5", Hostname: "localhost"}, sha1Password("password"), nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u5", Hostname: "localhost"}, sha1Password("password"), nil, nil)) checkAuthUser(t, rootk, "u5", useCount, "N") } diff --git a/executor/prepared_test.go b/executor/prepared_test.go index 079e06e56b5e0..89692bb1f99f2 100644 --- a/executor/prepared_test.go +++ b/executor/prepared_test.go @@ -1169,7 +1169,7 @@ func TestPrepareStmtAfterIsolationReadChange(t *testing.T) { store, dom := testkit.CreateMockStoreAndDomain(t) tk := testkit.NewTestKit(t, store) tk.MustExec(`set tidb_enable_prepared_plan_cache=0`) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") @@ -1216,7 +1216,7 @@ func TestPreparePC4Binding(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int)") diff --git a/executor/recover_test.go b/executor/recover_test.go index 92aa83ec99d3e..6fd3426f9c7b6 100644 --- a/executor/recover_test.go +++ b/executor/recover_test.go @@ -314,7 +314,7 @@ func TestRecoverTablePrivilege(t *testing.T) { // Recover without drop/create privilege. tk.MustExec("CREATE USER 'testrecovertable'@'localhost';") newTk := testkit.NewTestKit(t, store) - require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testrecovertable", Hostname: "localhost"}, nil, nil)) + require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testrecovertable", Hostname: "localhost"}, nil, nil, nil)) newTk.MustGetErrCode("recover table t_recover", errno.ErrTableaccessDenied) newTk.MustGetErrCode("flashback table t_recover", errno.ErrTableaccessDenied) @@ -363,7 +363,7 @@ func TestRecoverClusterMeetError(t *testing.T) { // Flashback without super privilege. tk.MustExec("CREATE USER 'testflashback'@'localhost';") newTk := testkit.NewTestKit(t, store) - require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testflashback", Hostname: "localhost"}, nil, nil)) + require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testflashback", Hostname: "localhost"}, nil, nil, nil)) newTk.MustGetErrCode(fmt.Sprintf("flashback cluster to timestamp '%s'", time.Now().Add(0-30*time.Second)), errno.ErrPrivilegeCheckFail) tk.MustExec("drop user 'testflashback'@'localhost';") @@ -544,7 +544,7 @@ func TestFlashbackSchema(t *testing.T) { // Recover without drop/create privilege. tk.MustExec("CREATE USER 'testflashbackschema'@'localhost';") newTk := testkit.NewTestKit(t, store) - require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testflashbackschema", Hostname: "localhost"}, nil, nil)) + require.NoError(t, newTk.Session().Auth(&auth.UserIdentity{Username: "testflashbackschema", Hostname: "localhost"}, nil, nil, nil)) newTk.MustGetErrCode("flashback database t_recover", errno.ErrDBaccessDenied) // Got drop privilege, still failed. diff --git a/executor/show_placement_test.go b/executor/show_placement_test.go index f03b09cb63d04..db5b35fb8e0c5 100644 --- a/executor/show_placement_test.go +++ b/executor/show_placement_test.go @@ -151,7 +151,7 @@ func TestShowPlacementPrivilege(t *testing.T) { defer tk.MustExec("drop table if exists db2.t3") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil, nil)) // before grant tk1.MustQuery("show placement").Check(testkit.Rows( @@ -308,7 +308,7 @@ func TestShowPlacementForDBPrivilege(t *testing.T) { defer tk.MustExec("drop table db2.t1") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil, nil)) privs := []string{ "all privileges on db2.*", @@ -400,7 +400,7 @@ func TestShowPlacementForTableAndPartitionPrivilege(t *testing.T) { defer tk.MustExec("drop table if exists db2.t1") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "user1", Hostname: "%"}, nil, nil, nil)) // before grant err := tk1.ExecToErr("show placement for table test.t1") diff --git a/executor/showtest/show_test.go b/executor/showtest/show_test.go index 852c30248e81d..e26006e038e4a 100644 --- a/executor/showtest/show_test.go +++ b/executor/showtest/show_test.go @@ -59,7 +59,7 @@ func TestShowOpenTables(t *testing.T) { func TestShowCreateViewDefiner(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%", AuthUsername: "root", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%", AuthUsername: "root", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create or replace view v1 as select 1") @@ -679,7 +679,7 @@ func TestShowVisibility(t *testing.T) { tk.MustExec(`create user 'show'@'%'`) tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil, nil)) // No ShowDatabases privilege, this user would see nothing except INFORMATION_SCHEMA. tk.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA")) @@ -717,7 +717,7 @@ func TestShowDatabasesInfoSchemaFirst(t *testing.T) { tk.MustExec(`grant select on BBBB.* to 'show'@'%'`) tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil, nil)) tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "AAAA", "BBBB")) tk.MustExec(`drop user 'show'@'%'`) @@ -821,12 +821,12 @@ func TestShowGrantsPrivilege(t *testing.T) { tk.MustExec("create user show_grants") tk.MustExec("show grants for show_grants") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "%"}, nil, nil, nil)) err := tk1.QueryToErr("show grants for root") require.EqualError(t, exeerrors.ErrDBaccessDenied.GenWithStackByArgs("show_grants", "%", mysql.SystemDB), err.Error()) // Test show grants for user with auth host name `%`. tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "127.0.0.1", AuthUsername: "show_grants", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "show_grants", Hostname: "127.0.0.1", AuthUsername: "show_grants", AuthHostname: "%"}, nil, nil, nil)) tk2.MustQuery("show grants") } @@ -836,7 +836,7 @@ func TestShowStatsPrivilege(t *testing.T) { tk.MustExec("create user show_stats") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_stats", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "show_stats", Hostname: "%"}, nil, nil, nil)) e := "[planner:1142]SHOW command denied to user 'show_stats'@'%' for table" err := tk1.ExecToErr("show stats_meta") require.ErrorContains(t, err, e) @@ -855,7 +855,7 @@ func TestShowStatsPrivilege(t *testing.T) { tk1.MustExec("SHOW STATS_HISTOGRAMS") tk.MustExec("create user a@'%' identified by '';") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "a", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "a", Hostname: "%"}, nil, nil, nil)) tk.MustExec("grant select on mysql.stats_meta to a@'%';") tk.MustExec("grant select on mysql.stats_buckets to a@'%';") tk.MustExec("grant select on mysql.stats_histograms to a@'%';") @@ -867,7 +867,7 @@ func TestShowStatsPrivilege(t *testing.T) { func TestIssue18878(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthHostname: "%"}, nil, nil, nil)) tk.MustQuery("select user()").Check(testkit.Rows("root@127.0.0.1")) tk.MustQuery("show grants") tk.MustQuery("select user()").Check(testkit.Rows("root@127.0.0.1")) @@ -887,10 +887,10 @@ func TestIssue17794(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) tk.MustExec("CREATE USER 'root'@'8.8.%'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "9.9.9.9", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "9.9.9.9", AuthHostname: "%"}, nil, nil, nil)) tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "8.8.8.8", AuthHostname: "8.8.%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "8.8.8.8", AuthHostname: "8.8.%"}, nil, nil, nil)) tk.MustQuery("show grants").Check(testkit.Rows("GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION")) tk1.MustQuery("show grants").Check(testkit.Rows("GRANT USAGE ON *.* TO 'root'@'8.8.%'")) } @@ -912,7 +912,7 @@ func TestIssue10549(t *testing.T) { tk.MustExec("GRANT 'app_developer' TO 'dev';") tk.MustExec("SET DEFAULT ROLE app_developer TO 'dev';") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "%", AuthUsername: "dev", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "%", AuthUsername: "dev", AuthHostname: "%"}, nil, nil, nil)) tk.MustQuery("SHOW DATABASES;").Check(testkit.Rows("INFORMATION_SCHEMA", "newdb")) tk.MustQuery("SHOW GRANTS;").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'")) tk.MustQuery("SHOW GRANTS FOR CURRENT_USER").Check(testkit.Rows("GRANT USAGE ON *.* TO 'dev'@'%'", "GRANT ALL PRIVILEGES ON newdb.* TO 'dev'@'%'", "GRANT 'app_developer'@'%' TO 'dev'@'%'")) @@ -926,7 +926,7 @@ func TestIssue11165(t *testing.T) { tk.MustExec("CREATE USER 'manager'@'localhost';") tk.MustExec("GRANT 'r_manager' TO 'manager'@'localhost';") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "manager", Hostname: "localhost", AuthUsername: "manager", AuthHostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "manager", Hostname: "localhost", AuthUsername: "manager", AuthHostname: "localhost"}, nil, nil, nil)) tk.MustExec("SET DEFAULT ROLE ALL TO 'manager'@'localhost';") tk.MustExec("SET DEFAULT ROLE NONE TO 'manager'@'localhost';") tk.MustExec("SET DEFAULT ROLE 'r_manager' TO 'manager'@'localhost';") @@ -1047,7 +1047,7 @@ func TestShow2(t *testing.T) { createTime := model.TSConvert2Time(tblInfo.Meta().UpdateTS).Format("2006-01-02 15:04:05") // The Hostname is the actual host - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) r := tk.MustQuery("show table status from test like 't'") r.Check(testkit.Rows(fmt.Sprintf("t InnoDB 10 Compact 0 0 0 0 0 0 %s utf8mb4_bin 注释", createTime))) @@ -1081,7 +1081,7 @@ func TestShowCreateUser(t *testing.T) { err = tk.QueryToErr("show create user 'aaa'@'localhost';") require.Equal(t, exeerrors.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'aaa'@'localhost'").Error(), err.Error()) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "127.0.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, nil, nil) tk.MustQuery("show create user current_user"). Check(testkit.Rows("CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH 'mysql_native_password' AS '' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT")) @@ -1093,7 +1093,7 @@ func TestShowCreateUser(t *testing.T) { // "show create user" for other user requires the SELECT privilege on mysql database. tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use mysql") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "check_priv", Hostname: "127.0.0.1", AuthUsername: "test_show", AuthHostname: "asdf"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "check_priv", Hostname: "127.0.0.1", AuthUsername: "test_show", AuthHostname: "asdf"}, nil, nil, nil)) err = tk1.QueryToErr("show create user 'root'@'%'") require.Error(t, err) @@ -1175,14 +1175,14 @@ func TestUnprivilegedShow(t *testing.T) { tk.MustExec(`CREATE USER 'lowprivuser'`) // no grants - tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) rs, err := tk.Exec("SHOW TABLE STATUS FROM testshow") require.NoError(t, err) require.NotNil(t, rs) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("GRANT ALL ON testshow.t1 TO 'lowprivuser'") - tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) is := dom.InfoSchema() tblInfo, err := is.TableByName(model.NewCIStr("testshow"), model.NewCIStr("t1")) @@ -1216,7 +1216,7 @@ func TestShowTableStatus(t *testing.T) { tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a bigint);`) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) // It's not easy to test the result contents because every time the test runs, "Create_time" changed. tk.MustExec("show table status;") @@ -1921,7 +1921,7 @@ func TestShowDatabasesLike(t *testing.T) { tk := testkit.NewTestKit(t, store) require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "root", Hostname: "%"}, nil, nil)) + Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("DROP DATABASE IF EXISTS `TEST_$1`") tk.MustExec("DROP DATABASE IF EXISTS `test_$2`") @@ -1958,7 +1958,7 @@ func TestShowCollationsLike(t *testing.T) { tk := testkit.NewTestKit(t, store) require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ - Username: "root", Hostname: "%"}, nil, nil)) + Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustQuery("SHOW COLLATION LIKE 'UTF8MB4_BI%'").Check(testkit.Rows("utf8mb4_bin utf8mb4 46 Yes Yes 1")) tk.MustQuery("SHOW COLLATION LIKE 'utf8mb4_bi%'").Check(testkit.Rows("utf8mb4_bin utf8mb4 46 Yes Yes 1")) } diff --git a/executor/simple.go b/executor/simple.go index cbe96c93f787f..fe746c81ef00b 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -1192,7 +1192,7 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm } switch authPlugin { - case mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password, mysql.AuthSocket, mysql.AuthTiDBAuthToken: + case mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password, mysql.AuthSocket, mysql.AuthTiDBAuthToken, mysql.AuthLDAPSimple, mysql.AuthLDAPSASL: default: return exeerrors.ErrPluginIsNotLoaded.GenWithStackByArgs(spec.AuthOpt.AuthPlugin) } @@ -1623,7 +1623,7 @@ func passwordVerification(ctx context.Context, sqlExecutor sqlexec.SQLExecutor, } func checkPasswordReusePolicy(ctx context.Context, sqlExecutor sqlexec.SQLExecutor, userDetail *userInfo, sctx sessionctx.Context, authPlugin string) error { - if strings.EqualFold(authPlugin, mysql.AuthTiDBAuthToken) { + if strings.EqualFold(authPlugin, mysql.AuthTiDBAuthToken) || strings.EqualFold(authPlugin, mysql.AuthLDAPSASL) || strings.EqualFold(authPlugin, mysql.AuthLDAPSimple) { // AuthTiDBAuthToken is the token login method on the cloud, // and the Password Reuse Policy does not take effect. return nil @@ -1809,7 +1809,7 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt) spec.AuthOpt.AuthPlugin = currentAuthPlugin } switch spec.AuthOpt.AuthPlugin { - case mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password, mysql.AuthSocket, "": + case mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password, mysql.AuthSocket, mysql.AuthLDAPSimple, mysql.AuthLDAPSASL, "": authTokenOptionHandler = NoNeedAuthTokenOptions case mysql.AuthTiDBAuthToken: if authTokenOptionHandler != OptionalAuthTokenOptions { diff --git a/executor/simple_test.go b/executor/simple_test.go index 7b4d340bc6a84..b0bda248bb5ba 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -119,7 +119,7 @@ func TestUserAttributes(t *testing.T) { // Non-root users could access COMMENT or ATTRIBUTE of all users via the view, // but not via the mysql.user table. tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser1"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testuser1"}, nil, nil, nil)) tk.MustQueryWithContext(ctx, `SELECT user, host, attribute FROM information_schema.user_attributes ORDER BY user`).Check( testkit.Rows("root % ", "testuser % {\"comment\": \"1234\"}", "testuser1 % {\"age\": 20, \"name\": \"Tom\"}", "testuser2 % ")) tk.MustGetErrCode(`SELECT user, host, user_attributes FROM mysql.user ORDER BY user`, mysql.ErrTableaccessDenied) @@ -145,7 +145,7 @@ func TestSetResourceGroup(t *testing.T) { tk.MustExec("CREATE RESOURCE GROUP rg1 ru_per_sec = 100") tk.MustExec("ALTER USER `root` RESOURCE GROUP `rg1`") tk.MustQuery("SELECT CURRENT_RESOURCE_GROUP()").Check(testkit.Rows("")) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustQuery("SELECT CURRENT_RESOURCE_GROUP()").Check(testkit.Rows("rg1")) tk.MustExec("CREATE RESOURCE GROUP rg2 ru_per_sec = 200") @@ -155,6 +155,6 @@ func TestSetResourceGroup(t *testing.T) { tk.MustQuery("SELECT CURRENT_RESOURCE_GROUP()").Check(testkit.Rows("")) tk.RefreshSession() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustQuery("SELECT CURRENT_RESOURCE_GROUP()").Check(testkit.Rows("rg1")) } diff --git a/executor/simpletest/BUILD.bazel b/executor/simpletest/BUILD.bazel index 2d0d1e46c8cb0..558a526eb48d0 100644 --- a/executor/simpletest/BUILD.bazel +++ b/executor/simpletest/BUILD.bazel @@ -10,7 +10,7 @@ go_test( ], flaky = True, race = "on", - shard_count = 33, + shard_count = 35, deps = [ "//config", "//parser/auth", diff --git a/executor/simpletest/simple_test.go b/executor/simpletest/simple_test.go index e1487a2baf343..e141d50496cc7 100644 --- a/executor/simpletest/simple_test.go +++ b/executor/simpletest/simple_test.go @@ -95,7 +95,7 @@ func TestIssue9111(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "user_admin", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "user_admin", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `create user test_create_user`) @@ -147,7 +147,7 @@ func TestExtendedStatsPrivileges(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "set session tidb_enable_extended_stats = on") require.NoError(t, err) @@ -185,7 +185,7 @@ func TestIssue17247(t *testing.T) { tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "issue17247", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "issue17247", Hostname: "%"}, nil, nil, nil)) tk1.MustExec("ALTER USER USER() IDENTIFIED BY 'xxx'") tk1.MustExec("ALTER USER CURRENT_USER() IDENTIFIED BY 'yyy'") tk1.MustExec("ALTER USER CURRENT_USER IDENTIFIED BY 'zzz'") @@ -217,10 +217,10 @@ func TestSetCurrentUserPwd(t *testing.T) { tk.MustExec("DROP USER IF EXISTS issue28534;") }() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "issue28534", Hostname: "localhost", CurrentUser: true, AuthUsername: "issue28534", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "issue28534", Hostname: "localhost", CurrentUser: true, AuthUsername: "issue28534", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec(`SET PASSWORD FOR CURRENT_USER() = "43582eussi"`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) result := tk.MustQuery(`SELECT authentication_string FROM mysql.User WHERE User="issue28534"`) result.Check(testkit.Rows(auth.EncodePassword("43582eussi"))) } @@ -235,7 +235,7 @@ func TestShowGrantsAfterDropRole(t *testing.T) { tk.MustExec("GRANT r29473 TO u29473") tk.MustExec("GRANT CREATE USER ON *.* TO u29473") - tk.Session().Auth(&auth.UserIdentity{Username: "u29473", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "u29473", Hostname: "%"}, nil, nil, nil) tk.MustExec("SET ROLE r29473") tk.MustExec("DROP ROLE r29473") tk.MustQuery("SHOW GRANTS").Check(testkit.Rows("GRANT CREATE USER ON *.* TO 'u29473'@'%'")) @@ -260,7 +260,7 @@ func TestPrivilegesAfterDropUser(t *testing.T) { tk.MustQuery("SELECT COUNT(1) FROM mysql.global_priv WHERE USER='u1' AND HOST='%'").Check(testkit.Rows("1")) tk.MustQuery("SELECT COUNT(1) FROM mysql.tables_priv WHERE USER='u1' AND HOST='%'").Check(testkit.Rows("1")) tk.MustQuery("SELECT COUNT(1) FROM mysql.columns_priv WHERE USER='u1' AND HOST='%'").Check(testkit.Rows("1")) - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows( "GRANT USAGE ON *.* TO 'u1'@'%'", "GRANT CREATE ON test.* TO 'u1'@'%'", @@ -283,7 +283,7 @@ func TestDropRoleAfterRevoke(t *testing.T) { // issue 29781 tk := testkit.NewTestKit(t, store) tk.MustExec("use test;") - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil) tk.MustExec("create role r1, r2, r3;") defer tk.MustExec("drop role if exists r1, r2, r3;") @@ -375,7 +375,7 @@ func TestSetRoleAllCorner(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "set_role_all", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "set_role_all", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `set role all`) require.NoError(t, err) @@ -391,7 +391,7 @@ func TestCreateRole(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `create role test_create_role;`) @@ -416,7 +416,7 @@ func TestDropRole(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testCreateRole", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, `drop role test_create_role;`) @@ -598,7 +598,7 @@ func TestRoleAdmin(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testRoleAdmin", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testRoleAdmin", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "GRANT `targetRole` TO `testRoleAdmin`;") @@ -672,7 +672,7 @@ func TestSetDefaultRoleAll(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "test_all", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "test_all", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() _, err = se.Execute(ctx, "set default role all to test_all;") @@ -930,7 +930,7 @@ func TestFlushPrivileges(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) defer se.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testflush", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "testflush", Hostname: "localhost"}, nil, nil, nil)) ctx := context.Background() // Before flush. @@ -1105,3 +1105,32 @@ func TestDropStatsForMultipleTable(t *testing.T) { require.True(t, statsTbl2.Pseudo) h.SetLease(0) } + +func TestCreateUserWithLDAP(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("CREATE USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_simple AS 'uid=bob,ou=People,dc=example,dc=com'") + tk.MustQuery("SELECT Host, User, authentication_string, plugin FROM mysql.User WHERE User = 'bob'").Check(testkit.Rows("localhost bob uid=bob,ou=People,dc=example,dc=com authentication_ldap_simple")) + + tk.MustExec("CREATE USER 'bob2'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob2,ou=People,dc=example,dc=com'") + tk.MustQuery("SELECT Host, User, authentication_string, plugin FROM mysql.User WHERE User = 'bob2'").Check(testkit.Rows("localhost bob2 uid=bob2,ou=People,dc=example,dc=com authentication_ldap_sasl")) +} + +func TestAlterUserWithLDAP(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + // case 1: alter from a LDAP user to LDAP user + tk.MustExec("CREATE USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_simple AS 'uid=bob,ou=People,dc=example,dc=com'") + tk.MustQuery("SELECT Host, User, authentication_string, plugin FROM mysql.User WHERE User = 'bob'").Check(testkit.Rows("localhost bob uid=bob,ou=People,dc=example,dc=com authentication_ldap_simple")) + tk.MustExec("ALTER USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob,ou=Manager,dc=example,dc=com'") + tk.MustQuery("SELECT Host, User, authentication_string, plugin FROM mysql.User WHERE User = 'bob'").Check(testkit.Rows("localhost bob uid=bob,ou=Manager,dc=example,dc=com authentication_ldap_sasl")) + + // case 2: should ignore the password history + tk.MustExec("ALTER USER 'bob'@'localhost' PASSWORD HISTORY 5\n") + tk.MustExec("ALTER USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob,ou=People,dc=example,dc=com'") + tk.MustExec("ALTER USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob,ou=Manager,dc=example,dc=com'") + tk.MustExec("ALTER USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob,ou=People,dc=example,dc=com'") + tk.MustExec("ALTER USER 'bob'@'localhost' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=bob,ou=Manager,dc=example,dc=com'") +} diff --git a/executor/slow_query_sql_test.go b/executor/slow_query_sql_test.go index b7a8d3b3a957d..fb84bbb394bd8 100644 --- a/executor/slow_query_sql_test.go +++ b/executor/slow_query_sql_test.go @@ -266,7 +266,7 @@ func TestIssue37066(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) tk.MustExec("set tidb_slow_log_threshold=0;") defer func() { diff --git a/extension/function_test.go b/extension/function_test.go index 86fcd0be845c3..06fa301543525 100644 --- a/extension/function_test.go +++ b/extension/function_test.go @@ -104,7 +104,7 @@ func TestExtensionFuncCtx(t *testing.T) { tk.MustExec("grant ALL ON test.* to u1@localhost") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) tk1.MustExec("set role r1") tk1.MustExec("use test") tk1.Session().GetSessionVars().ConnectionInfo = &variable.ConnectionInfo{ @@ -344,35 +344,35 @@ func TestExtensionFuncPrivilege(t *testing.T) { tk1 := testkit.NewTestKit(t, store) // root has all privileges by default - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) tk1.MustQuery("select custom_both_dyn_priv_func()").Check(testkit.Rows("ghi")) // u1 in non-sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) require.EqualError(t, tk1.ExecToErr("select custom_only_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the SUPER or CUSTOM_DYN_PRIV_1 privilege(s) for this operation") tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) require.EqualError(t, tk1.ExecToErr("select custom_both_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the SUPER or CUSTOM_DYN_PRIV_1 privilege(s) for this operation") // u2 in non-sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) tk1.MustQuery("select custom_both_dyn_priv_func()").Check(testkit.Rows("ghi")) // u3 in non-sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u3", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u3", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) require.EqualError(t, tk1.ExecToErr("select custom_only_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the SUPER or CUSTOM_DYN_PRIV_1 privilege(s) for this operation") tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) require.EqualError(t, tk1.ExecToErr("select custom_both_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the SUPER or CUSTOM_DYN_PRIV_1 privilege(s) for this operation") // u4 in non-sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) @@ -381,35 +381,35 @@ func TestExtensionFuncPrivilege(t *testing.T) { sem.Enable() // root in sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) require.EqualError(t, tk1.ExecToErr("select custom_only_sem_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") require.EqualError(t, tk1.ExecToErr("select custom_both_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") // u1 in sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) require.EqualError(t, tk1.ExecToErr("select custom_only_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the CUSTOM_DYN_PRIV_1 privilege(s) for this operation") require.EqualError(t, tk1.ExecToErr("select custom_only_sem_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") require.EqualError(t, tk1.ExecToErr("select custom_both_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") // u2 in sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) require.EqualError(t, tk1.ExecToErr("select custom_only_sem_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") require.EqualError(t, tk1.ExecToErr("select custom_both_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the RESTRICTED_CUSTOM_DYN_PRIV_2 privilege(s) for this operation") // u3 in sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u3", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u3", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) require.EqualError(t, tk1.ExecToErr("select custom_only_dyn_priv_func()"), "[expression:1227]Access denied; you need (at least one of) the CUSTOM_DYN_PRIV_1 privilege(s) for this operation") tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) tk1.MustQuery("select custom_both_dyn_priv_func()").Check(testkit.Rows("ghi")) // u4 in sem - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil, nil)) tk1.MustQuery("select custom_no_priv_func()").Check(testkit.Rows("zzz")) tk1.MustQuery("select custom_only_dyn_priv_func()").Check(testkit.Rows("abc")) tk1.MustQuery("select custom_only_sem_dyn_priv_func()").Check(testkit.Rows("def")) diff --git a/extension/registry_test.go b/extension/registry_test.go index ba1130d815fbf..d353388c07edc 100644 --- a/extension/registry_test.go +++ b/extension/registry_test.go @@ -220,10 +220,10 @@ func TestSetVariablePrivilege(t *testing.T) { tk.MustExec("create user u2@localhost") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) sem.Disable() tk1.MustExec("set @@var1=7") @@ -297,11 +297,11 @@ func TestCustomAccessCheck(t *testing.T) { tk.MustExec("create user u2@localhost") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk1.MustExec("use test") tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("GRANT all on test.t1 TO u2@localhost") tk2.MustExec("use test") diff --git a/go.mod b/go.mod index 41cfdb536d21a..0fb3d0ec7aae5 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,8 @@ require ( github.com/fatanugraha/noloopclosure v0.1.1 github.com/fatih/color v1.15.0 github.com/fsouza/fake-gcs-server v1.44.0 - github.com/go-sql-driver/mysql v1.7.0 + github.com/go-ldap/ldap/v3 v3.4.4 + github.com/go-sql-driver/mysql v1.7.1 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.3 @@ -137,6 +138,7 @@ require ( cloud.google.com/go/iam v0.13.0 // indirect cloud.google.com/go/pubsub v1.30.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/DataDog/zstd v1.4.5 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -168,6 +170,7 @@ require ( github.com/fatih/structtag v1.2.0 // indirect github.com/felixge/httpsnoop v1.0.2 // indirect github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect + github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect github.com/go-kit/kit v0.9.0 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -280,6 +283,7 @@ require ( replace ( // fix potential security issue(CVE-2020-26160) introduced by indirect dependency. github.com/dgrijalva/jwt-go => github.com/form3tech-oss/jwt-go v3.2.6-0.20210809144907-32ab6a8243d7+incompatible + github.com/go-ldap/ldap/v3 => github.com/YangKeao/ldap/v3 v3.4.5-0.20230421065457-369a3bab1117 github.com/pingcap/tidb/parser => ./parser go.opencensus.io => go.opencensus.io v0.23.1-0.20220331163232-052120675fac ) diff --git a/go.sum b/go.sum index 7934e8c66cb89..e828745a1630f 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,8 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1/go.mod h1:KLF4gFr6DcKFZwSu github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0 h1:62Ew5xXg5UCGIXDOM7+y4IL5/6mQJq1nenhBCJAeGX8= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0/go.mod h1:eHWhQKXc1Gv1DvWH//UzgWjWFEo0Pp4pH2vBzjBw8Fc= github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -94,6 +96,8 @@ github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrU github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/YangKeao/ldap/v3 v3.4.5-0.20230421065457-369a3bab1117 h1:+OqGGFc2YHFd82aSHmjlILVt1t4JWJjrNIfV8cVEPow= +github.com/YangKeao/ldap/v3 v3.4.5-0.20230421065457-369a3bab1117/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= @@ -105,6 +109,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1581 h1:Q/yk4z/cHUVZfgTqtD09qeYBxHwshQAjVRX73qs8UH0= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1581/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -303,6 +309,8 @@ github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgoo github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= +github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -325,8 +333,8 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -1103,6 +1111,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1206,6 +1215,7 @@ golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1313,6 +1323,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1325,6 +1336,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go index 497d01ab32301..884658871a8d1 100644 --- a/infoschema/cluster_tables_test.go +++ b/infoschema/cluster_tables_test.go @@ -202,7 +202,7 @@ func SubTestDataLockWaitsPrivilege(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) err := tk.QueryToErr("select * from information_schema.DATA_LOCK_WAITS") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") @@ -213,7 +213,7 @@ func SubTestDataLockWaitsPrivilege(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser2", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) _ = tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS") } @@ -318,7 +318,7 @@ select * from t3; require.NoError(t, user1.Session().Auth(&auth.UserIdentity{ Username: "user1", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) user1.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("1")) user1.MustQuery("select count(*) from `SLOW_QUERY`").Check(testkit.Rows("1")) user1.MustQuery("select user,query from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("user1 select * from t1;")) @@ -328,7 +328,7 @@ select * from t3; require.NoError(t, user2.Session().Auth(&auth.UserIdentity{ Username: "user2", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) user2.MustQuery("select count(*) from `CLUSTER_SLOW_QUERY`").Check(testkit.Rows("2")) user2.MustQuery("select user,query from `CLUSTER_SLOW_QUERY` order by query").Check(testkit.Rows("user2 select * from t2;", "user2 select * from t3;")) } @@ -382,7 +382,7 @@ func TestStmtSummaryEvictedCountTable(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) err := tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED") // This error is come from cop(TiDB) fetch from rpc server. @@ -391,7 +391,7 @@ func TestStmtSummaryEvictedCountTable(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser2", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) require.NoError(t, tk.QueryToErr("select * from information_schema.CLUSTER_STATEMENTS_SUMMARY_EVICTED")) } @@ -418,7 +418,7 @@ func TestStmtSummaryIssue35340(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: user, Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) tk.MustQuery("select count(*) from information_schema.statements_summary;") } }() @@ -815,7 +815,7 @@ func (s *clusterTablesSuite) setUpMockPDHTTPServer() (*httptest.Server, string) func (s *clusterTablesSuite) newTestKitWithRoot(t *testing.T) *testkit.TestKit { tk := testkit.NewTestKit(t, s.store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk } @@ -887,7 +887,7 @@ func TestCreateBindingFromHistory(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -953,7 +953,7 @@ func TestCreateBindingForPrepareFromHistory(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -982,7 +982,7 @@ func TestErrorCasesCreateBindingFromHistory(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t1, t2, t3") @@ -1056,7 +1056,7 @@ func TestSetBindingStatusBySQLDigest(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(id int, a int, key(a))") @@ -1089,7 +1089,7 @@ func TestCreateBindingWhenCloseStmtSummaryTable(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1110,7 +1110,7 @@ func TestCreateBindingForNotSupportedStmt(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1141,7 +1141,7 @@ func TestCreateBindingRepeatedly(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") @@ -1213,7 +1213,7 @@ func TestCreateBindingWithUsingKeyword(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t, t1, t2") @@ -1251,7 +1251,7 @@ func TestNewCreatedBindingCanWorkWithPlanCache(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t, t1, t2") @@ -1279,7 +1279,7 @@ func TestCreateBindingForPrepareToken(t *testing.T) { defer s.httpServer.Close() defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index ab4ee9f9827fe..c3db6adeaad51 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -50,7 +50,7 @@ import ( func newTestKitWithRoot(t *testing.T, store kv.Storage) *testkit.TestKit { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk } @@ -60,7 +60,7 @@ func newTestKitWithPlanCache(t *testing.T, store kv.Storage) *testkit.TestKit { require.NoError(t, err) tk.SetSession(se) tk.RefreshConnectionID() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk } @@ -126,7 +126,7 @@ func TestInfoSchemaFieldValue(t *testing.T) { require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{ Username: "xxx", Hostname: "127.0.0.1", - }, nil, nil)) + }, nil, nil, nil)) tk1.MustQuery("select distinct(table_schema) from information_schema.tables").Check(testkit.Rows("INFORMATION_SCHEMA")) @@ -1083,7 +1083,7 @@ func TestStmtSummaryTablePrivilege(t *testing.T) { Hostname: "localhost", AuthUsername: "test_user", AuthHostname: "localhost", - }, nil, nil) + }, nil, nil, nil) result = tk1.MustQuery("select * from information_schema.statements_summary where digest_text like 'select * from `t`%'") // Ordinary users can not see others' records @@ -1143,7 +1143,7 @@ func TestCapturePrivilege(t *testing.T) { Hostname: "localhost", AuthUsername: "test_user", AuthHostname: "localhost", - }, nil, nil) + }, nil, nil, nil) rows = tk1.MustQuery("show global bindings").Rows() // Ordinary users can not see others' records @@ -1170,7 +1170,7 @@ func TestIssue18845(t *testing.T) { Hostname: "localhost", AuthUsername: "user18845", AuthHostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery(`select count(*) from information_schema.columns;`) } @@ -1534,7 +1534,7 @@ func TestInfoSchemaClientErrors(t *testing.T) { errno.IncrementError(1365, "root", "localhost") tk.MustExec("CREATE USER 'infoschematest'@'localhost'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "infoschematest", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "infoschematest", Hostname: "localhost"}, nil, nil, nil)) err := tk.QueryToErr("SELECT * FROM information_schema.client_errors_summary_global") require.Equal(t, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation", err.Error()) @@ -1638,7 +1638,7 @@ func TestInfoSchemaDeadlockPrivilege(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) err := tk.QueryToErr("select * from information_schema.deadlocks") require.Error(t, err) require.Equal(t, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation", err.Error()) @@ -1649,7 +1649,7 @@ func TestInfoSchemaDeadlockPrivilege(t *testing.T) { require.NoError(t, tk.Session().Auth(&auth.UserIdentity{ Username: "testuser2", Hostname: "localhost", - }, nil, nil)) + }, nil, nil, nil)) _ = tk.MustQuery("select * from information_schema.deadlocks") } @@ -1835,7 +1835,7 @@ func TestAddFieldsForBinding(t *testing.T) { defer s.rpcserver.Stop() tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int, key(a))") diff --git a/parser/ast/misc.go b/parser/ast/misc.go index b26ef9e70ae28..5b075f8ca1ef1 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -1397,6 +1397,16 @@ func (n *UserSpec) EncodedPassword() (string, bool) { } } + // store the LDAP dn directly in the password field + switch opt.AuthPlugin { + case mysql.AuthLDAPSimple, mysql.AuthLDAPSASL: + // TODO: validate the HashString to be a `dn` for LDAP + // It seems fine to not validate here, and LDAP server will give an error when the client'll try to login this user. + // The percona server implementation doesn't have a validation for this HashString. + // However, returning an error for obvious wrong format is more friendly. + return opt.HashString, true + } + // In case we have 'IDENTIFIED WITH ' but no 'BY ' to set an empty password. if opt.HashString == "" { return opt.HashString, true diff --git a/parser/mysql/const.go b/parser/mysql/const.go index f836cc05e4286..a2abd640c5d20 100644 --- a/parser/mysql/const.go +++ b/parser/mysql/const.go @@ -183,6 +183,8 @@ const ( AuthSocket = "auth_socket" AuthTiDBSessionToken = "tidb_session_token" AuthTiDBAuthToken = "tidb_auth_token" + AuthLDAPSimple = "authentication_ldap_simple" + AuthLDAPSASL = "authentication_ldap_sasl" ) // MySQL database and tables. diff --git a/planner/core/binary_plan_test.go b/planner/core/binary_plan_test.go index e530e20bf8262..65548581451fb 100644 --- a/planner/core/binary_plan_test.go +++ b/planner/core/binary_plan_test.go @@ -49,7 +49,7 @@ func TestBinaryPlanSwitch(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) origin := tk.MustQuery("SELECT @@global.tidb_generate_binary_plan") @@ -124,7 +124,7 @@ func TestTooLongBinaryPlan(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) origin := tk.MustQuery("SELECT @@global.tidb_enable_stmt_summary") @@ -194,7 +194,7 @@ func TestLongBinaryPlan(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) @@ -248,7 +248,7 @@ func TestBinaryPlanOfPreparedStmt(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) tk.MustExec("use test") @@ -409,7 +409,7 @@ func TestUnnecessaryBinaryPlanInSlowLog(t *testing.T) { require.NoError(t, logutil.InitLogger(newCfg.Log.ToLogConfig())) store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec(fmt.Sprintf("set @@tidb_slow_query_file='%v'", f.Name())) origin := tk.MustQuery("SELECT @@global.tidb_slow_log_threshold") diff --git a/planner/core/integration_partition_test.go b/planner/core/integration_partition_test.go index 5fd57cc33ff14..becfcd39f729c 100644 --- a/planner/core/integration_partition_test.go +++ b/planner/core/integration_partition_test.go @@ -415,7 +415,7 @@ func TestListPartitionPrivilege(t *testing.T) { se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.SetSession(se) tk.MustExec("create database list_partition_pri") tk.MustExec("use list_partition_pri") @@ -429,7 +429,7 @@ func TestListPartitionPrivilege(t *testing.T) { tk1 := testkit.NewTestKit(t, store) se, err = session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "priv_test", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "priv_test", Hostname: "%"}, nil, nil, nil)) tk1.SetSession(se) tk1.MustExec(`use list_partition_pri`) err = tk1.ExecToErr(`alter table tlist truncate partition p0`) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 577b72ca81faa..89331a04e9fff 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -2568,7 +2568,7 @@ func TestCreateViewIsolationRead(t *testing.T) { store := testkit.CreateMockStore(t) se, err := session.CreateSession4Test(store) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk := testkit.NewTestKit(t, store) tk.SetSession(se) @@ -3047,7 +3047,7 @@ func TestSelectIgnoreTemporaryTableInView(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tk.MustExec("create table t1 (a int, b int)") tk.MustExec("create table t2 (c int, d int)") tk.MustExec("create view v1 as select * from t1 order by a") @@ -4254,7 +4254,7 @@ func TestLeftShiftPushDownToTiFlash(t *testing.T) { func TestIssue36609(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t1(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))") tk.MustExec("create table t2(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))") @@ -5268,7 +5268,7 @@ func TestVirtualExprPushDown(t *testing.T) { func TestIssue41458(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec(`create table t (a int, b int, c int, index ia(a));`) tk.MustExec("select * from t t1 join t t2 on t1.b = t2.b join t t3 on t2.b=t3.b join t t4 on t3.b=t4.b where t3.a=1 and t2.a=2;") diff --git a/planner/core/prepare_test.go b/planner/core/prepare_test.go index 583b6a5150334..c4d31a6aaceff 100644 --- a/planner/core/prepare_test.go +++ b/planner/core/prepare_test.go @@ -435,7 +435,7 @@ func TestPrepareCache(t *testing.T) { // user u_tp userSess := newSession(t, store, "test") - require.NoError(t, userSess.Auth(&auth.UserIdentity{Username: "u_tp", Hostname: "localhost"}, nil, nil)) + require.NoError(t, userSess.Auth(&auth.UserIdentity{Username: "u_tp", Hostname: "localhost"}, nil, nil, nil)) mustExec(t, userSess, `prepare ps_stp_r from 'select * from tp where c1 > ?'`) mustExec(t, userSess, `set @p2 = 2`) tk.SetSession(userSess) @@ -1811,7 +1811,7 @@ func TestIssue18066(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec(`set tidb_enable_prepared_plan_cache=1`) tk.RefreshConnectionID() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") diff --git a/privilege/BUILD.bazel b/privilege/BUILD.bazel index d85b91614612e..23e0682a08622 100644 --- a/privilege/BUILD.bazel +++ b/privilege/BUILD.bazel @@ -8,6 +8,7 @@ go_library( deps = [ "//parser/auth", "//parser/mysql", + "//privilege/conn", "//sessionctx", "//sessionctx/variable", "//types", diff --git a/privilege/conn/BUILD.bazel b/privilege/conn/BUILD.bazel new file mode 100644 index 0000000000000..109898cb68c12 --- /dev/null +++ b/privilege/conn/BUILD.bazel @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "conn", + srcs = ["conn.go"], + importpath = "github.com/pingcap/tidb/privilege/conn", + visibility = ["//visibility:public"], +) diff --git a/privilege/conn/conn.go b/privilege/conn/conn.go new file mode 100644 index 0000000000000..0011c368c03ca --- /dev/null +++ b/privilege/conn/conn.go @@ -0,0 +1,30 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package conn + +import "context" + +// AuthConn is an interface to help auth plugin to communicate with the client. +type AuthConn interface { + // WriteAuthMoreData should write a (u8)1 before data. + // also see `client_mpvio_read_packet` in the MySQL client. It'll ignore the first byte if it's 1. + WriteAuthMoreData(data []byte) error + // ReadPacket reads one more packet. + // also see `client_mpvio_write_packet` in the MySQL client. It's just a normal packet without any prefixing. + // NOTE: the first packet returned by the client is appended in the `Protocol::AuthSwitchResponse`, also see `client_mpvio_write_packet`. + ReadPacket() ([]byte, error) + // Flush flushes all packets in the connection and sends them to the client + Flush(ctx context.Context) error +} diff --git a/privilege/privilege.go b/privilege/privilege.go index 3229c1e3bb26f..609e48062ba12 100644 --- a/privilege/privilege.go +++ b/privilege/privilege.go @@ -17,6 +17,7 @@ package privilege import ( "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/privilege/conn" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" @@ -75,7 +76,7 @@ type Manager interface { // ConnectionVerification verifies user privilege for connection. // Requires exact match on user name and host name. - ConnectionVerification(user *auth.UserIdentity, authUser, authHost string, auth, salt []byte, sessionVars *variable.SessionVars) (VerificationInfo, error) + ConnectionVerification(user *auth.UserIdentity, authUser, authHost string, auth, salt []byte, sessionVars *variable.SessionVars, authConn conn.AuthConn) (VerificationInfo, error) // AuthSuccess records auth success state AuthSuccess(authUser, authHost string) diff --git a/privilege/privileges/BUILD.bazel b/privilege/privileges/BUILD.bazel index e5ac940f97fd6..e070d3f567b9c 100644 --- a/privilege/privileges/BUILD.bazel +++ b/privilege/privileges/BUILD.bazel @@ -20,6 +20,8 @@ go_library( "//parser/mysql", "//parser/terror", "//privilege", + "//privilege/conn", + "//privilege/privileges/ldap", "//sessionctx", "//sessionctx/sessionstates", "//sessionctx/variable", diff --git a/privilege/privileges/ldap/BUILD.bazel b/privilege/privileges/ldap/BUILD.bazel new file mode 100644 index 0000000000000..a807291caf073 --- /dev/null +++ b/privilege/privileges/ldap/BUILD.bazel @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ldap", + srcs = [ + "const.go", + "ldap_common.go", + "sasl.go", + "simple.go", + ], + importpath = "github.com/pingcap/tidb/privilege/privileges/ldap", + visibility = ["//visibility:public"], + deps = [ + "//privilege/conn", + "@com_github_go_ldap_ldap_v3//:ldap", + "@com_github_ngaut_pools//:pools", + "@com_github_pingcap_errors//:errors", + ], +) + +go_test( + name = "ldap_test", + timeout = "short", + srcs = ["ldap_common_test.go"], + embed = [":ldap"], + flaky = True, + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/privilege/privileges/ldap/const.go b/privilege/privileges/ldap/const.go new file mode 100644 index 0000000000000..5179fd49c07ff --- /dev/null +++ b/privilege/privileges/ldap/const.go @@ -0,0 +1,24 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ldap + +// SASLAuthMethodSCRAMSHA1 represents the authentication mechanism with SCRAM-SHA-1 +const SASLAuthMethodSCRAMSHA1 = "SCRAM-SHA-1" + +// SASLAuthMethodSCRAMSHA256 represents the authentication mechanism with SCRAM-SHA-256 +const SASLAuthMethodSCRAMSHA256 = "SCRAM-SHA-256" + +// SASLAuthMethodGSSAPI represents the authentication mechanism with GSSAPI +const SASLAuthMethodGSSAPI = "GSSAPI" diff --git a/privilege/privileges/ldap/ldap_common.go b/privilege/privileges/ldap/ldap_common.go new file mode 100644 index 0000000000000..36e06e2d5ac68 --- /dev/null +++ b/privilege/privileges/ldap/ldap_common.go @@ -0,0 +1,374 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ldap + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "os" + "sync" + + "github.com/go-ldap/ldap/v3" + "github.com/ngaut/pools" + "github.com/pingcap/errors" +) + +// ldapAuthImpl gives the internal utilities of authentication with LDAP. +// The getter and setter methods will lock the mutex inside, while all other methods don't, so all other method call +// should be protected by `impl.Lock()`. +type ldapAuthImpl struct { + sync.RWMutex + // the following attributes are used to search the users + bindBaseDN string + bindRootDN string + bindRootPW string + searchAttr string + + // the following attributes are used to connect to LDAP server + ldapServerHost string + ldapServerPort int + enableTLS bool + caPath string + initCapacity int + maxCapacity int + + caPool *x509.CertPool + + ldapConnectionPool *pools.ResourcePool +} + +func (impl *ldapAuthImpl) searchUser(userName string) (dn string, err error) { + var l *ldap.Conn + + l, err = impl.getConnection() + if err != nil { + return "", err + } + defer impl.putConnection(l) + + err = l.Bind(impl.bindRootDN, impl.bindRootPW) + if err != nil { + return "", errors.Wrap(err, "bind root dn to search user") + } + defer func() { + // bind to anonymous user + _, err = l.SimpleBind(&ldap.SimpleBindRequest{ + AllowEmptyPassword: true, + }) + }() + + result, err := l.Search(&ldap.SearchRequest{ + BaseDN: impl.bindBaseDN, + Scope: ldap.ScopeWholeSubtree, + Filter: fmt.Sprintf("(%s=%s)", impl.searchAttr, userName), + }) + if err != nil { + return + } + + if len(result.Entries) == 0 { + return "", errors.New("LDAP user not found") + } + + dn = result.Entries[0].DN + return +} + +// canonicalizeDN turns the `dn` provided in database to the `dn` recognized by LDAP server +// If the first byte of `dn` is `+`, it'll be converted into "${searchAttr}=${username},..." +// both `userName` and `dn` should be non-empty +func (impl *ldapAuthImpl) canonicalizeDN(userName string, dn string) string { + if dn[0] == '+' { + return fmt.Sprintf("%s=%s,%s", impl.searchAttr, userName, dn[1:]) + } + + return dn +} + +func (impl *ldapAuthImpl) initializeCAPool() error { + if impl.caPath == "" { + impl.caPool = nil + return nil + } + + impl.caPool = x509.NewCertPool() + caCert, err := os.ReadFile(impl.caPath) + if err != nil { + return errors.Wrapf(err, "read ca certificate at %s", caCert) + } + + ok := impl.caPool.AppendCertsFromPEM(caCert) + if !ok { + return errors.New("fail to parse ca certificate") + } + + return nil +} + +func (impl *ldapAuthImpl) connectionFactory() (pools.Resource, error) { + address := fmt.Sprintf("%s:%d", impl.ldapServerHost, impl.ldapServerPort) + + // It's fine to load these two TLS configurations one-by-one (but not guarded by a single lock), because there isn't + // a way to set two variables atomically. + if impl.enableTLS { + ldapConnection, err := ldap.Dial("tcp", address) + if err != nil { + return nil, errors.Wrap(err, "create ldap connection") + } + + err = ldapConnection.StartTLS(&tls.Config{ + RootCAs: impl.caPool, + ServerName: impl.ldapServerHost, + }) + if err != nil { + return nil, errors.Wrap(err, "start tls on ldap connection") + } + return ldapConnection, nil + } + ldapConnection, err := ldap.Dial("tcp", address) + if err != nil { + return nil, errors.Wrap(err, "create ldap connection") + } + + return ldapConnection, nil +} + +const getConnectionMaxRetry = 10 + +func (impl *ldapAuthImpl) getConnection() (*ldap.Conn, error) { + retryCount := 0 + for { + conn, err := impl.ldapConnectionPool.Get() + if err != nil { + return nil, err + } + + // try to bind anonymous user. It has two meanings: + // 1. Clear the state of previous binding, to avoid security leaks. (Though it's not serious, because even the current + // connection has binded to other users, the following authentication will still fail. But the ACL for anonymous + // user and a valid user could be different, so it's better to bind back to anonymous user here. + // 2. Detect whether this connection is still valid to use, in case the server has closed this connection. + ldapConnection := conn.(*ldap.Conn) + _, err = ldapConnection.SimpleBind(&ldap.SimpleBindRequest{ + AllowEmptyPassword: true, + }) + if err != nil { + // fail to bind to anonymous user, just release this connection and try to get a new one + impl.ldapConnectionPool.Put(nil) + + retryCount++ + if retryCount >= getConnectionMaxRetry { + return nil, errors.Wrap(err, "fail to bind to anonymous user") + } + continue + } + + return conn.(*ldap.Conn), nil + } +} + +func (impl *ldapAuthImpl) putConnection(conn *ldap.Conn) { + impl.ldapConnectionPool.Put(conn) +} + +func (impl *ldapAuthImpl) initializePool() { + if impl.ldapConnectionPool != nil { + impl.ldapConnectionPool.Close() + } + + // skip initialization when the variables are not correct + if impl.initCapacity > 0 && impl.maxCapacity >= impl.initCapacity { + impl.ldapConnectionPool = pools.NewResourcePool(impl.connectionFactory, impl.initCapacity, impl.maxCapacity, 0) + } +} + +// SetBindBaseDN updates the BaseDN used to search the user +func (impl *ldapAuthImpl) SetBindBaseDN(bindBaseDN string) { + impl.Lock() + defer impl.Unlock() + + impl.bindBaseDN = bindBaseDN +} + +// SetBindRootDN updates the RootDN. Before searching the users, the connection will bind +// this root user. +func (impl *ldapAuthImpl) SetBindRootDN(bindRootDN string) { + impl.Lock() + defer impl.Unlock() + + impl.bindRootDN = bindRootDN +} + +// SetBindRootPW updates the password of the user specified by `rootDN`. +func (impl *ldapAuthImpl) SetBindRootPW(bindRootPW string) { + impl.Lock() + defer impl.Unlock() + + impl.bindRootPW = bindRootPW +} + +// SetSearchAttr updates the search attributes. +func (impl *ldapAuthImpl) SetSearchAttr(searchAttr string) { + impl.Lock() + defer impl.Unlock() + + impl.searchAttr = searchAttr +} + +// SetLDAPServerHost updates the host of LDAP server +func (impl *ldapAuthImpl) SetLDAPServerHost(ldapServerHost string) { + impl.Lock() + defer impl.Unlock() + + if ldapServerHost != impl.ldapServerHost { + impl.ldapServerHost = ldapServerHost + } +} + +// SetLDAPServerPort updates the port of LDAP server +func (impl *ldapAuthImpl) SetLDAPServerPort(ldapServerPort int) { + impl.Lock() + defer impl.Unlock() + + if ldapServerPort != impl.ldapServerPort { + impl.ldapServerPort = ldapServerPort + } +} + +// SetEnableTLS sets whether to enable StartTLS for LDAP connection +func (impl *ldapAuthImpl) SetEnableTLS(enableTLS bool) { + impl.Lock() + defer impl.Unlock() + + if enableTLS != impl.enableTLS { + impl.enableTLS = enableTLS + } +} + +// SetCAPath sets the path of CA certificate used to connect to LDAP server +func (impl *ldapAuthImpl) SetCAPath(path string) error { + impl.Lock() + defer impl.Unlock() + + if path != impl.caPath { + impl.caPath = path + err := impl.initializeCAPool() + if err != nil { + return err + } + } + + return nil +} + +func (impl *ldapAuthImpl) SetInitCapacity(initCapacity int) { + impl.Lock() + defer impl.Unlock() + + if initCapacity != impl.initCapacity { + impl.initCapacity = initCapacity + impl.initializePool() + } +} + +func (impl *ldapAuthImpl) SetMaxCapacity(maxCapacity int) { + impl.Lock() + defer impl.Unlock() + + if maxCapacity != impl.maxCapacity { + impl.maxCapacity = maxCapacity + impl.initializePool() + } +} + +// GetBindBaseDN returns the BaseDN used to search the user +func (impl *ldapAuthImpl) GetBindBaseDN() string { + impl.RLock() + defer impl.RUnlock() + + return impl.bindBaseDN +} + +// GetBindRootDN returns the RootDN. Before searching the users, the connection will bind +// this root user. +func (impl *ldapAuthImpl) GetBindRootDN() string { + impl.RLock() + defer impl.RUnlock() + + return impl.bindRootDN +} + +// GetBindRootPW returns the password of the user specified by `rootDN`. +func (impl *ldapAuthImpl) GetBindRootPW() string { + impl.RLock() + defer impl.RUnlock() + + return impl.bindRootPW +} + +// GetSearchAttr returns the search attributes. +func (impl *ldapAuthImpl) GetSearchAttr() string { + impl.RLock() + defer impl.RUnlock() + + return impl.searchAttr +} + +// GetLDAPServerHost returns the host of LDAP server +func (impl *ldapAuthImpl) GetLDAPServerHost() string { + impl.RLock() + defer impl.RUnlock() + + return impl.ldapServerHost +} + +// GetLDAPServerPort returns the port of LDAP server +func (impl *ldapAuthImpl) GetLDAPServerPort() int { + impl.RLock() + defer impl.RUnlock() + + return impl.ldapServerPort +} + +// GetEnableTLS sets whether to enable StartTLS for LDAP connection +func (impl *ldapAuthImpl) GetEnableTLS() bool { + impl.RLock() + defer impl.RUnlock() + + return impl.enableTLS +} + +// GetCAPath returns the path of CA certificate used to connect to LDAP server +func (impl *ldapAuthImpl) GetCAPath() string { + impl.RLock() + defer impl.RUnlock() + + return impl.caPath +} + +func (impl *ldapAuthImpl) GetInitCapacity() int { + impl.RLock() + defer impl.RUnlock() + + return impl.initCapacity +} + +func (impl *ldapAuthImpl) GetMaxCapacity() int { + impl.RLock() + defer impl.RUnlock() + + return impl.maxCapacity +} diff --git a/privilege/privileges/ldap/ldap_common_test.go b/privilege/privileges/ldap/ldap_common_test.go new file mode 100644 index 0000000000000..6229e9010aaa5 --- /dev/null +++ b/privilege/privileges/ldap/ldap_common_test.go @@ -0,0 +1,29 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ldap + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCanonicalizeDN(t *testing.T) { + impl := &ldapAuthImpl{ + searchAttr: "cn", + } + require.Equal(t, impl.canonicalizeDN("yka", "cn=y,dc=ping,dc=cap"), "cn=y,dc=ping,dc=cap") + require.Equal(t, impl.canonicalizeDN("yka", "+dc=ping,dc=cap"), "cn=yka,dc=ping,dc=cap") +} diff --git a/privilege/privileges/ldap/sasl.go b/privilege/privileges/ldap/sasl.go new file mode 100644 index 0000000000000..f3b81a68be25c --- /dev/null +++ b/privilege/privileges/ldap/sasl.go @@ -0,0 +1,119 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ldap + +import ( + "context" + + "github.com/go-ldap/ldap/v3" + "github.com/pingcap/errors" + "github.com/pingcap/tidb/privilege/conn" +) + +type ldapSASLAuthImpl struct { + *ldapAuthImpl + + saslAuthMethod string +} + +// AuthLDAPSASL authenticates the user through LDAP SASL +func (impl *ldapSASLAuthImpl) AuthLDAPSASL(userName string, dn string, clientCred []byte, authConn conn.AuthConn) error { + dn, ldapConn, err := func() (string, *ldap.Conn, error) { + // It's fine to just `RLock` here, even we're fetching resources from the pool, because the resource pool can be + // accessed concurrently. The `RLock` here is to protect the configurations. + // + // It's a bad idea to lock through the whole function, as this function will write/read to interact with the client. + // If the client somehow died and don't send responds, this function will not end for a long time (until connection + // timeout) and this lock will not be released. Therefore, we only `RLock` the configurations in the + impl.RLock() + defer impl.RUnlock() + + var err error + if len(dn) == 0 { + dn, err = impl.searchUser(userName) + if err != nil { + return "", nil, err + } + } else { + dn = impl.canonicalizeDN(userName, dn) + } + + ldapConn, err := impl.getConnection() + if err != nil { + return "", nil, errors.Wrap(err, "create LDAP connection") + } + + return dn, ldapConn, nil + }() + if err != nil { + return err + } + + defer impl.putConnection(ldapConn) + for { + resultCode, serverCred, err := ldapConn.ServerBindStep(clientCred, dn, impl.saslAuthMethod, nil) + if err != nil { + return err + } + + // The client is still waiting for the last serverCred, so cannot break the loop right now even if the `resultCode` + // is 0 + err = authConn.WriteAuthMoreData(serverCred) + if err != nil { + return err + } + + // In TiDB, all `context.Context` before `dispatch` is all `context.Background()` with some KV used for log, so + // it's just fine to use `context.Background()` here. + err = authConn.Flush(context.Background()) + if err != nil { + return err + } + + // `resultCode == 0` means the result is `LDAP_SUCCESS`, the authentication succeeds and we could go further now. + if resultCode == 0 { + break + } + + clientCred, err = authConn.ReadPacket() + if err != nil { + return err + } + } + + return nil +} + +// SetSASLAuthMethod sets the authentication method used by SASL +func (impl *ldapSASLAuthImpl) SetSASLAuthMethod(saslAuthMethod string) { + impl.Lock() + defer impl.Unlock() + + impl.saslAuthMethod = saslAuthMethod +} + +// GetSASLAuthMethod returns the authentication method used by SASL +func (impl *ldapSASLAuthImpl) GetSASLAuthMethod() string { + impl.Lock() + defer impl.Unlock() + + return impl.saslAuthMethod +} + +// LDAPSASLAuthImpl is the implementation of authentication with LDAP SASL +var LDAPSASLAuthImpl = &ldapSASLAuthImpl{ + &ldapAuthImpl{}, + "", +} diff --git a/privilege/privileges/ldap/simple.go b/privilege/privileges/ldap/simple.go new file mode 100644 index 0000000000000..07934699832a4 --- /dev/null +++ b/privilege/privileges/ldap/simple.go @@ -0,0 +1,65 @@ +// Copyright 2023-2023 PingCAP Xingchen (Beijing) Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ldap + +import ( + "github.com/pingcap/errors" +) + +type ldapSimplAuthImpl struct { + *ldapAuthImpl +} + +// AuthLDAPSimple authenticates the user through LDAP Simple Bind +// password is expected to be a nul-terminated string +func (impl *ldapSimplAuthImpl) AuthLDAPSimple(userName string, dn string, password []byte) error { + impl.RLock() + defer impl.RUnlock() + + if len(password) == 0 { + return errors.New("invalid password") + } + if password[len(password)-1] != 0 { + return errors.New("invalid password") + } + passwordStr := string(password[:len(password)-1]) + + var err error + if len(dn) == 0 { + dn, err = impl.searchUser(userName) + if err != nil { + return err + } + } else { + dn = impl.canonicalizeDN(userName, dn) + } + + ldapConn, err := impl.getConnection() + if err != nil { + return errors.Wrap(err, "create LDAP connection") + } + defer impl.putConnection(ldapConn) + err = ldapConn.Bind(dn, passwordStr) + if err != nil { + return errors.Wrap(err, "bind LDAP") + } + + return nil +} + +// LDAPSimpleAuthImpl is the implementation of authentication with LDAP clear text password +var LDAPSimpleAuthImpl = &ldapSimplAuthImpl{ + &ldapAuthImpl{}, +} diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 236fd20968655..ea056bb041223 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -32,6 +32,8 @@ import ( "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/privilege" + "github.com/pingcap/tidb/privilege/conn" + "github.com/pingcap/tidb/privilege/privileges/ldap" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/sessionstates" "github.com/pingcap/tidb/sessionctx/variable" @@ -236,6 +238,8 @@ func (p *UserPrivileges) isValidHash(record *UserRecord) bool { return true case mysql.AuthTiDBAuthToken: return true + case mysql.AuthLDAPSimple, mysql.AuthLDAPSASL: + return true } logutil.BgLogger().Error("user password from the mysql.user table not like a known hash format", zap.String("user", record.User), zap.String("plugin", record.AuthPlugin), zap.Int("hash_length", len(pwd))) @@ -268,9 +272,11 @@ func (p *UserPrivileges) GetAuthPluginForConnection(user, host string) (string, if record == nil { return "", errors.New("Failed to get user record") } - if record.AuthPlugin == mysql.AuthTiDBAuthToken { + switch record.AuthPlugin { + case mysql.AuthTiDBAuthToken, mysql.AuthLDAPSASL, mysql.AuthLDAPSimple: return record.AuthPlugin, nil } + // zero-length auth string means no password for native and caching_sha2 auth. // but for auth_socket it means there should be a 1-to-1 mapping between the TiDB user // and the OS user. @@ -505,7 +511,7 @@ func BuildPasswordLockingJSON(failedLoginAttempts int64, } // ConnectionVerification implements the Manager interface. -func (p *UserPrivileges) ConnectionVerification(user *auth.UserIdentity, authUser, authHost string, authentication, salt []byte, sessionVars *variable.SessionVars) (info privilege.VerificationInfo, err error) { +func (p *UserPrivileges) ConnectionVerification(user *auth.UserIdentity, authUser, authHost string, authentication, salt []byte, sessionVars *variable.SessionVars, authConn conn.AuthConn) (info privilege.VerificationInfo, err error) { if SkipWithGrant { p.user = authUser p.host = authHost @@ -565,6 +571,18 @@ func (p *UserPrivileges) ConnectionVerification(user *auth.UserIdentity, authUse logutil.BgLogger().Error("check claims failed", zap.Error(err)) return info, ErrAccessDenied.FastGenByArgs(user.Username, user.Hostname, hasPassword) } + } else if record.AuthPlugin == mysql.AuthLDAPSASL { + if err = ldap.LDAPSASLAuthImpl.AuthLDAPSASL(authUser, pwd, authentication, authConn); err != nil { + // though the pwd stores only `dn` for LDAP SASL, it could be unsafe to print it out. + // for example, someone may alter the auth plugin name but forgot to change the password... + logutil.BgLogger().Warn("verify through LDAP SASL failed", zap.String("username", user.Username), zap.Error(err)) + return info, ErrAccessDenied.FastGenByArgs(user.Username, user.Hostname, hasPassword) + } + } else if record.AuthPlugin == mysql.AuthLDAPSimple { + if err = ldap.LDAPSimpleAuthImpl.AuthLDAPSimple(authUser, pwd, authentication); err != nil { + logutil.BgLogger().Warn("verify through LDAP Simple failed", zap.String("username", user.Username), zap.Error(err)) + return info, ErrAccessDenied.FastGenByArgs(user.Username, user.Hostname, hasPassword) + } } else if len(pwd) > 0 && len(authentication) > 0 { switch record.AuthPlugin { // NOTE: If the checking of the clear-text password fails, please set `info.FailedDueToWrongPassword = true`. diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 7974b951396f0..fc2802cfa656e 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -59,7 +59,7 @@ func TestCheckDBPrivilege(t *testing.T) { tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testcheck", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testcheck", Hostname: "localhost"}, nil, nil, nil)) pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) @@ -73,7 +73,7 @@ func TestCheckDBPrivilege(t *testing.T) { activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "testcheck", Hostname: "localhost"}) rootTk.MustExec(`GRANT 'testcheck'@'localhost' TO 'testcheck_tmp'@'localhost';`) tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "testcheck_tmp", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "testcheck_tmp", Hostname: "localhost"}, nil, nil, nil)) pc = privilege.GetPrivilegeManager(tk2.Session()) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.SelectPriv)) require.True(t, pc.RequestVerification(activeRoles, "test", "", "", mysql.UpdatePriv)) @@ -89,7 +89,7 @@ func TestCheckPointGetDBPrivilege(t *testing.T) { rootTk.MustExec(`insert into test2.t(id, v) values(1, 1)`) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`use test;`) err := tk.ExecToErr(`select * from test2.t where id = 1`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) @@ -111,7 +111,7 @@ func TestCheckExchangePartitionDBPrivilege(t *testing.T) { rootTk.MustExec(`create table nt (a varchar(3));`) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tester", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("use test") rootTk.MustExec(`GRANT CREATE ON test.* TO 'tester'@'localhost';`) @@ -144,7 +144,7 @@ func TestIssue22946(t *testing.T) { rootTk.MustExec("grant select on test.* to delTest@'localhost';") tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "delTest", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "delTest", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`delete from db1.a as A where exists(select 1 from db2.b as B where A.id = B.id);`) rootTk.MustExec("use db1;") err := tk.ExecToErr("delete from test.a as A;") @@ -160,7 +160,7 @@ func TestCheckTablePrivilege(t *testing.T) { tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test1", Hostname: "localhost"}, nil, nil, nil)) pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "test", "", mysql.SelectPriv)) @@ -175,7 +175,7 @@ func TestCheckTablePrivilege(t *testing.T) { activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "test1", Hostname: "localhost"}) tk2 := testkit.NewTestKit(t, store) rootTk.MustExec(`GRANT 'test1'@'localhost' TO 'test1_tmp'@'localhost';`) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "test1_tmp", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "test1_tmp", Hostname: "localhost"}, nil, nil, nil)) pc2 := privilege.GetPrivilegeManager(tk2.Session()) require.True(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.SelectPriv)) require.True(t, pc2.RequestVerification(activeRoles, "test", "test", "", mysql.UpdatePriv)) @@ -195,7 +195,7 @@ func TestCheckViewPrivilege(t *testing.T) { tk := testkit.NewTestKit(t, store) activeRoles := make([]*auth.RoleIdentity, 0) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "vuser", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "vuser", Hostname: "localhost"}, nil, nil, nil)) pc := privilege.GetPrivilegeManager(tk.Session()) require.False(t, pc.RequestVerification(activeRoles, "test", "v", "", mysql.SelectPriv)) @@ -216,7 +216,7 @@ func TestCheckPrivilegeWithRoles(t *testing.T) { rootTk.MustExec(`GRANT r_1, r_2, r_3 TO 'test_role'@'localhost';`) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_role", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_role", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`SET ROLE r_1, r_2;`) rootTk.MustExec(`SET DEFAULT ROLE r_1 TO 'test_role'@'localhost';`) // test bogus role for current user. @@ -436,11 +436,11 @@ func TestErrorMessage(t *testing.T) { // The session.Auth() func will populate the AuthUsername and AuthHostname fields. // We don't have to explicitly specify them. - require.NoError(t, wildTk.Session().Auth(&auth.UserIdentity{Username: "wildcard", Hostname: "192.168.1.1"}, nil, nil)) + require.NoError(t, wildTk.Session().Auth(&auth.UserIdentity{Username: "wildcard", Hostname: "192.168.1.1"}, nil, nil, nil)) require.EqualError(t, wildTk.ExecToErr("use mysql;"), "[executor:1044]Access denied for user 'wildcard'@'%' to database 'mysql'") specificTk := testkit.NewTestKit(t, store) - require.NoError(t, specificTk.Session().Auth(&auth.UserIdentity{Username: "specifichost", Hostname: "192.168.1.1"}, nil, nil)) + require.NoError(t, specificTk.Session().Auth(&auth.UserIdentity{Username: "specifichost", Hostname: "192.168.1.1"}, nil, nil, nil)) require.EqualError(t, specificTk.ExecToErr("use mysql;"), "[executor:1044]Access denied for user 'specifichost'@'192.168.1.1' to database 'mysql'") } @@ -466,12 +466,12 @@ func TestDropTablePrivileges(t *testing.T) { ctx, _ := tk.Session().(sessionctx.Context) tk.MustExec(`CREATE TABLE todrop(c int);`) // ctx.GetSessionVars().User = "root@localhost" - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`CREATE USER 'drop'@'localhost';`) tk.MustExec(`GRANT Select ON test.todrop TO 'drop'@'localhost';`) // ctx.GetSessionVars().User = "drop@localhost" - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "drop", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "drop", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`SELECT * FROM todrop;`) require.Error(t, tk.ExecToErr("DROP TABLE todrop;")) @@ -494,12 +494,12 @@ func TestSetPasswdStmt(t *testing.T) { tk.MustExec("CREATE USER 'nobodyuser'") tk.MustExec("GRANT ALL ON *.* TO 'superuser'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser", Hostname: "localhost", AuthUsername: "superuser", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser", Hostname: "localhost", AuthUsername: "superuser", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("SET PASSWORD for 'nobodyuser' = 'newpassword'") tk.MustExec("SET PASSWORD for 'nobodyuser' = ''") // low privileged user trying to set password for other user (fails) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser", Hostname: "localhost", AuthUsername: "nobodyuser", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser", Hostname: "localhost", AuthUsername: "nobodyuser", AuthHostname: "%"}, nil, nil, nil)) err := tk.ExecToErr("SET PASSWORD for 'superuser' = 'newpassword'") require.Error(t, err) } @@ -526,7 +526,7 @@ func TestAlterUserStmt(t *testing.T) { tk.MustExec(`ALTER USER 'semuser1' COMMENT 'comment1'`) tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "semuser1"`).Check(testkit.Rows("{\"metadata\": {\"comment\": \"comment1\"}, \"resource_group\": \"rg1\"}")) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") @@ -535,7 +535,7 @@ func TestAlterUserStmt(t *testing.T) { // nobodyuser4 = FAIL (has SYSTEM_USER) // superuser2 = FAIL (has SYSTEM_USER privilege implied by SUPER) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") @@ -546,7 +546,7 @@ func TestAlterUserStmt(t *testing.T) { // Nobody3 has no privileges at all, but they can still alter their own password. // Any other user fails. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser3", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser3", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") err = tk.ExecToErr("ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") @@ -556,13 +556,13 @@ func TestAlterUserStmt(t *testing.T) { // Nobody5 doesn't explicitly have CREATE USER, but mysql also accepts UDPATE on mysql.user // as a substitute so it can modify nobody2 and nobody3 but not nobody4 - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") err = tk.ExecToErr("ALTER USER 'nobodyuser4' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SYSTEM_USER or SUPER privilege(s) for this operation") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'semuser1' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'semuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'semuser3' IDENTIFIED BY ''") @@ -577,17 +577,17 @@ func TestAlterUserStmt(t *testing.T) { // any request for UpdatePriv on mysql.user even if the privilege exists in the internal mysql.user table. // UpdatePriv on mysql.user - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser5", Hostname: "localhost"}, nil, nil, nil)) err = tk.ExecToErr("ALTER USER 'nobodyuser2' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation") // actual CreateUserPriv - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nobodyuser2", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") // UpdatePriv on mysql.user but also has RESTRICTED_TABLES_ADMIN - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser1", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ALTER USER 'nobodyuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'nobodyuser3' IDENTIFIED BY ''") @@ -597,10 +597,10 @@ func TestAlterUserStmt(t *testing.T) { tk.MustExec("ALTER USER 'semuser2' IDENTIFIED BY ''") tk.MustExec("ALTER USER 'semuser3' IDENTIFIED BY ''") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "superuser2", Hostname: "localhost"}, nil, nil, nil)) err = tk.ExecToErr("ALTER USER 'semuser1' IDENTIFIED BY 'newpassword'") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the RESTRICTED_USER_ADMIN privilege(s) for this operation") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser4", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "semuser4", Hostname: "localhost"}, nil, nil, nil)) // has restricted_user_admin but not CREATE USER or (update on mysql.user + RESTRICTED_TABLES_ADMIN) tk.MustExec("ALTER USER 'semuser4' IDENTIFIED BY ''") // can modify self err = tk.ExecToErr("ALTER USER 'nobodyuser3' IDENTIFIED BY 'newpassword'") @@ -619,13 +619,13 @@ func TestSelectViewSecurity(t *testing.T) { ctx, _ := tk.Session().(sessionctx.Context) tk.MustExec(`CREATE TABLE viewsecurity(c int);`) // ctx.GetSessionVars().User = "root@localhost" - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`CREATE USER 'selectusr'@'localhost';`) tk.MustExec(`GRANT CREATE VIEW ON test.* TO 'selectusr'@'localhost';`) tk.MustExec(`GRANT SELECT ON test.viewsecurity TO 'selectusr'@'localhost';`) // ctx.GetSessionVars().User = "selectusr@localhost" - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "selectusr", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "selectusr", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`SELECT * FROM test.viewsecurity;`) tk.MustExec(`CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW test.selectviewsecurity as select * FROM test.viewsecurity;`) @@ -702,7 +702,7 @@ func TestShowViewPriv(t *testing.T) { } for _, test := range tests { - tk.Session().Auth(&auth.UserIdentity{Username: test.userName, Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: test.userName, Hostname: "localhost"}, nil, nil, nil) err := tk.ExecToErr("SHOW CREATE VIEW test.v") if test.showViewErr != "" { require.EqualError(t, err, test.showViewErr, test) @@ -740,15 +740,15 @@ func TestRoleAdminSecurity(t *testing.T) { tk.MustExec(`CREATE USER 'ar2'@'localhost';`) tk.MustExec(`GRANT ALL ON *.* to ar1@localhost`) defer func() { - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("drop user 'ar1'@'localhost'") tk.MustExec("drop user 'ar2'@'localhost'") }() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar1", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`create role r_test1@localhost`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ar2", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr(`create role r_test2@localhost`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) } @@ -779,7 +779,7 @@ func TestCheckCertBasedAuth(t *testing.T) { tk.MustExec(`CREATE USER 'r15_san_only_fail'@'localhost' require san 'URI:spiffe://mesh.pingcap.com/ns/timesh/sa/me2'`) defer func() { - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("drop user 'r1'@'localhost'") tk.MustExec("drop user 'r2'@'localhost'") tk.MustExec("drop user 'r3'@'localhost'") @@ -798,27 +798,27 @@ func TestCheckCertBasedAuth(t *testing.T) { }() // test without ssl or ca - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) // test use ssl without ca tk.Session().GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: nil} - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) // test use ssl with signed but info wrong ca. tk.Session().GetSessionVars().TLSConnectionState = &tls.ConnectionState{VerifiedChains: [][]*x509.Certificate{{{}}}} - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) // test a all pass case tk.Session().GetSessionVars().TLSConnectionState = connectionState( @@ -848,16 +848,16 @@ func TestCheckCertBasedAuth(t *testing.T) { require.NoError(t, err) cert.URIs = append(cert.URIs, &url) }) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r14_san_only_pass", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r4", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r14_san_only_pass", Hostname: "localhost"}, nil, nil, nil)) // test require but give nothing tk.Session().GetSessionVars().TLSConnectionState = nil - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) // test mismatch cipher tk.Session().GetSessionVars().TLSConnectionState = connectionState( @@ -882,9 +882,9 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_256_GCM_SHA384) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r6", Hostname: "localhost"}, nil, nil)) // not require cipher - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r11_cipher_only", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r5", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r6", Hostname: "localhost"}, nil, nil, nil)) // not require cipher + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r11_cipher_only", Hostname: "localhost"}, nil, nil, nil)) // test only subject or only issuer tk.Session().GetSessionVars().TLSConnectionState = connectionState( @@ -909,7 +909,7 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r7_issuer_only", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r7_issuer_only", Hostname: "localhost"}, nil, nil, nil)) tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ @@ -932,7 +932,7 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r8_subject_only", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r8_subject_only", Hostname: "localhost"}, nil, nil, nil)) // test disorder issuer or subject tk.Session().GetSessionVars().TLSConnectionState = connectionState( @@ -950,7 +950,7 @@ func TestCheckCertBasedAuth(t *testing.T) { }, }, tls.TLS_AES_128_GCM_SHA256) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r9_subject_disorder", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r9_subject_disorder", Hostname: "localhost"}, nil, nil, nil)) tk.Session().GetSessionVars().TLSConnectionState = connectionState( pkix.Name{ Names: []pkix.AttributeTypeAndValue{ @@ -966,14 +966,14 @@ func TestCheckCertBasedAuth(t *testing.T) { Names: []pkix.AttributeTypeAndValue{}, }, tls.TLS_AES_128_GCM_SHA256) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r10_issuer_disorder", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r10_issuer_disorder", Hostname: "localhost"}, nil, nil, nil)) // test mismatch san - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r15_san_only_fail", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r15_san_only_fail", Hostname: "localhost"}, nil, nil, nil)) // test old data and broken data - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r12_old_tidb_user", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r13_broken_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "r12_old_tidb_user", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r13_broken_user", Hostname: "localhost"}, nil, nil, nil)) } func connectionState(issuer, subject pkix.Name, cipher uint16, opt ...func(c *x509.Certificate)) *tls.ConnectionState { @@ -996,13 +996,13 @@ func TestCheckAuthenticate(t *testing.T) { tk.MustExec(`CREATE USER 'u3@example.com'@'localhost';`) tk.MustExec(`CREATE USER u4@localhost;`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) salt := []byte{85, 92, 45, 22, 58, 79, 107, 6, 122, 125, 58, 80, 12, 90, 103, 32, 90, 10, 74, 82} authentication := []byte{24, 180, 183, 225, 166, 6, 81, 102, 70, 248, 199, 143, 91, 204, 169, 9, 161, 171, 203, 33} - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, authentication, salt)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, authentication, salt, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil, nil)) tk1 := testkit.NewTestKit(t, store) tk1.MustExec("drop user 'u1'@'localhost'") @@ -1010,18 +1010,18 @@ func TestCheckAuthenticate(t *testing.T) { tk1.MustExec("drop user 'u3@example.com'@'localhost'") tk1.MustExec("drop user u4@localhost") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u2", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u3@example.com", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost"}, nil, nil, nil)) tk2 := testkit.NewTestKit(t, store) tk2.MustExec("create role 'r1'@'localhost'") tk2.MustExec("create role 'r2'@'localhost'") tk2.MustExec("create role 'r3@example.com'@'localhost'") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil)) - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3@example.com", Hostname: "localhost"}, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r1", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r2", Hostname: "localhost"}, nil, nil, nil)) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "r3@example.com", Hostname: "localhost"}, nil, nil, nil)) tk1.MustExec("drop user 'r1'@'localhost'") tk1.MustExec("drop user 'r2'@'localhost'") @@ -1037,34 +1037,34 @@ func TestUseDB(t *testing.T) { tk.MustExec("CREATE USER 'usenobody'") tk.MustExec("GRANT ALL ON *.* TO 'usesuper'") // without grant option - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil, nil)) require.Error(t, tk.ExecToErr("GRANT SELECT ON mysql.* TO 'usenobody'")) // with grant option tk = testkit.NewTestKit(t, store) // high privileged user tk.MustExec("GRANT ALL ON *.* TO 'usesuper' WITH GRANT OPTION") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("use mysql") // low privileged user - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil, nil)) err := tk.ExecToErr("use mysql") require.Error(t, err) // try again after privilege granted - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("GRANT SELECT ON mysql.* TO 'usenobody'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usenobody", Hostname: "localhost", AuthUsername: "usenobody", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("use mysql") // test `use db` for role. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "usesuper", Hostname: "localhost", AuthUsername: "usesuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec(`CREATE DATABASE app_db`) tk.MustExec(`CREATE ROLE 'app_developer'`) tk.MustExec(`GRANT ALL ON app_db.* TO 'app_developer'`) tk.MustExec(`CREATE USER 'dev'@'localhost'`) tk.MustExec(`GRANT 'app_developer' TO 'dev'@'localhost'`) tk.MustExec(`SET DEFAULT ROLE 'app_developer' TO 'dev'@'localhost'`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "localhost", AuthUsername: "dev", AuthHostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dev", Hostname: "localhost", AuthUsername: "dev", AuthHostname: "localhost"}, nil, nil, nil)) tk.MustExec("use app_db") err = tk.ExecToErr("use mysql") require.Error(t, err) @@ -1079,19 +1079,19 @@ func TestRevokePrivileges(t *testing.T) { tk.MustExec("GRANT ALL ON *.* TO 'hasgrant'") tk.MustExec("GRANT ALL ON mysql.* TO 'withoutgrant'") // Without grant option - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil, nil)) require.Error(t, tk.ExecToErr("REVOKE SELECT ON mysql.* FROM 'withoutgrant'")) // With grant option tk = testkit.NewTestKit(t, store) tk.MustExec("GRANT ALL ON *.* TO 'hasgrant' WITH GRANT OPTION") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "hasgrant", Hostname: "localhost", AuthUsername: "hasgrant", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("REVOKE SELECT ON mysql.* FROM 'withoutgrant'") tk.MustExec("REVOKE ALL ON mysql.* FROM withoutgrant") // For issue https://github.com/pingcap/tidb/issues/23850 tk.MustExec("CREATE USER u4") tk.MustExec("GRANT ALL ON *.* TO u4 WITH GRANT OPTION") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost", AuthUsername: "u4", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u4", Hostname: "localhost", AuthUsername: "u4", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("REVOKE ALL ON *.* FROM CURRENT_USER()") } @@ -1102,10 +1102,10 @@ func TestSetGlobal(t *testing.T) { tk.MustExec(`CREATE USER setglobal_b@localhost`) tk.MustExec(`GRANT SUPER ON *.* to setglobal_a@localhost`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_a", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_a", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`set global innodb_commit_concurrency=16`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_b", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "setglobal_b", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr(`set global innodb_commit_concurrency=16`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) } @@ -1118,20 +1118,20 @@ func TestCreateDropUser(t *testing.T) { tk.MustExec(`GRANT ALL ON *.* to tcd2 WITH GRANT OPTION`) // should fail - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil, nil)) err := tk.ExecToErr(`CREATE USER acdc`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) err = tk.ExecToErr(`DROP USER tcd2`) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) // should pass - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthUsername: "tcd2", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthUsername: "tcd2", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec(`DROP USER tcd1`) tk.MustExec(`CREATE USER tcd1`) // should pass tk.MustExec(`GRANT tcd2 TO tcd1`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthUsername: "tcd1", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec(`SET ROLE tcd2;`) tk.MustExec(`CREATE USER tcd3`) tk.MustExec(`DROP USER tcd3`) @@ -1159,10 +1159,10 @@ func TestConfigPrivilege(t *testing.T) { tk.MustExec(`GRANT ALL ON *.* to tcd2`) tk.MustExec(`REVOKE CONFIG ON *.* FROM tcd2`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthHostname: "tcd1", AuthUsername: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd1", Hostname: "localhost", AuthHostname: "tcd1", AuthUsername: "%"}, nil, nil, nil)) tk.MustExec(`SHOW CONFIG`) tk.MustExec(`SET CONFIG TIKV testkey="testval"`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthHostname: "tcd2", AuthUsername: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tcd2", Hostname: "localhost", AuthHostname: "tcd2", AuthUsername: "%"}, nil, nil, nil)) err := tk.ExecToErr(`SHOW CONFIG`) require.Error(t, err) require.Regexp(t, "you need \\(at least one of\\) the CONFIG privilege\\(s\\) for this operation$", err.Error()) @@ -1180,12 +1180,12 @@ func TestShowCreateTable(t *testing.T) { tk.MustExec(`GRANT select ON mysql.* to tsct2`) // should fail - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct1", Hostname: "localhost", AuthUsername: "tsct1", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct1", Hostname: "localhost", AuthUsername: "tsct1", AuthHostname: "%"}, nil, nil, nil)) err := tk.ExecToErr(`SHOW CREATE TABLE mysql.user`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) // should pass - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct2", Hostname: "localhost", AuthUsername: "tsct2", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tsct2", Hostname: "localhost", AuthUsername: "tsct2", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec(`SHOW CREATE TABLE mysql.user`) } @@ -1203,7 +1203,7 @@ func TestReplaceAndInsertOnDuplicate(t *testing.T) { tk.MustExec(`GRANT DELETE ON t1 TO tr_delete`) // Restrict the permission to INSERT only. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_insert", Hostname: "localhost", AuthUsername: "tr_insert", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_insert", Hostname: "localhost", AuthUsername: "tr_insert", AuthHostname: "%"}, nil, nil, nil)) // REPLACE requires INSERT + DELETE privileges, having INSERT alone is insufficient. err := tk.ExecToErr(`REPLACE INTO t1 VALUES (1, 2)`) @@ -1219,13 +1219,13 @@ func TestReplaceAndInsertOnDuplicate(t *testing.T) { tk.MustExec(`INSERT INTO t1 VALUES (6, 7)`) // Also check that having DELETE alone is insufficient for REPLACE. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_delete", Hostname: "localhost", AuthUsername: "tr_delete", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_delete", Hostname: "localhost", AuthUsername: "tr_delete", AuthHostname: "%"}, nil, nil, nil)) err = tk.ExecToErr(`REPLACE INTO t1 VALUES (8, 9)`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'tr_delete'@'%' for table 't1'") // Also check that having UPDATE alone is insufficient for INSERT ON DUPLICATE. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_update", Hostname: "localhost", AuthUsername: "tr_update", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tr_update", Hostname: "localhost", AuthUsername: "tr_update", AuthHostname: "%"}, nil, nil, nil)) err = tk.ExecToErr(`INSERT INTO t1 VALUES (10, 11) ON DUPLICATE KEY UPDATE b = 12`) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'tr_update'@'%' for table 't1'") @@ -1243,10 +1243,10 @@ func TestAnalyzeTable(t *testing.T) { tk.MustExec("use atest") tk.MustExec("CREATE TABLE t1 (a int)") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("analyze table mysql.user") // low privileged user - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil, nil)) err := tk.ExecToErr("analyze table t1") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'anobody'@'%' for table 't1'") @@ -1255,16 +1255,16 @@ func TestAnalyzeTable(t *testing.T) { require.EqualError(t, err, "[planner:1142]SELECT command denied to user 'anobody'@'%' for table 't1'") // try again after SELECT privilege granted - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("GRANT SELECT ON atest.* TO 'anobody'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil, nil)) err = tk.ExecToErr("analyze table t1") require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) require.EqualError(t, err, "[planner:1142]INSERT command denied to user 'anobody'@'%' for table 't1'") // Add INSERT privilege and it should work. - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "asuper", Hostname: "localhost", AuthUsername: "asuper", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("GRANT INSERT ON atest.* TO 'anobody'") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "anobody", Hostname: "localhost", AuthUsername: "anobody", AuthHostname: "%"}, nil, nil, nil)) tk.MustExec("analyze table t1") } @@ -1275,7 +1275,7 @@ func TestSystemSchema(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec(`CREATE USER 'u1'@'localhost';`) tk.MustExec(`GRANT SELECT ON *.* TO 'u1'@'localhost';`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`select * from information_schema.tables`) tk.MustExec(`select * from information_schema.key_column_usage`) err := tk.ExecToErr("create table information_schema.t(a int)") @@ -1314,15 +1314,15 @@ func TestPerformanceSchema(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec(`CREATE USER 'u1'@'localhost';`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr("select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`GRANT SELECT ON *.* TO 'u1'@'localhost';`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("select * from performance_schema.events_statements_summary_by_digest where schema_name = 'tst'") tk.MustExec(`select * from performance_schema.events_statements_summary_by_digest`) err = tk.ExecToErr("drop table performance_schema.events_statements_summary_by_digest") @@ -1436,7 +1436,7 @@ func TestMetricsSchema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: test.user, Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnPrivilege) rs, err := tk.Session().ExecuteInternal(ctx, test.stmt) @@ -1455,11 +1455,11 @@ func TestAdminCommand(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`CREATE USER 'test_admin'@'localhost';`) tk.MustExec(`CREATE TABLE t(a int)`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_admin", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_admin", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr("ADMIN SHOW DDL JOBS") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) @@ -1467,7 +1467,7 @@ func TestAdminCommand(t *testing.T) { require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrPrivilegeCheckFail)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("ADMIN SHOW DDL JOBS") } @@ -1475,12 +1475,12 @@ func TestTableNotExistNoPermissions(t *testing.T) { store := createStoreAndPrepareDB(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`CREATE USER 'testnotexist'@'localhost';`) tk.MustExec(`CREATE DATABASE dbexists`) tk.MustExec(`CREATE TABLE dbexists.t1 (a int)`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testnotexist", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testnotexist", Hostname: "localhost"}, nil, nil, nil)) tests := []struct { stmt string @@ -1533,24 +1533,24 @@ func TestLoadDataPrivilege(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`CREATE USER 'test_load'@'localhost';`) tk.MustExec(`CREATE TABLE t_load(a int)`) tk.MustExec(`GRANT SELECT on *.* to 'test_load'@'localhost'`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil, nil)) err = tk.ExecToErr("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`GRANT INSERT on *.* to 'test_load'@'localhost'`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' INTO TABLE t_load") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(`GRANT INSERT on *.* to 'test_load'@'localhost'`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_load", Hostname: "localhost"}, nil, nil, nil)) err = tk.ExecToErr("LOAD DATA LOCAL INFILE '/tmp/load_data_priv.csv' REPLACE INTO TABLE t_load") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) @@ -1561,7 +1561,7 @@ func TestSelectIntoNoPermissions(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec(`CREATE USER 'nofile'@'localhost';`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nofile", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "nofile", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr(`select 1 into outfile '/tmp/doesntmatter-no-permissions'`) require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrSpecificAccessDenied)) @@ -1584,11 +1584,11 @@ func TestAuthHost(t *testing.T) { rootTk.MustExec(`CREATE USER 'test_auth_host'@'%';`) rootTk.MustExec(`GRANT ALL ON *.* TO 'test_auth_host'@'%' WITH GRANT OPTION;`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil, nil)) tk.MustExec("CREATE USER 'test_auth_host'@'192.168.%';") tk.MustExec("GRANT SELECT ON *.* TO 'test_auth_host'@'192.168.%';") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_auth_host", Hostname: "192.168.0.10"}, nil, nil, nil)) err := tk.ExecToErr("create user test_auth_host_a") require.Error(t, err) @@ -1654,7 +1654,7 @@ func TestFieldList(t *testing.T) { // Issue #14237 List fields RPC tk.MustExec("use test") tk.MustExec(`CREATE USER 'tableaccess'@'localhost'`) tk.MustExec(`CREATE TABLE fieldlistt1 (a int)`) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tableaccess", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "tableaccess", Hostname: "localhost"}, nil, nil, nil)) _, err := tk.Session().FieldList("fieldlistt1") require.Error(t, err) require.True(t, terror.ErrorEqual(err, core.ErrTableaccessDenied)) @@ -1669,7 +1669,7 @@ func TestDynamicPrivs(t *testing.T) { rootTk.MustExec("CREATE ROLE anyrolename") tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "notsuper", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "notsuper", Hostname: "%"}, nil, nil, nil)) // test SYSTEM_VARIABLES_ADMIN err := tk.ExecToErr("SET GLOBAL wait_timeout = 86400") @@ -1717,12 +1717,12 @@ func TestDynamicGrantOption(t *testing.T) { rootTk.MustExec("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser2 WITH GRANT OPTION") tk1 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "varuser1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "varuser1", Hostname: "%"}, nil, nil, nil)) err := tk1.ExecToErr("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation") tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "varuser2", Hostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "varuser2", Hostname: "%"}, nil, nil, nil)) tk2.MustExec("GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") } @@ -1736,9 +1736,9 @@ func TestSecurityEnhancedModeRestrictedTables(t *testing.T) { cloudAdminTK.MustExec("GRANT CREATE ON mysql.* to cloudadmin") cloudAdminTK.MustExec("CREATE USER uroot") cloudAdminTK.MustExec("GRANT ALL ON *.* to uroot WITH GRANT OPTION") // A "MySQL" all powerful user. - require.NoError(t, cloudAdminTK.Session().Auth(&auth.UserIdentity{Username: "cloudadmin", Hostname: "%"}, nil, nil)) + require.NoError(t, cloudAdminTK.Session().Auth(&auth.UserIdentity{Username: "cloudadmin", Hostname: "%"}, nil, nil, nil)) urootTk := testkit.NewTestKit(t, store) - require.NoError(t, urootTk.Session().Auth(&auth.UserIdentity{Username: "uroot", Hostname: "%"}, nil, nil)) + require.NoError(t, urootTk.Session().Auth(&auth.UserIdentity{Username: "uroot", Hostname: "%"}, nil, nil, nil)) sem.Enable() defer sem.Disable() @@ -1767,7 +1767,7 @@ func TestSecurityEnhancedModeInfoschema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "uroot1", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) sem.Enable() defer sem.Disable() @@ -1782,7 +1782,7 @@ func TestSecurityEnhancedModeInfoschema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "uroot2", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) // flip from is NOT NULL etc tk.MustQuery(`SELECT COUNT(*) FROM information_schema.tidb_servers_info WHERE ip IS NULL`).Check(testkit.Rows("0")) @@ -1801,7 +1801,7 @@ func TestClusterConfigInfoschema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "ccnobody", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS").Check(testkit.Rows("GRANT USAGE ON *.* TO 'ccnobody'@'%'")) err := tk.QueryToErr("SELECT * FROM information_schema.cluster_config") @@ -1832,7 +1832,7 @@ func TestClusterConfigInfoschema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "ccconfig", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS").Check(testkit.Rows("GRANT CONFIG ON *.* TO 'ccconfig'@'%'")) // Needs CONFIG privilege tk.MustQuery("SELECT * FROM information_schema.cluster_config") @@ -1855,7 +1855,7 @@ func TestClusterConfigInfoschema(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "ccprocess", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS").Check(testkit.Rows("GRANT PROCESS ON *.* TO 'ccprocess'@'%'")) // Needs Process privilege tk.MustQuery("SELECT * FROM information_schema.CLUSTER_info") @@ -1883,7 +1883,7 @@ func TestSecurityEnhancedModeStatusVars(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "unostatus", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) } func TestSecurityEnhancedLocalBackupRestore(t *testing.T) { @@ -1895,7 +1895,7 @@ func TestSecurityEnhancedLocalBackupRestore(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "backuprestore", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnPrivilege) // Prior to SEM nolocal has permission, the error should be because backup requires tikv @@ -1939,7 +1939,7 @@ func TestRenameUser(t *testing.T) { rootTk.MustExec("CREATE USER ru3") rootTk.MustExec("CREATE USER ru6@localhost") tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ru1", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "ru1", Hostname: "localhost"}, nil, nil, nil)) // Check privileges (need CREATE USER) err := tk.ExecToErr("RENAME USER ru3 TO ru4") @@ -2006,7 +2006,7 @@ func TestSecurityEnhancedModeSysVars(t *testing.T) { Hostname: "localhost", AuthUsername: "uroot", AuthHostname: "%", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery(`SHOW VARIABLES LIKE 'tidb_force_priority'`).Check(testkit.Rows()) tk.MustQuery(`SELECT * FROM information_schema.variables_info WHERE variable_name = 'tidb_force_priority'`).Check(testkit.Rows()) @@ -2040,7 +2040,7 @@ func TestSecurityEnhancedModeSysVars(t *testing.T) { Hostname: "localhost", AuthUsername: "uroot", AuthHostname: "%", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery(`SHOW VARIABLES LIKE 'tidb_force_priority'`).Check(testkit.Rows("tidb_force_priority NO_PRIORITY")) tk.MustQuery(`SELECT COUNT(*) FROM information_schema.variables_info WHERE variable_name = 'tidb_top_sql_max_meta_count'`).Check(testkit.Rows("1")) @@ -2120,7 +2120,7 @@ func TestSecurityEnhancedModeRestrictedUsers(t *testing.T) { Hostname: "localhost", AuthUsername: "uroot", AuthHostname: "%", - }, nil, nil) + }, nil, nil, nil) for _, stmt := range stmts { _, err := tk.Exec(stmt) @@ -2133,7 +2133,7 @@ func TestSecurityEnhancedModeRestrictedUsers(t *testing.T) { Hostname: "localhost", AuthUsername: "uroot", AuthHostname: "%", - }, nil, nil) + }, nil, nil, nil) for _, stmt := range stmts { tk.MustExec(stmt) @@ -2194,7 +2194,7 @@ func TestInfoSchemaUserPrivileges(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "isnobody", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) // I can see myself, but I can not see other users tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee = "'isnobody'@'%'"`).Check(testkit.Rows("'isnobody'@'%' def USAGE NO")) @@ -2205,7 +2205,7 @@ func TestInfoSchemaUserPrivileges(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "isselectonmysqluser", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) // Now as isselectonmysqluser // Tests discovered issue that SELECT on mysql.user is not sufficient. It must be on mysql.* @@ -2218,7 +2218,7 @@ func TestInfoSchemaUserPrivileges(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "isroot", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) // I can see myself, but I can not see other users tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee = "'isnobody'@'%'"`).Check(testkit.Rows()) @@ -2229,7 +2229,7 @@ func TestInfoSchemaUserPrivileges(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "isselectonmysql", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) // Now as isselectonmysqluser tk.MustQuery(`SELECT * FROM information_schema.user_privileges WHERE grantee = "'isnobody'@'%'"`).Check(testkit.Rows("'isnobody'@'%' def USAGE NO")) @@ -2251,7 +2251,7 @@ func TestGrantOptionAndRevoke(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "ruser", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery(`SHOW GRANTS FOR u1`).Check(testkit.Rows("GRANT SELECT ON *.* TO 'u1'@'%' WITH GRANT OPTION", "GRANT UPDATE,DELETE ON db.* TO 'u1'@'%'")) @@ -2317,7 +2317,7 @@ func TestGrantReferences(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR referencesUser").Check(testkit.Rows( `GRANT REFERENCES ON *.* TO 'referencesUser'@'%'`, `GRANT REFERENCES ON reftestdb.* TO 'referencesUser'@'%'`, @@ -2339,7 +2339,7 @@ func TestDashboardClientDynamicPriv(t *testing.T) { tk1.Session().Auth(&auth.UserIdentity{ Username: "dc_u1", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk1.MustQuery("SHOW GRANTS FOR CURRENT_USER()").Check(testkit.Rows( "GRANT USAGE ON *.* TO 'dc_u1'@'%'", "GRANT 'dc_r1'@'%' TO 'dc_u1'@'%'", @@ -2390,7 +2390,7 @@ func TestShowGrantsWithRolesAndDynamicPrivs(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "tsg_u1", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS").Check(testkit.Rows( "GRANT PROCESS,CONFIG ON *.* TO 'tsg_u1'@'%'", "GRANT 'tsg_r1'@'%' TO 'tsg_u1'@'%'", @@ -2414,7 +2414,7 @@ func TestShowGrantsWithRolesAndDynamicPrivs(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "tsg_u2", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS").Check(testkit.Rows( "GRANT USAGE ON *.* TO 'tsg_u2'@'%'", "GRANT 'tsg_r1'@'%' TO 'tsg_u2'@'%'", @@ -2470,7 +2470,7 @@ func TestGrantLockTables(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR lock_tables_user").Check(testkit.Rows( `GRANT LOCK TABLES ON *.* TO 'lock_tables_user'@'%'`, `GRANT LOCK TABLES ON lock_tables_db.* TO 'lock_tables_user'@'%'`)) @@ -2506,7 +2506,7 @@ func TestShowGrantsForCurrentUserUsingRole(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "joe", Hostname: "%", - }, nil, nil) + }, nil, nil, nil) err := tk.QueryToErr("SHOW GRANTS FOR CURRENT_USER() USING notgranted") require.Error(t, err) @@ -2541,7 +2541,7 @@ func TestGrantPlacementAdminDynamicPriv(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR placement_user").Check(testkit.Rows( `GRANT USAGE ON *.* TO 'placement_user'@'%'`, `GRANT PLACEMENT_ADMIN ON *.* TO 'placement_user'@'%'`)) @@ -2561,17 +2561,17 @@ func TestPlacementPolicyStmt(t *testing.T) { tk.MustExec("GRANT ALL ON *.* TO super_user") tk.MustExec("GRANT PLACEMENT_ADMIN ON *.* TO placement_user") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "empty_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "empty_user", Hostname: "localhost"}, nil, nil, nil)) err := tk.ExecToErr(createStmt) require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or PLACEMENT_ADMIN privilege(s) for this operation") err = tk.ExecToErr(dropStmt) require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or PLACEMENT_ADMIN privilege(s) for this operation") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "super_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "super_user", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(createStmt) tk.MustExec(dropStmt) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "placement_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "placement_user", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec(createStmt) tk.MustExec(dropStmt) } @@ -2584,7 +2584,7 @@ func TestResourceGroupAdminDynamicPriv(t *testing.T) { tk1.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk1.MustExec("CREATE USER resource_group_user") tk1.MustExec("set @@global.tidb_enable_resource_control = 1") @@ -2593,7 +2593,7 @@ func TestResourceGroupAdminDynamicPriv(t *testing.T) { tk2.Session().Auth(&auth.UserIdentity{ Username: "resource_group_user", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) err := tk2.ExecToErr("CREATE RESOURCE GROUP test RU_PER_SEC = 666") require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or RESOURCE_GROUP_ADMIN privilege(s) for this operation") @@ -2638,7 +2638,7 @@ func TestGrantCreateTmpTables(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows( `GRANT CREATE TEMPORARY TABLES ON *.* TO 'u1'@'%'`, `GRANT CREATE TEMPORARY TABLES ON create_tmp_table_db.* TO 'u1'@'%'`)) @@ -2661,13 +2661,13 @@ func TestCreateTmpTablesPriv(t *testing.T) { tk.MustExec("GRANT CREATE TEMPORARY TABLES, USAGE ON test.* TO vcreate_tmp") tk.MustExec("GRANT CREATE TEMPORARY TABLES, USAGE ON *.* TO vcreate_tmp_all") - tk.Session().Auth(&auth.UserIdentity{Username: "vcreate", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "vcreate", Hostname: "localhost"}, nil, nil, nil) err := tk.ExecToErr(createStmt) require.EqualError(t, err, "[planner:1044]Access denied for user 'vcreate'@'%' to database 'test'") - tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp", Hostname: "localhost"}, nil, nil, nil) tk.MustExec(createStmt) tk.MustExec(dropStmt) - tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp_all", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp_all", Hostname: "localhost"}, nil, nil, nil) // TODO: issue #29280 to be fixed. //err = tk.ExecToErr(createStmt) //require.EqualError(t, err, "[planner:1044]Access denied for user 'vcreate_tmp_all'@'%' to database 'test'") @@ -2778,7 +2778,7 @@ func TestCreateTmpTablesPriv(t *testing.T) { }, } - tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp", Hostname: "localhost"}, nil, nil) + tk.Session().Auth(&auth.UserIdentity{Username: "vcreate_tmp", Hostname: "localhost"}, nil, nil, nil) tk.MustExec("use test") tk.MustExec(dropStmt) for _, test := range tests { @@ -2809,7 +2809,7 @@ func TestRevokeSecondSyntax(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustExec(`drop user if exists ss1;`) tk.MustExec(`create user ss1;`) @@ -2831,7 +2831,7 @@ func TestGrantEvent(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows( `GRANT EVENT ON *.* TO 'u1'@'%'`, `GRANT EVENT ON event_db.* TO 'u1'@'%'`)) @@ -2855,7 +2855,7 @@ func TestGrantRoutine(t *testing.T) { tk.Session().Auth(&auth.UserIdentity{ Username: "root", Hostname: "localhost", - }, nil, nil) + }, nil, nil, nil) tk.MustQuery("SHOW GRANTS FOR u1").Check(testkit.Rows( `GRANT CREATE ROUTINE,ALTER ROUTINE ON *.* TO 'u1'@'%'`, `GRANT CREATE ROUTINE,ALTER ROUTINE ON routine_db.* TO 'u1'@'%'`)) @@ -2871,15 +2871,15 @@ func TestIssue28675(t *testing.T) { tk.MustExec(`create user test_user`) tk.MustExec("create view test.v as select 1") tk.MustExec("grant show view on test.v to test_user") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_user", Hostname: "localhost"}, nil, nil, nil)) tk.MustQuery("select count(*) from information_schema.columns where table_schema='test' and table_name='v'").Check(testkit.Rows("0")) tk.ExecToErr("desc test.v") tk.ExecToErr("explain test.v") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("grant update on test.v to test_user") tk.MustExec("grant select on test.v to test_user") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_user", Hostname: "localhost"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "test_user", Hostname: "localhost"}, nil, nil, nil)) tk.MustQuery("select count(*) from information_schema.columns where table_schema='test' and table_name='v'").Check(testkit.Rows("1")) tk.MustQuery("select count(*) from information_schema.columns where table_schema='Test' and table_name='V'").Check(testkit.Rows("1")) tk.MustQuery("select privileges from information_schema.columns where table_schema='test' and table_name='v'").Check(testkit.Rows("select,update")) @@ -2956,7 +2956,7 @@ func TestIssue29823(t *testing.T) { tk.MustExec("grant r1 to u1") tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil, nil)) tk2.MustExec("set role all") tk2.MustQuery("select current_role()").Check(testkit.Rows("`r1`@`%`")) tk2.MustQuery("select * from test.t1").Check(testkit.Rows()) @@ -2982,7 +2982,7 @@ func TestCheckPreparePrivileges(t *testing.T) { tk.MustExec("insert into t values(1)") tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "%"}, nil, nil, nil)) // sql err := tk2.ExecToErr("prepare s from 'select * from test.t'") @@ -3021,7 +3021,7 @@ func TestIssue37488(t *testing.T) { tk.MustExec("CREATE USER dba_test@'192.168.%';") tk.MustExec("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER ON test.* TO 'dba_test'@'192.168.%';") - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dba_test", Hostname: "192.168.13.15"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dba_test", Hostname: "192.168.13.15"}, nil, nil, nil)) tk.MustQuery("select current_user()").Check(testkit.Rows("dba_test@192.168.%")) tk.MustExec("DROP TABLE IF EXISTS a;") // succ } @@ -3074,33 +3074,33 @@ func TestPasswordExpireWithoutSandBoxMode(t *testing.T) { // PASSWORD EXPIRE user := &auth.UserIdentity{Username: "testuser", Hostname: "localhost"} tk := testkit.NewTestKit(t, store) - err := tk.Session().Auth(user, nil, nil) + err := tk.Session().Auth(user, nil, nil, nil) require.ErrorContains(t, err, "Your password has expired") // PASSWORD EXPIRE NEVER rootTk.MustExec(`ALTER USER 'testuser'@'localhost' IDENTIFIED BY '' PASSWORD EXPIRE NEVER`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) // PASSWORD EXPIRE INTERVAL N DAY rootTk.MustExec(`ALTER USER 'testuser'@'localhost' PASSWORD EXPIRE INTERVAL 2 DAY`) rootTk.MustExec(`UPDATE mysql.user SET password_last_changed = (now() - INTERVAL 1 DAY) where user='testuser'`) rootTk.MustExec(`FLUSH PRIVILEGES`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) rootTk.MustExec(`UPDATE mysql.user SET password_last_changed = (now() - INTERVAL 2 DAY) where user='testuser'`) rootTk.MustExec(`FLUSH PRIVILEGES`) time.Sleep(2 * time.Second) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.ErrorContains(t, err, "Your password has expired") // PASSWORD EXPIRE DEFAULT rootTk.MustExec(`ALTER USER 'testuser'@'localhost' PASSWORD EXPIRE DEFAULT`) rootTk.MustExec(`SET GLOBAL default_password_lifetime = 2`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.ErrorContains(t, err, "Your password has expired") rootTk.MustExec(`SET GLOBAL default_password_lifetime = 3`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) } @@ -3113,14 +3113,14 @@ func TestPasswordExpireWithSandBoxMode(t *testing.T) { // PASSWORD EXPIRE user := &auth.UserIdentity{Username: "testuser", Hostname: "localhost"} tk := testkit.NewTestKit(t, store) - err := tk.Session().Auth(user, nil, nil) + err := tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.True(t, tk.Session().InSandBoxMode()) tk.Session().DisableSandBoxMode() // PASSWORD EXPIRE NEVER rootTk.MustExec(`ALTER USER 'testuser'@'localhost' IDENTIFIED BY '' PASSWORD EXPIRE NEVER`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.False(t, tk.Session().InSandBoxMode()) @@ -3128,13 +3128,13 @@ func TestPasswordExpireWithSandBoxMode(t *testing.T) { rootTk.MustExec(`ALTER USER 'testuser'@'localhost' PASSWORD EXPIRE INTERVAL 2 DAY`) rootTk.MustExec(`UPDATE mysql.user SET password_last_changed = (now() - INTERVAL 1 DAY) where user='testuser'`) rootTk.MustExec(`FLUSH PRIVILEGES`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.False(t, tk.Session().InSandBoxMode()) rootTk.MustExec(`UPDATE mysql.user SET password_last_changed = (now() - INTERVAL 2 DAY) where user='testuser'`) rootTk.MustExec(`FLUSH PRIVILEGES`) time.Sleep(2 * time.Second) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.True(t, tk.Session().InSandBoxMode()) tk.Session().DisableSandBoxMode() @@ -3142,12 +3142,12 @@ func TestPasswordExpireWithSandBoxMode(t *testing.T) { // PASSWORD EXPIRE DEFAULT rootTk.MustExec(`ALTER USER 'testuser'@'localhost' PASSWORD EXPIRE DEFAULT`) rootTk.MustExec(`SET GLOBAL default_password_lifetime = 2`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.True(t, tk.Session().InSandBoxMode()) tk.Session().DisableSandBoxMode() rootTk.MustExec(`SET GLOBAL default_password_lifetime = 3`) - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.NoError(t, err) require.False(t, tk.Session().InSandBoxMode()) } @@ -3175,31 +3175,31 @@ func TestVerificationInfoWithSessionTokenPlugin(t *testing.T) { // Test password expiration without sandbox. user := &auth.UserIdentity{Username: "testuser", Hostname: "localhost", AuthPlugin: mysql.AuthTiDBSessionToken} tk := testkit.NewTestKit(t, store) - err = tk.Session().Auth(user, tokenBytes, nil) + err = tk.Session().Auth(user, tokenBytes, nil, nil) require.NoError(t, err) require.False(t, tk.Session().InSandBoxMode()) // Test password expiration with sandbox. variable.IsSandBoxModeEnabled.Store(true) - err = tk.Session().Auth(user, tokenBytes, nil) + err = tk.Session().Auth(user, tokenBytes, nil, nil) require.NoError(t, err) require.False(t, tk.Session().InSandBoxMode()) // Enable resource group. variable.EnableResourceControl.Store(true) - err = tk.Session().Auth(user, tokenBytes, nil) + err = tk.Session().Auth(user, tokenBytes, nil, nil) require.NoError(t, err) require.Equal(t, "default", tk.Session().GetSessionVars().ResourceGroupName) // Non-default resource group. rootTk.MustExec("CREATE RESOURCE GROUP rg1 RU_PER_SEC = 999") rootTk.MustExec(`ALTER USER 'testuser'@'localhost' RESOURCE GROUP rg1`) - err = tk.Session().Auth(user, tokenBytes, nil) + err = tk.Session().Auth(user, tokenBytes, nil, nil) require.NoError(t, err) require.Equal(t, "rg1", tk.Session().GetSessionVars().ResourceGroupName) // Wrong token - err = tk.Session().Auth(user, nil, nil) + err = tk.Session().Auth(user, nil, nil, nil) require.ErrorContains(t, err, "Access denied") } @@ -3212,5 +3212,5 @@ func TestNilHandleInConnectionVerification(t *testing.T) { }() store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, nil, nil)) } diff --git a/server/BUILD.bazel b/server/BUILD.bazel index f1643693f0965..ec306f081588a 100644 --- a/server/BUILD.bazel +++ b/server/BUILD.bazel @@ -50,7 +50,9 @@ go_library( "//planner/core", "//plugin", "//privilege", + "//privilege/conn", "//privilege/privileges", + "//privilege/privileges/ldap", "//server/metrics", "//session", "//session/txninfo", diff --git a/server/conn.go b/server/conn.go index 639260d39fbe3..578987d63eab3 100644 --- a/server/conn.go +++ b/server/conn.go @@ -72,6 +72,8 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/plugin" "github.com/pingcap/tidb/privilege" + "github.com/pingcap/tidb/privilege/conn" + "github.com/pingcap/tidb/privilege/privileges/ldap" server_metrics "github.com/pingcap/tidb/server/metrics" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" @@ -189,19 +191,31 @@ func (cc *clientConn) String() string { // plugin. MySQL 8.0 libmysqlclient based clients by default always try `caching_sha2_password`, even // when the server advertises the its default to be `mysql_native_password`. In addition to this switching // may be needed on a per user basis as the authentication method is set per user. -// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest +// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_auth_switch_request.html // https://bugs.mysql.com/bug.php?id=93044 func (cc *clientConn) authSwitchRequest(ctx context.Context, plugin string) ([]byte, error) { + clientPlugin := plugin + if plugin == mysql.AuthLDAPSASL { + clientPlugin += "_client" + } else if plugin == mysql.AuthLDAPSimple { + clientPlugin = mysql.AuthMySQLClearPassword + } failpoint.Inject("FakeAuthSwitch", func() { - failpoint.Return([]byte(plugin), nil) + failpoint.Return([]byte(clientPlugin), nil) }) - enclen := 1 + len(plugin) + 1 + len(cc.salt) + 1 + enclen := 1 + len(clientPlugin) + 1 + len(cc.salt) + 1 data := cc.alloc.AllocWithLen(4, enclen) data = append(data, mysql.AuthSwitchRequest) // switch request - data = append(data, []byte(plugin)...) + data = append(data, []byte(clientPlugin)...) data = append(data, byte(0x00)) // requires null - data = append(data, cc.salt...) - data = append(data, 0) + if plugin == mysql.AuthLDAPSASL { + // append sasl auth method name + data = append(data, []byte(ldap.LDAPSASLAuthImpl.GetSASLAuthMethod())...) + data = append(data, byte(0x00)) + } else { + data = append(data, cc.salt...) + data = append(data, 0) + } err := cc.writePacket(data) if err != nil { logutil.Logger(ctx).Debug("write response to client failed", zap.Error(err)) @@ -647,6 +661,8 @@ func (cc *clientConn) readOptionalSSLRequestAndHandshakeResponse(ctx context.Con case mysql.AuthTiDBSessionToken: case mysql.AuthTiDBAuthToken: case mysql.AuthMySQLClearPassword: + case mysql.AuthLDAPSASL: + case mysql.AuthLDAPSimple: default: return errors.New("Unknown auth plugin") } @@ -676,6 +692,8 @@ func (cc *clientConn) handleAuthPlugin(ctx context.Context, resp *handshakeRespo case mysql.AuthSocket: case mysql.AuthTiDBSessionToken: case mysql.AuthMySQLClearPassword: + case mysql.AuthLDAPSASL: + case mysql.AuthLDAPSimple: default: logutil.Logger(ctx).Warn("Unknown Auth Plugin", zap.String("plugin", resp.AuthPlugin)) } @@ -814,7 +832,7 @@ func (cc *clientConn) openSessionAndDoAuth(authData []byte, authPlugin string) e } userIdentity := &auth.UserIdentity{Username: cc.user, Hostname: host, AuthPlugin: authPlugin} - if err = cc.ctx.Auth(userIdentity, authData, cc.salt); err != nil { + if err = cc.ctx.Auth(userIdentity, authData, cc.salt, cc); err != nil { return err } cc.ctx.SetPort(port) @@ -2608,3 +2626,22 @@ func (cc getLastStmtInConn) PProfLabel() string { return "" } } + +var _ conn.AuthConn = &clientConn{} + +// WriteAuthMoreData implements `conn.AuthConn` interface +func (cc *clientConn) WriteAuthMoreData(data []byte) error { + // See https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_auth_more_data.html + // the `AuthMoreData` packet is just an arbitrary binary slice with a byte 0x1 as prefix. + return cc.writePacket(append([]byte{0, 0, 0, 0, 1}, data...)) +} + +// ReadPacket implements `conn.AuthConn` interface +func (cc *clientConn) ReadPacket() ([]byte, error) { + return cc.readPacket() +} + +// Flush implements `conn.AuthConn` interface +func (cc *clientConn) Flush(ctx context.Context) error { + return cc.flush(ctx) +} diff --git a/server/conn_test.go b/server/conn_test.go index 16aa40e31d7c8..39c4f86ada18f 100644 --- a/server/conn_test.go +++ b/server/conn_test.go @@ -1630,13 +1630,13 @@ func TestAuthSessionTokenPlugin(t *testing.T) { // create a token without TLS tk1 := testkit.NewTestKitWithSession(t, store, tc.Session) tc.Session.GetSessionVars().ConnectionInfo = cc.connectInfo() - tk1.Session().Auth(&auth.UserIdentity{Username: "auth_session_token", Hostname: "localhost"}, nil, nil) + tk1.Session().Auth(&auth.UserIdentity{Username: "auth_session_token", Hostname: "localhost"}, nil, nil, nil) tk1.MustQuery("show session_states") // create a token with TLS cc.tlsConn = &tls.Conn{} tc.Session.GetSessionVars().ConnectionInfo = cc.connectInfo() - tk1.Session().Auth(&auth.UserIdentity{Username: "auth_session_token", Hostname: "localhost"}, nil, nil) + tk1.Session().Auth(&auth.UserIdentity{Username: "auth_session_token", Hostname: "localhost"}, nil, nil, nil) tk1.MustQuery("show session_states") // create a token with UnixSocket @@ -1986,3 +1986,42 @@ func TestProcessInfoForExecuteCommand(t *testing.T) { 0x0A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0})) require.Equal(t, cc.ctx.Session.ShowProcess().Info, "select sum(col1) from t where col1 < ? and col1 > 100") } + +func TestLDAPAuthSwitch(t *testing.T) { + store := testkit.CreateMockStore(t) + cfg := newTestConfig() + cfg.Port = 0 + cfg.Status.StatusPort = 0 + drv := NewTiDBDriver(store) + srv, err := NewServer(cfg, drv) + require.NoError(t, err) + tk := testkit.NewTestKit(t, store) + tk.MustExec("CREATE USER test_simple_ldap IDENTIFIED WITH authentication_ldap_simple AS 'uid=test_simple_ldap,dc=example,dc=com'") + + cc := &clientConn{ + connectionID: 1, + alloc: arena.NewAllocator(1024), + chunkAlloc: chunk.NewAllocator(), + pkt: &packetIO{ + bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)), + }, + server: srv, + user: "test_simple_ldap", + } + se, _ := session.CreateSession4Test(store) + tc := &TiDBContext{ + Session: se, + stmts: make(map[int]*TiDBStatement), + } + cc.setCtx(tc) + cc.isUnixSocket = true + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/FakeAuthSwitch", "return(1)")) + respAuthSwitch, err := cc.checkAuthPlugin(context.Background(), &handshakeResponse41{ + Capability: mysql.ClientProtocol41 | mysql.ClientPluginAuth, + User: "test_simple_ldap", + }) + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/FakeAuthSwitch")) + require.NoError(t, err) + require.Equal(t, []byte(mysql.AuthMySQLClearPassword), respAuthSwitch) +} diff --git a/server/mock_conn.go b/server/mock_conn.go index 620cae702707a..692a66c888a7d 100644 --- a/server/mock_conn.go +++ b/server/mock_conn.go @@ -120,7 +120,7 @@ func CreateMockConn(t *testing.T, server *Server) MockConn { cc.server.rwlock.Unlock() tc.Session.SetSessionManager(server) tc.Session.GetSessionVars().ConnectionInfo = cc.connectInfo() - err = tc.Session.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil) + err = tc.Session.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil) require.NoError(t, err) return &mockConn{ clientConn: cc, diff --git a/session/BUILD.bazel b/session/BUILD.bazel index 209ed174ca505..a16b09f672bb2 100644 --- a/session/BUILD.bazel +++ b/session/BUILD.bazel @@ -46,6 +46,7 @@ go_library( "//planner/core", "//plugin", "//privilege", + "//privilege/conn", "//privilege/privileges", "//session/metrics", "//session/txninfo", diff --git a/session/bootstrap_test.go b/session/bootstrap_test.go index fd208a46e03d9..11b33fdbd6464 100644 --- a/session/bootstrap_test.go +++ b/session/bootstrap_test.go @@ -59,7 +59,7 @@ func TestBootstrap(t *testing.T) { match(t, rows, `%`, "root", "", "mysql_native_password", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", nil, nil, nil, "", "N", time.Now(), nil) r.Close() - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "anyhost"}, []byte(""), []byte(""))) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "anyhost"}, []byte(""), []byte(""), nil)) mustExec(t, se, "use test") @@ -690,7 +690,7 @@ func TestForIssue23387(t *testing.T) { require.NoError(t, err) se := CreateSessionAndSetID(t, store) - se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890")) + se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890"), nil) mustExec(t, se, "create user quatest") dom.Close() // Upgrade to a newer version, check the user's privilege. @@ -700,7 +700,7 @@ func TestForIssue23387(t *testing.T) { defer dom.Close() se = CreateSessionAndSetID(t, store) - se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890")) + se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890"), nil) rs, err := exec(se, "show grants for quatest") require.NoError(t, err) rows, err := ResultSetToStringSlice(context.Background(), se, rs) diff --git a/session/session.go b/session/session.go index eadb7644a5b7a..b4e08b4379e32 100644 --- a/session/session.go +++ b/session/session.go @@ -66,6 +66,7 @@ import ( plannercore "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/plugin" "github.com/pingcap/tidb/privilege" + "github.com/pingcap/tidb/privilege/conn" "github.com/pingcap/tidb/privilege/privileges" session_metrics "github.com/pingcap/tidb/session/metrics" "github.com/pingcap/tidb/session/txninfo" @@ -148,7 +149,7 @@ type Session interface { SetCollation(coID int) error SetSessionManager(util.SessionManager) Close() - Auth(user *auth.UserIdentity, auth, salt []byte) error + Auth(user *auth.UserIdentity, auth, salt []byte, authConn conn.AuthConn) error AuthWithoutVerification(user *auth.UserIdentity) bool AuthPluginForUser(user *auth.UserIdentity) (string, error) MatchIdentity(username, remoteHost string) (*auth.UserIdentity, error) @@ -2613,7 +2614,7 @@ func (s *session) AuthPluginForUser(user *auth.UserIdentity) (string, error) { // Auth validates a user using an authentication string and salt. // If the password fails, it will keep trying other users until exhausted. // This means it can not be refactored to use MatchIdentity yet. -func (s *session) Auth(user *auth.UserIdentity, authentication, salt []byte) error { +func (s *session) Auth(user *auth.UserIdentity, authentication, salt []byte, authConn conn.AuthConn) error { hasPassword := "YES" if len(authentication) == 0 { hasPassword = "NO" @@ -2656,7 +2657,7 @@ func (s *session) Auth(user *auth.UserIdentity, authentication, salt []byte) err } } - info, err := pm.ConnectionVerification(user, authUser.Username, authUser.Hostname, authentication, salt, s.sessionVars) + info, err := pm.ConnectionVerification(user, authUser.Username, authUser.Hostname, authentication, salt, s.sessionVars, authConn) if err != nil { if info.FailedDueToWrongPassword { // when user enables the account locking function for consecutive login failures, diff --git a/session/sessiontest/session_test.go b/session/sessiontest/session_test.go index eb6314411a21e..cccfb26ca7432 100644 --- a/session/sessiontest/session_test.go +++ b/session/sessiontest/session_test.go @@ -235,8 +235,8 @@ func TestAutoCommitRespectsReadOnly(t *testing.T) { var wg sync.WaitGroup tk1 := testkit.NewTestKit(t, store) tk2 := testkit.NewTestKit(t, store) - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk1.MustExec("create table test.auto_commit_test (a int)") wg.Add(1) @@ -850,11 +850,11 @@ func TestSkipWithGrant(t *testing.T) { save2 := privileges.SkipWithGrant privileges.SkipWithGrant = false - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "user_not_exist"}, []byte("yyy"), []byte("zzz"))) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "user_not_exist"}, []byte("yyy"), []byte("zzz"), nil)) privileges.SkipWithGrant = true - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: `%`}, []byte("yyy"), []byte("zzz"))) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, []byte(""), []byte(""))) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: `%`}, []byte("yyy"), []byte("zzz"), nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, []byte(""), []byte(""), nil)) tk.MustExec("use test") tk.MustExec("create table t (id int)") tk.MustExec("create role r_1") @@ -1716,14 +1716,14 @@ func TestGrantViewRelated(t *testing.T) { tkRoot.MustExec("use test") tkUser.MustExec("use test") - tkRoot.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tkRoot.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tkRoot.MustExec("create table if not exists t (a int)") tkRoot.MustExec("create view v_version29 as select * from t") tkRoot.MustExec("create user 'u_version29'@'%'") tkRoot.MustExec("grant select on t to u_version29@'%'") - tkUser.Session().Auth(&auth.UserIdentity{Username: "u_version29", Hostname: "localhost", CurrentUser: true, AuthUsername: "u_version29", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tkUser.Session().Auth(&auth.UserIdentity{Username: "u_version29", Hostname: "localhost", CurrentUser: true, AuthUsername: "u_version29", AuthHostname: "%"}, nil, []byte("012345678901234567890"), nil) tkUser.MustQuery("select current_user();").Check(testkit.Rows("u_version29@%")) require.Error(t, tkUser.ExecToErr("select * from test.v_version29;")) @@ -1797,7 +1797,7 @@ func TestUpdatePrivilege(t *testing.T) { tk1 := testkit.NewTestKit(t, store) tk1.MustExec("use test") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: "localhost"}, []byte(""), []byte(""))) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: "localhost"}, []byte(""), []byte(""), nil)) tk1.MustMatchErrMsg("update t2 set id = 666 where id = 1;", "privilege check.*") @@ -1811,7 +1811,7 @@ func TestUpdatePrivilege(t *testing.T) { tk.MustExec("create table tb_wehub_server (id int, active_count int, used_count int)") tk.MustExec("create user 'weperk'") tk.MustExec("grant all privileges on weperk.* to 'weperk'@'%'") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "weperk", Hostname: "%"}, []byte(""), []byte(""))) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "weperk", Hostname: "%"}, []byte(""), []byte(""), nil)) tk1.MustExec("use weperk") tk1.MustExec("update tb_wehub_server a set a.active_count=a.active_count+1,a.used_count=a.used_count+1 where id=1") @@ -1847,7 +1847,7 @@ and s.b !='xx';`) tk.MustExec("insert into tp.record (id,name,age) values (1,'john',18),(2,'lary',19),(3,'lily',18)") tk.MustExec("create table ap.record( id int,name varchar(128),age int)") tk.MustExec("insert into ap.record(id) values(1)") - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: "localhost"}, []byte(""), []byte(""))) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "xxx", Hostname: "localhost"}, []byte(""), []byte(""), nil)) tk1.MustExec("update ap.record t inner join tp.record tt on t.id=tt.id set t.name=tt.name") } @@ -3437,7 +3437,7 @@ func TestSessionAuth(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "Any not exist username with zero password!", Hostname: "anyhost"}, []byte(""), []byte(""))) + require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "Any not exist username with zero password!", Hostname: "anyhost"}, []byte(""), []byte(""), nil)) } func TestLastInsertID(t *testing.T) { diff --git a/sessionctx/variable/BUILD.bazel b/sessionctx/variable/BUILD.bazel index c2404e630bef1..7429412894e20 100644 --- a/sessionctx/variable/BUILD.bazel +++ b/sessionctx/variable/BUILD.bazel @@ -31,6 +31,7 @@ go_library( "//parser/model", "//parser/mysql", "//parser/types", + "//privilege/privileges/ldap", "//sessionctx/sessionstates", "//sessionctx/stmtctx", "//sessionctx/variable/featuretag/disttask", diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 015d2f33b1e01..6b1e3f02f84fd 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/charset" "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/privilege/privileges/ldap" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/types" _ "github.com/pingcap/tidb/types/parser_driver" // for parser driver @@ -869,7 +870,7 @@ var defaultSysVars = []*SysVar{ return nil }}, {Scope: ScopeGlobal, Name: SkipNameResolve, Value: Off, Type: TypeBool}, - {Scope: ScopeGlobal, Name: DefaultAuthPlugin, Value: mysql.AuthNativePassword, Type: TypeEnum, PossibleValues: []string{mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password}}, + {Scope: ScopeGlobal, Name: DefaultAuthPlugin, Value: mysql.AuthNativePassword, Type: TypeEnum, PossibleValues: []string{mysql.AuthNativePassword, mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password, mysql.AuthLDAPSASL, mysql.AuthLDAPSimple}}, {Scope: ScopeGlobal, Name: TiDBPersistAnalyzeOptions, Value: BoolToOnOff(DefTiDBPersistAnalyzeOptions), Type: TypeBool, GetGlobal: func(_ context.Context, s *SessionVars) (string, error) { return BoolToOnOff(PersistAnalyzeOptions.Load()), nil @@ -2518,6 +2519,168 @@ var defaultSysVars = []*SysVar{ s.PlanCacheInvalidationOnFreshStats = TiDBOptOn(val) return nil }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLAuthMethodName, Value: DefAuthenticationLDAPSASLAuthMethodName, Type: TypeEnum, PossibleValues: []string{ldap.SASLAuthMethodSCRAMSHA1, ldap.SASLAuthMethodSCRAMSHA256, ldap.SASLAuthMethodGSSAPI}, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSASLAuthImpl.SetSASLAuthMethod(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetSASLAuthMethod(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLServerHost, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + // TODO: validate the ip/hostname + ldap.LDAPSASLAuthImpl.SetLDAPServerHost(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetLDAPServerHost(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLServerPort, Value: strconv.Itoa(DefAuthenticationLDAPSASLServerPort), Type: TypeInt, MinValue: 1, MaxValue: math.MaxUint16, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSASLAuthImpl.SetLDAPServerPort(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSASLAuthImpl.GetLDAPServerPort()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLTLS, Value: BoolToOnOff(DefAuthenticationLDAPSASLTLS), Type: TypeBool, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSASLAuthImpl.SetEnableTLS(TiDBOptOn(s)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return BoolToOnOff(ldap.LDAPSASLAuthImpl.GetEnableTLS()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLCAPath, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + return ldap.LDAPSASLAuthImpl.SetCAPath(s) + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetCAPath(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLUserSearchAttr, Value: DefAuthenticationLDAPSASLUserSearchAttr, Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + // TODO: validate the ip/hostname + ldap.LDAPSASLAuthImpl.SetSearchAttr(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetSearchAttr(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLBindBaseDN, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSASLAuthImpl.SetBindBaseDN(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetBindBaseDN(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLBindRootDN, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSASLAuthImpl.SetBindRootDN(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetBindRootDN(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLBindRootPW, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSASLAuthImpl.SetBindRootPW(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSASLAuthImpl.GetBindRootPW(), nil + }}, + // TODO: allow setting init_pool_size to 0 to disable pooling + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLInitPoolSize, Value: strconv.Itoa(DefAuthenticationLDAPSASLInitPoolSize), Type: TypeInt, MinValue: 1, MaxValue: 32767, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSASLAuthImpl.SetInitCapacity(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSASLAuthImpl.GetInitCapacity()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSASLMaxPoolSize, Value: strconv.Itoa(DefAuthenticationLDAPSASLMaxPoolSize), Type: TypeInt, MinValue: 1, MaxValue: 32767, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSASLAuthImpl.SetMaxCapacity(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSASLAuthImpl.GetMaxCapacity()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleAuthMethodName, Value: DefAuthenticationLDAPSimpleAuthMethodName, Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + s = strings.ToUpper(s) + // Only "SIMPLE" is supported + if s != "SIMPLE" { + return errors.Errorf("auth method %s is not supported", s) + } + return nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleServerHost, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + // TODO: validate the ip/hostname + ldap.LDAPSimpleAuthImpl.SetLDAPServerHost(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetLDAPServerHost(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleServerPort, Value: strconv.Itoa(DefAuthenticationLDAPSimpleServerPort), Type: TypeInt, MinValue: 1, MaxValue: math.MaxUint16, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSimpleAuthImpl.SetLDAPServerPort(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSimpleAuthImpl.GetLDAPServerPort()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleTLS, Value: BoolToOnOff(DefAuthenticationLDAPSimpleTLS), Type: TypeBool, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSimpleAuthImpl.SetEnableTLS(TiDBOptOn(s)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return BoolToOnOff(ldap.LDAPSimpleAuthImpl.GetEnableTLS()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleCAPath, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + return ldap.LDAPSimpleAuthImpl.SetCAPath(s) + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetCAPath(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleUserSearchAttr, Value: DefAuthenticationLDAPSimpleUserSearchAttr, Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + // TODO: validate the ip/hostname + ldap.LDAPSimpleAuthImpl.SetSearchAttr(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetSearchAttr(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleBindBaseDN, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSimpleAuthImpl.SetBindBaseDN(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetBindBaseDN(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleBindRootDN, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSimpleAuthImpl.SetBindRootDN(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetBindRootDN(), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleBindRootPW, Value: "", Type: TypeStr, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + ldap.LDAPSimpleAuthImpl.SetBindRootPW(s) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return ldap.LDAPSimpleAuthImpl.GetBindRootPW(), nil + }}, + // TODO: allow setting init_pool_size to 0 to disable pooling + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleInitPoolSize, Value: strconv.Itoa(DefAuthenticationLDAPSimpleInitPoolSize), Type: TypeInt, MinValue: 1, MaxValue: 32767, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSimpleAuthImpl.SetInitCapacity(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSimpleAuthImpl.GetInitCapacity()), nil + }}, + {Scope: ScopeGlobal, Name: AuthenticationLDAPSimpleMaxPoolSize, Value: strconv.Itoa(DefAuthenticationLDAPSimpleMaxPoolSize), Type: TypeInt, MinValue: 1, MaxValue: 32767, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return err + } + ldap.LDAPSimpleAuthImpl.SetMaxCapacity(int(val)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return strconv.Itoa(ldap.LDAPSimpleAuthImpl.GetMaxCapacity()), nil + }}, } func setTiFlashComputeDispatchPolicy(s *SessionVars, val string) error { diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index cd3aa1018ad77..813fd8d9e89d0 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -989,6 +989,54 @@ const ( // TiDBTTLRunningTasks limits the count of running ttl tasks. Default to 0, means 3 times the count of TiKV (or no // limitation, if the storage is not TiKV). TiDBTTLRunningTasks = "tidb_ttl_running_tasks" + // AuthenticationLDAPSASLAuthMethodName defines the authentication method used by LDAP SASL authentication plugin + AuthenticationLDAPSASLAuthMethodName = "authentication_ldap_sasl_auth_method_name" + // AuthenticationLDAPSASLCAPath defines the ca certificate to verify LDAP connection in LDAP SASL authentication plugin + AuthenticationLDAPSASLCAPath = "authentication_ldap_sasl_ca_path" + // AuthenticationLDAPSASLTLS defines whether to use TLS connection in LDAP SASL authentication plugin + AuthenticationLDAPSASLTLS = "authentication_ldap_sasl_tls" + // AuthenticationLDAPSASLServerHost defines the server host of LDAP server for LDAP SASL authentication plugin + AuthenticationLDAPSASLServerHost = "authentication_ldap_sasl_server_host" + // AuthenticationLDAPSASLServerPort defines the port of LDAP server for LDAP SASL authentication plugin + AuthenticationLDAPSASLServerPort = "authentication_ldap_sasl_server_port" + // AuthenticationLDAPSASLReferral defines whether to enable LDAP referral for LDAP SASL authentication plugin + AuthenticationLDAPSASLReferral = "authentication_ldap_sasl_referral" + // AuthenticationLDAPSASLUserSearchAttr defines the attribute of username in LDAP server + AuthenticationLDAPSASLUserSearchAttr = "authentication_ldap_sasl_user_search_attr" + // AuthenticationLDAPSASLBindBaseDN defines the `dn` to search the users in. It's used to limit the search scope of TiDB. + AuthenticationLDAPSASLBindBaseDN = "authentication_ldap_sasl_bind_base_dn" + // AuthenticationLDAPSASLBindRootDN defines the `dn` of the user to login the LDAP server and perform search. + AuthenticationLDAPSASLBindRootDN = "authentication_ldap_sasl_bind_root_dn" + // AuthenticationLDAPSASLBindRootPW defines the password of the user to login the LDAP server and perform search. + AuthenticationLDAPSASLBindRootPW = "authentication_ldap_sasl_bind_root_pw" + // AuthenticationLDAPSASLInitPoolSize defines the init size of connection pool to LDAP server for SASL plugin. + AuthenticationLDAPSASLInitPoolSize = "authentication_ldap_sasl_init_pool_size" + // AuthenticationLDAPSASLMaxPoolSize defines the max size of connection pool to LDAP server for SASL plugin. + AuthenticationLDAPSASLMaxPoolSize = "authentication_ldap_sasl_max_pool_size" + // AuthenticationLDAPSimpleAuthMethodName defines the authentication method used by LDAP Simple authentication plugin + AuthenticationLDAPSimpleAuthMethodName = "authentication_ldap_simple_auth_method_name" + // AuthenticationLDAPSimpleCAPath defines the ca certificate to verify LDAP connection in LDAP Simple authentication plugin + AuthenticationLDAPSimpleCAPath = "authentication_ldap_simple_ca_path" + // AuthenticationLDAPSimpleTLS defines whether to use TLS connection in LDAP Simple authentication plugin + AuthenticationLDAPSimpleTLS = "authentication_ldap_simple_tls" + // AuthenticationLDAPSimpleServerHost defines the server host of LDAP server for LDAP Simple authentication plugin + AuthenticationLDAPSimpleServerHost = "authentication_ldap_simple_server_host" + // AuthenticationLDAPSimpleServerPort defines the port of LDAP server for LDAP Simple authentication plugin + AuthenticationLDAPSimpleServerPort = "authentication_ldap_simple_server_port" + // AuthenticationLDAPSimpleReferral defines whether to enable LDAP referral for LDAP Simple authentication plugin + AuthenticationLDAPSimpleReferral = "authentication_ldap_simple_referral" + // AuthenticationLDAPSimpleUserSearchAttr defines the attribute of username in LDAP server + AuthenticationLDAPSimpleUserSearchAttr = "authentication_ldap_simple_user_search_attr" + // AuthenticationLDAPSimpleBindBaseDN defines the `dn` to search the users in. It's used to limit the search scope of TiDB. + AuthenticationLDAPSimpleBindBaseDN = "authentication_ldap_simple_bind_base_dn" + // AuthenticationLDAPSimpleBindRootDN defines the `dn` of the user to login the LDAP server and perform search. + AuthenticationLDAPSimpleBindRootDN = "authentication_ldap_simple_bind_root_dn" + // AuthenticationLDAPSimpleBindRootPW defines the password of the user to login the LDAP server and perform search. + AuthenticationLDAPSimpleBindRootPW = "authentication_ldap_simple_bind_root_pw" + // AuthenticationLDAPSimpleInitPoolSize defines the init size of connection pool to LDAP server for SASL plugin. + AuthenticationLDAPSimpleInitPoolSize = "authentication_ldap_simple_init_pool_size" + // AuthenticationLDAPSimpleMaxPoolSize defines the max size of connection pool to LDAP server for SASL plugin. + AuthenticationLDAPSimpleMaxPoolSize = "authentication_ldap_simple_max_pool_size" ) // TiDB intentional limits @@ -1231,43 +1279,55 @@ const ( DefTiDBServerMemoryLimitGCTrigger = 0.7 DefTiDBEnableGOGCTuner = true // DefTiDBGOGCTunerThreshold is to limit TiDBGOGCTunerThreshold. - DefTiDBGOGCTunerThreshold float64 = 0.6 - DefTiDBOptPrefixIndexSingleScan = true - DefTiDBExternalTS = 0 - DefTiDBEnableExternalTSRead = false - DefTiDBEnableReusechunk = true - DefTiDBUseAlloc = false - DefTiDBEnablePlanReplayerCapture = false - DefTiDBIndexMergeIntersectionConcurrency = ConcurrencyUnset - DefTiDBTTLJobEnable = true - DefTiDBTTLScanBatchSize = 500 - DefTiDBTTLScanBatchMaxSize = 10240 - DefTiDBTTLScanBatchMinSize = 1 - DefTiDBTTLDeleteBatchSize = 100 - DefTiDBTTLDeleteBatchMaxSize = 10240 - DefTiDBTTLDeleteBatchMinSize = 1 - DefTiDBTTLDeleteRateLimit = 0 - DefTiDBTTLRunningTasks = -1 - DefPasswordReuseHistory = 0 - DefPasswordReuseTime = 0 - DefTiDBStoreBatchSize = 4 - DefTiDBHistoricalStatsDuration = 7 * 24 * time.Hour - DefTiDBEnableHistoricalStatsForCapture = false - DefTiDBTTLJobScheduleWindowStartTime = "00:00 +0000" - DefTiDBTTLJobScheduleWindowEndTime = "23:59 +0000" - DefTiDBTTLScanWorkerCount = 4 - DefTiDBTTLDeleteWorkerCount = 4 - DefaultExchangeCompressionMode = kv.ExchangeCompressionModeUnspecified - DefTiDBEnableResourceControl = true - DefTiDBPessimisticTransactionFairLocking = false - DefTiDBEnablePlanCacheForParamLimit = true - DefTiFlashComputeDispatchPolicy = tiflashcompute.DispatchPolicyConsistentHashStr - DefTiDBEnablePlanCacheForSubquery = true - DefTiDBLoadBasedReplicaReadThreshold = time.Second - DefTiDBOptEnableLateMaterialization = true - DefTiDBOptOrderingIdxSelThresh = 0.0 - DefTiDBPlanCacheInvalidationOnFreshStats = true - DefTiDBEnableRowLevelChecksum = false + DefTiDBGOGCTunerThreshold float64 = 0.6 + DefTiDBOptPrefixIndexSingleScan = true + DefTiDBExternalTS = 0 + DefTiDBEnableExternalTSRead = false + DefTiDBEnableReusechunk = true + DefTiDBUseAlloc = false + DefTiDBEnablePlanReplayerCapture = false + DefTiDBIndexMergeIntersectionConcurrency = ConcurrencyUnset + DefTiDBTTLJobEnable = true + DefTiDBTTLScanBatchSize = 500 + DefTiDBTTLScanBatchMaxSize = 10240 + DefTiDBTTLScanBatchMinSize = 1 + DefTiDBTTLDeleteBatchSize = 100 + DefTiDBTTLDeleteBatchMaxSize = 10240 + DefTiDBTTLDeleteBatchMinSize = 1 + DefTiDBTTLDeleteRateLimit = 0 + DefTiDBTTLRunningTasks = -1 + DefPasswordReuseHistory = 0 + DefPasswordReuseTime = 0 + DefTiDBStoreBatchSize = 4 + DefTiDBHistoricalStatsDuration = 7 * 24 * time.Hour + DefTiDBEnableHistoricalStatsForCapture = false + DefTiDBTTLJobScheduleWindowStartTime = "00:00 +0000" + DefTiDBTTLJobScheduleWindowEndTime = "23:59 +0000" + DefTiDBTTLScanWorkerCount = 4 + DefTiDBTTLDeleteWorkerCount = 4 + DefaultExchangeCompressionMode = kv.ExchangeCompressionModeUnspecified + DefTiDBEnableResourceControl = true + DefTiDBPessimisticTransactionFairLocking = false + DefTiDBEnablePlanCacheForParamLimit = true + DefTiFlashComputeDispatchPolicy = tiflashcompute.DispatchPolicyConsistentHashStr + DefTiDBEnablePlanCacheForSubquery = true + DefTiDBLoadBasedReplicaReadThreshold = time.Second + DefTiDBOptEnableLateMaterialization = true + DefTiDBOptOrderingIdxSelThresh = 0.0 + DefTiDBPlanCacheInvalidationOnFreshStats = true + DefTiDBEnableRowLevelChecksum = false + DefAuthenticationLDAPSASLAuthMethodName = "SCRAM-SHA-1" + DefAuthenticationLDAPSASLServerPort = 389 + DefAuthenticationLDAPSASLTLS = false + DefAuthenticationLDAPSASLUserSearchAttr = "uid" + DefAuthenticationLDAPSASLInitPoolSize = 10 + DefAuthenticationLDAPSASLMaxPoolSize = 1000 + DefAuthenticationLDAPSimpleAuthMethodName = "SIMPLE" + DefAuthenticationLDAPSimpleServerPort = 389 + DefAuthenticationLDAPSimpleTLS = false + DefAuthenticationLDAPSimpleUserSearchAttr = "uid" + DefAuthenticationLDAPSimpleInitPoolSize = 10 + DefAuthenticationLDAPSimpleMaxPoolSize = 1000 ) // Process global variables. diff --git a/sessiontxn/staleread/externalts_test.go b/sessiontxn/staleread/externalts_test.go index 2ee7c6f14f767..a0bd0b81a938c 100644 --- a/sessiontxn/staleread/externalts_test.go +++ b/sessiontxn/staleread/externalts_test.go @@ -61,7 +61,7 @@ func TestExternalTimestampRead(t *testing.T) { func TestExternalTimestampReadonly(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t (id INT NOT NULL,PRIMARY KEY (id))") @@ -88,7 +88,7 @@ func TestExternalTimestampReadonly(t *testing.T) { func TestExternalTimestampReadWithTransaction(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t (id INT NOT NULL,PRIMARY KEY (id))") @@ -122,7 +122,7 @@ func TestExternalTimestampReadWithTransaction(t *testing.T) { func TestExternalTimestampNotAffectPrepare(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t (id INT NOT NULL,PRIMARY KEY (id))") diff --git a/table/tables/cache_test.go b/table/tables/cache_test.go index c20d98cafc921..2560ea834fefc 100644 --- a/table/tables/cache_test.go +++ b/table/tables/cache_test.go @@ -472,7 +472,7 @@ func TestCacheTableWriteOperatorWaitLockLease(t *testing.T) { // This line is a hack, if auth user string is "", the statement summary is skipped, // so it's added to make the later code been covered. - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost"}, nil, nil, nil)) tk.MustExec("drop table if exists wait_tb1") tk.MustExec("create table wait_tb1(id int)") diff --git a/table/tables/tables_test.go b/table/tables/tables_test.go index 5d857d5adedfb..3a8140f43ca79 100644 --- a/table/tables/tables_test.go +++ b/table/tables/tables_test.go @@ -711,7 +711,7 @@ func TestConstraintCheckForUniqueIndex(t *testing.T) { func TestViewColumns(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int primary key, b varchar(20))") @@ -768,7 +768,7 @@ func TestTxnAssertion(t *testing.T) { se, err := session.CreateSession4Test(store) se.SetConnectionID(1) require.NoError(t, err) - require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk := testkit.NewTestKit(t, store) tk.SetSession(se) diff --git a/table/temptable/intergration_test.go b/table/temptable/intergration_test.go index 1403dc60788a0..c3836a5f79096 100644 --- a/table/temptable/intergration_test.go +++ b/table/temptable/intergration_test.go @@ -26,7 +26,7 @@ func TestSelectTemporaryTableUnionView(t *testing.T) { // see the issue: https://github.com/pingcap/tidb/issues/42563 store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk.MustExec("use test") tk.MustExec("create table t(a int)") tk.MustExec("insert into t values(1)") diff --git a/tests/realtikvtest/pessimistictest/pessimistic_test.go b/tests/realtikvtest/pessimistictest/pessimistic_test.go index d297eedad65bc..bcde6d9cbe19e 100644 --- a/tests/realtikvtest/pessimistictest/pessimistic_test.go +++ b/tests/realtikvtest/pessimistictest/pessimistic_test.go @@ -203,7 +203,7 @@ func TestDeadlock(t *testing.T) { // Use the root user so that the statements can be recorded into statements_summary table, which is necessary // for fetching - require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk1.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk1.MustExec("drop table if exists deadlock") tk1.MustExec("create table deadlock (k int primary key, v int)") tk1.MustExec("insert into deadlock values (1, 1), (2, 1)") @@ -212,7 +212,7 @@ func TestDeadlock(t *testing.T) { ts1, err := strconv.ParseUint(tk1.MustQuery("select @@tidb_current_ts").Rows()[0][0].(string), 10, 64) require.NoError(t, err) - require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk2.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) tk2.MustExec("begin pessimistic") ts2, err := strconv.ParseUint(tk2.MustQuery("select @@tidb_current_ts").Rows()[0][0].(string), 10, 64) require.NoError(t, err) diff --git a/util/stmtsummary/v2/tests/table_test.go b/util/stmtsummary/v2/tests/table_test.go index e91df486fcc5f..2f1dbf363e4d5 100644 --- a/util/stmtsummary/v2/tests/table_test.go +++ b/util/stmtsummary/v2/tests/table_test.go @@ -241,7 +241,7 @@ func TestStmtSummaryTablePrivilege(t *testing.T) { Hostname: "localhost", AuthUsername: "test_user", AuthHostname: "localhost", - }, nil, nil) + }, nil, nil, nil) result = tk1.MustQuery("select * from information_schema.statements_summary where digest_text like 'select * from `t`%'") // Ordinary users can not see others' records @@ -299,7 +299,7 @@ func TestCapturePrivilege(t *testing.T) { Hostname: "localhost", AuthUsername: "test_user", AuthHostname: "localhost", - }, nil, nil) + }, nil, nil, nil) rows = tk1.MustQuery("show global bindings").Rows() // Ordinary users can not see others' records @@ -535,7 +535,7 @@ func newTestKit(t *testing.T, store kv.Storage) *testkit.TestKit { func newTestKitWithRoot(t *testing.T, store kv.Storage) *testkit.TestKit { tk := newTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk } @@ -547,7 +547,7 @@ func newTestKitWithPlanCache(t *testing.T, store kv.Storage) *testkit.TestKit { require.NoError(t, err) tk.SetSession(se) tk.RefreshConnectionID() - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) return tk }