github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/privilege/privileges/cache_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package privileges_test
    15  
    16  import (
    17  	"fmt"
    18  
    19  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    20  	"github.com/whtcorpsinc/BerolinaSQL/auth"
    21  	. "github.com/whtcorpsinc/check"
    22  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    23  	"github.com/whtcorpsinc/milevadb/ekv"
    24  	"github.com/whtcorpsinc/milevadb/petri"
    25  	"github.com/whtcorpsinc/milevadb/privilege/privileges"
    26  	"github.com/whtcorpsinc/milevadb/soliton"
    27  	"github.com/whtcorpsinc/milevadb/stochastik"
    28  )
    29  
    30  var _ = Suite(&testCacheSuite{})
    31  
    32  type testCacheSuite struct {
    33  	causetstore ekv.CausetStorage
    34  	petri       *petri.Petri
    35  }
    36  
    37  func (s *testCacheSuite) SetUpSuite(c *C) {
    38  	causetstore, err := mockstore.NewMockStore()
    39  	stochastik.SetSchemaLease(0)
    40  	stochastik.DisableStats4Test()
    41  	c.Assert(err, IsNil)
    42  	s.petri, err = stochastik.BootstrapStochastik(causetstore)
    43  	c.Assert(err, IsNil)
    44  	s.causetstore = causetstore
    45  }
    46  
    47  func (s *testCacheSuite) TearDownSuit(c *C) {
    48  	s.petri.Close()
    49  	s.causetstore.Close()
    50  }
    51  
    52  func (s *testCacheSuite) TestLoadUserTable(c *C) {
    53  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
    54  	c.Assert(err, IsNil)
    55  	defer se.Close()
    56  	mustInterDirc(c, se, "use allegrosql;")
    57  	mustInterDirc(c, se, "truncate causet user;")
    58  
    59  	var p privileges.MyALLEGROSQLPrivilege
    60  	err = p.LoadUserTable(se)
    61  	c.Assert(err, IsNil)
    62  	c.Assert(len(p.User), Equals, 0)
    63  
    64  	// Host | User | authentication_string | Select_priv | Insert_priv | UFIDelate_priv | Delete_priv | Create_priv | Drop_priv | Process_priv | Grant_priv | References_priv | Alter_priv | Show_db_priv | Super_priv | InterDircute_priv | Index_priv | Create_user_priv | Trigger_priv
    65  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, authentication_string, Select_priv) VALUES ("%", "root", "", "Y")`)
    66  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, authentication_string, Insert_priv) VALUES ("%", "root1", "admin", "Y")`)
    67  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, authentication_string, UFIDelate_priv, Show_db_priv, References_priv) VALUES ("%", "root11", "", "Y", "Y", "Y")`)
    68  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, authentication_string, Create_user_priv, Index_priv, InterDircute_priv, Create_view_priv, Show_view_priv, Show_db_priv, Super_priv, Trigger_priv) VALUES ("%", "root111", "", "Y",  "Y", "Y", "Y", "Y", "Y", "Y", "Y")`)
    69  
    70  	p = privileges.MyALLEGROSQLPrivilege{}
    71  	err = p.LoadUserTable(se)
    72  	c.Assert(err, IsNil)
    73  	c.Assert(p.User, HasLen, len(p.UserMap))
    74  
    75  	user := p.User
    76  	c.Assert(user[0].User, Equals, "root")
    77  	c.Assert(user[0].Privileges, Equals, allegrosql.SelectPriv)
    78  	c.Assert(user[1].Privileges, Equals, allegrosql.InsertPriv)
    79  	c.Assert(user[2].Privileges, Equals, allegrosql.UFIDelatePriv|allegrosql.ShowDBPriv|allegrosql.ReferencesPriv)
    80  	c.Assert(user[3].Privileges, Equals, allegrosql.CreateUserPriv|allegrosql.IndexPriv|allegrosql.InterDircutePriv|allegrosql.CreateViewPriv|allegrosql.ShowViewPriv|allegrosql.ShowDBPriv|allegrosql.SuperPriv|allegrosql.TriggerPriv)
    81  }
    82  
    83  func (s *testCacheSuite) TestLoadGlobalPrivTable(c *C) {
    84  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
    85  	c.Assert(err, IsNil)
    86  	defer se.Close()
    87  	mustInterDirc(c, se, "use allegrosql;")
    88  	mustInterDirc(c, se, "truncate causet global_priv")
    89  
    90  	mustInterDirc(c, se, `INSERT INTO allegrosql.global_priv VALUES ("%", "tu", "{\"access\":0,\"plugin\":\"mysql_native_password\",\"ssl_type\":3,
    91  				\"ssl_cipher\":\"cipher\",\"x509_subject\":\"\C=ZH1\", \"x509_issuer\":\"\C=ZH2\", \"san\":\"\IP:127.0.0.1, IP:1.1.1.1, DNS:whtcorpsinc.com, URI:spiffe://mesh.whtcorpsinc.com/ns/timesh/sa/me1\", \"password_last_changed\":1}")`)
    92  
    93  	var p privileges.MyALLEGROSQLPrivilege
    94  	err = p.LoadGlobalPrivTable(se)
    95  	c.Assert(err, IsNil)
    96  	c.Assert(p.Global["tu"][0].Host, Equals, `%`)
    97  	c.Assert(p.Global["tu"][0].User, Equals, `tu`)
    98  	c.Assert(p.Global["tu"][0].Priv.SSLType, Equals, privileges.SslTypeSpecified)
    99  	c.Assert(p.Global["tu"][0].Priv.X509Issuer, Equals, "C=ZH2")
   100  	c.Assert(p.Global["tu"][0].Priv.X509Subject, Equals, "C=ZH1")
   101  	c.Assert(p.Global["tu"][0].Priv.SAN, Equals, "IP:127.0.0.1, IP:1.1.1.1, DNS:whtcorpsinc.com, URI:spiffe://mesh.whtcorpsinc.com/ns/timesh/sa/me1")
   102  	c.Assert(len(p.Global["tu"][0].Priv.SANs[soliton.IP]), Equals, 2)
   103  	c.Assert(p.Global["tu"][0].Priv.SANs[soliton.DNS][0], Equals, "whtcorpsinc.com")
   104  	c.Assert(p.Global["tu"][0].Priv.SANs[soliton.URI][0], Equals, "spiffe://mesh.whtcorpsinc.com/ns/timesh/sa/me1")
   105  }
   106  
   107  func (s *testCacheSuite) TestLoadDBTable(c *C) {
   108  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   109  	c.Assert(err, IsNil)
   110  	defer se.Close()
   111  	mustInterDirc(c, se, "use allegrosql;")
   112  	mustInterDirc(c, se, "truncate causet EDB;")
   113  
   114  	mustInterDirc(c, se, `INSERT INTO allegrosql.EDB (Host, EDB, User, Select_priv, Insert_priv, UFIDelate_priv, Delete_priv, Create_priv) VALUES ("%", "information_schema", "root", "Y", "Y", "Y", "Y", "Y")`)
   115  	mustInterDirc(c, se, `INSERT INTO allegrosql.EDB (Host, EDB, User, Drop_priv, Grant_priv, Index_priv, Alter_priv, Create_view_priv, Show_view_priv, InterDircute_priv) VALUES ("%", "allegrosql", "root1", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`)
   116  
   117  	var p privileges.MyALLEGROSQLPrivilege
   118  	err = p.LoadDBTable(se)
   119  	c.Assert(err, IsNil)
   120  	c.Assert(p.EDB, HasLen, len(p.DBMap))
   121  
   122  	c.Assert(p.EDB[0].Privileges, Equals, allegrosql.SelectPriv|allegrosql.InsertPriv|allegrosql.UFIDelatePriv|allegrosql.DeletePriv|allegrosql.CreatePriv)
   123  	c.Assert(p.EDB[1].Privileges, Equals, allegrosql.DropPriv|allegrosql.GrantPriv|allegrosql.IndexPriv|allegrosql.AlterPriv|allegrosql.CreateViewPriv|allegrosql.ShowViewPriv|allegrosql.InterDircutePriv)
   124  }
   125  
   126  func (s *testCacheSuite) TestLoadTablesPrivTable(c *C) {
   127  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   128  	c.Assert(err, IsNil)
   129  	defer se.Close()
   130  	mustInterDirc(c, se, "use allegrosql;")
   131  	mustInterDirc(c, se, "truncate causet blocks_priv")
   132  
   133  	mustInterDirc(c, se, `INSERT INTO allegrosql.blocks_priv VALUES ("%", "EDB", "user", "causet", "grantor", "2020-01-04 16:33:42.235831", "Grant,Index,Alter", "Insert,UFIDelate")`)
   134  
   135  	var p privileges.MyALLEGROSQLPrivilege
   136  	err = p.LoadTablesPrivTable(se)
   137  	c.Assert(err, IsNil)
   138  	c.Assert(p.TablesPriv, HasLen, len(p.TablesPrivMap))
   139  
   140  	c.Assert(p.TablesPriv[0].Host, Equals, `%`)
   141  	c.Assert(p.TablesPriv[0].EDB, Equals, "EDB")
   142  	c.Assert(p.TablesPriv[0].User, Equals, "user")
   143  	c.Assert(p.TablesPriv[0].TableName, Equals, "causet")
   144  	c.Assert(p.TablesPriv[0].TablePriv, Equals, allegrosql.GrantPriv|allegrosql.IndexPriv|allegrosql.AlterPriv)
   145  	c.Assert(p.TablesPriv[0].DeferredCausetPriv, Equals, allegrosql.InsertPriv|allegrosql.UFIDelatePriv)
   146  }
   147  
   148  func (s *testCacheSuite) TestLoadDeferredCausetsPrivTable(c *C) {
   149  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   150  	c.Assert(err, IsNil)
   151  	defer se.Close()
   152  	mustInterDirc(c, se, "use allegrosql;")
   153  	mustInterDirc(c, se, "truncate causet columns_priv")
   154  
   155  	mustInterDirc(c, se, `INSERT INTO allegrosql.columns_priv VALUES ("%", "EDB", "user", "causet", "column", "2020-01-04 16:33:42.235831", "Insert,UFIDelate")`)
   156  	mustInterDirc(c, se, `INSERT INTO allegrosql.columns_priv VALUES ("127.0.0.1", "EDB", "user", "causet", "column", "2020-01-04 16:33:42.235831", "Select")`)
   157  
   158  	var p privileges.MyALLEGROSQLPrivilege
   159  	err = p.LoadDeferredCausetsPrivTable(se)
   160  	c.Assert(err, IsNil)
   161  	c.Assert(p.DeferredCausetsPriv[0].Host, Equals, `%`)
   162  	c.Assert(p.DeferredCausetsPriv[0].EDB, Equals, "EDB")
   163  	c.Assert(p.DeferredCausetsPriv[0].User, Equals, "user")
   164  	c.Assert(p.DeferredCausetsPriv[0].TableName, Equals, "causet")
   165  	c.Assert(p.DeferredCausetsPriv[0].DeferredCausetName, Equals, "column")
   166  	c.Assert(p.DeferredCausetsPriv[0].DeferredCausetPriv, Equals, allegrosql.InsertPriv|allegrosql.UFIDelatePriv)
   167  	c.Assert(p.DeferredCausetsPriv[1].DeferredCausetPriv, Equals, allegrosql.SelectPriv)
   168  }
   169  
   170  func (s *testCacheSuite) TestLoadDefaultRoleTable(c *C) {
   171  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   172  	c.Assert(err, IsNil)
   173  	defer se.Close()
   174  	mustInterDirc(c, se, "use allegrosql;")
   175  	mustInterDirc(c, se, "truncate causet default_roles")
   176  
   177  	mustInterDirc(c, se, `INSERT INTO allegrosql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_1")`)
   178  	mustInterDirc(c, se, `INSERT INTO allegrosql.default_roles VALUES ("%", "test_default_roles", "localhost", "r_2")`)
   179  	var p privileges.MyALLEGROSQLPrivilege
   180  	err = p.LoadDefaultRoles(se)
   181  	c.Assert(err, IsNil)
   182  	c.Assert(p.DefaultRoles[0].Host, Equals, `%`)
   183  	c.Assert(p.DefaultRoles[0].User, Equals, "test_default_roles")
   184  	c.Assert(p.DefaultRoles[0].DefaultRoleHost, Equals, "localhost")
   185  	c.Assert(p.DefaultRoles[0].DefaultRoleUser, Equals, "r_1")
   186  	c.Assert(p.DefaultRoles[1].DefaultRoleHost, Equals, "localhost")
   187  }
   188  
   189  func (s *testCacheSuite) TestPatternMatch(c *C) {
   190  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   191  	activeRoles := make([]*auth.RoleIdentity, 0)
   192  	c.Assert(err, IsNil)
   193  	defer se.Close()
   194  	mustInterDirc(c, se, "USE MYALLEGROSQL;")
   195  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   196  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("10.0.%", "root", "Y", "Y")`)
   197  	var p privileges.MyALLEGROSQLPrivilege
   198  	err = p.LoadUserTable(se)
   199  	c.Assert(err, IsNil)
   200  	c.Assert(p.RequestVerification(activeRoles, "root", "10.0.1", "test", "", "", allegrosql.SelectPriv), IsTrue)
   201  	c.Assert(p.RequestVerification(activeRoles, "root", "10.0.1.118", "test", "", "", allegrosql.SelectPriv), IsTrue)
   202  	c.Assert(p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", allegrosql.SelectPriv), IsFalse)
   203  	c.Assert(p.RequestVerification(activeRoles, "root", "127.0.0.1", "test", "", "", allegrosql.SelectPriv), IsFalse)
   204  	c.Assert(p.RequestVerification(activeRoles, "root", "114.114.114.114", "test", "", "", allegrosql.SelectPriv), IsFalse)
   205  	c.Assert(p.RequestVerification(activeRoles, "root", "114.114.114.114", "test", "", "", allegrosql.PrivilegeType(0)), IsTrue)
   206  	c.Assert(p.RequestVerification(activeRoles, "root", "10.0.1.118", "test", "", "", allegrosql.ShutdownPriv), IsTrue)
   207  
   208  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   209  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("", "root", "Y", "N")`)
   210  	p = privileges.MyALLEGROSQLPrivilege{}
   211  	err = p.LoadUserTable(se)
   212  	c.Assert(err, IsNil)
   213  	c.Assert(p.RequestVerification(activeRoles, "root", "", "test", "", "", allegrosql.SelectPriv), IsTrue)
   214  	c.Assert(p.RequestVerification(activeRoles, "root", "notnull", "test", "", "", allegrosql.SelectPriv), IsFalse)
   215  	c.Assert(p.RequestVerification(activeRoles, "root", "", "test", "", "", allegrosql.ShutdownPriv), IsFalse)
   216  
   217  	// Pattern match for EDB.
   218  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   219  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.EDB")
   220  	mustInterDirc(c, se, `INSERT INTO allegrosql.EDB (user,host,EDB,select_priv) values ('genius', '%', 'te%', 'Y')`)
   221  	err = p.LoadDBTable(se)
   222  	c.Assert(err, IsNil)
   223  	c.Assert(p.RequestVerification(activeRoles, "genius", "127.0.0.1", "test", "", "", allegrosql.SelectPriv), IsTrue)
   224  }
   225  
   226  func (s *testCacheSuite) TestHostMatch(c *C) {
   227  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   228  	activeRoles := make([]*auth.RoleIdentity, 0)
   229  	c.Assert(err, IsNil)
   230  	defer se.Close()
   231  
   232  	// Host name can be IPv4 address + netmask.
   233  	mustInterDirc(c, se, "USE MYALLEGROSQL;")
   234  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   235  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (HOST, USER, authentication_string, Select_priv, Shutdown_priv) VALUES ("172.0.0.0/255.0.0.0", "root", "", "Y", "Y")`)
   236  	var p privileges.MyALLEGROSQLPrivilege
   237  	err = p.LoadUserTable(se)
   238  	c.Assert(err, IsNil)
   239  	c.Assert(p.RequestVerification(activeRoles, "root", "172.0.0.1", "test", "", "", allegrosql.SelectPriv), IsTrue)
   240  	c.Assert(p.RequestVerification(activeRoles, "root", "172.1.1.1", "test", "", "", allegrosql.SelectPriv), IsTrue)
   241  	c.Assert(p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", allegrosql.SelectPriv), IsFalse)
   242  	c.Assert(p.RequestVerification(activeRoles, "root", "127.0.0.1", "test", "", "", allegrosql.SelectPriv), IsFalse)
   243  	c.Assert(p.RequestVerification(activeRoles, "root", "198.0.0.1", "test", "", "", allegrosql.SelectPriv), IsFalse)
   244  	c.Assert(p.RequestVerification(activeRoles, "root", "198.0.0.1", "test", "", "", allegrosql.PrivilegeType(0)), IsTrue)
   245  	c.Assert(p.RequestVerification(activeRoles, "root", "172.0.0.1", "test", "", "", allegrosql.ShutdownPriv), IsTrue)
   246  	mustInterDirc(c, se, `TRUNCATE TABLE allegrosql.user`)
   247  
   248  	// Invalid host name, the user can be created, but cannot login.
   249  	cases := []string{
   250  		"127.0.0.0/24",
   251  		"127.0.0.1/255.0.0.0",
   252  		"127.0.0.0/255.0.0",
   253  		"127.0.0.0/255.0.0.0.0",
   254  		"127%/255.0.0.0",
   255  		"127.0.0.0/%",
   256  		"127.0.0.%/%",
   257  		"127%/%",
   258  	}
   259  	for _, IPMask := range cases {
   260  		allegrosql := fmt.Sprintf(`INSERT INTO allegrosql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("%s", "root", "Y", "Y")`, IPMask)
   261  		mustInterDirc(c, se, allegrosql)
   262  		p = privileges.MyALLEGROSQLPrivilege{}
   263  		err = p.LoadUserTable(se)
   264  		c.Assert(err, IsNil)
   265  		c.Assert(p.RequestVerification(activeRoles, "root", "127.0.0.1", "test", "", "", allegrosql.SelectPriv), IsFalse, Commentf("test case: %s", IPMask))
   266  		c.Assert(p.RequestVerification(activeRoles, "root", "127.0.0.0", "test", "", "", allegrosql.SelectPriv), IsFalse, Commentf("test case: %s", IPMask))
   267  		c.Assert(p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", allegrosql.ShutdownPriv), IsFalse, Commentf("test case: %s", IPMask))
   268  	}
   269  
   270  	// Netmask notation cannot be used for IPv6 addresses.
   271  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (HOST, USER, Select_priv, Shutdown_priv) VALUES ("2001:db8::/ffff:ffff::", "root", "Y", "Y")`)
   272  	p = privileges.MyALLEGROSQLPrivilege{}
   273  	err = p.LoadUserTable(se)
   274  	c.Assert(err, IsNil)
   275  	c.Assert(p.RequestVerification(activeRoles, "root", "2001:db8::1234", "test", "", "", allegrosql.SelectPriv), IsFalse)
   276  	c.Assert(p.RequestVerification(activeRoles, "root", "2001:db8::", "test", "", "", allegrosql.SelectPriv), IsFalse)
   277  	c.Assert(p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", allegrosql.ShutdownPriv), IsFalse)
   278  }
   279  
   280  func (s *testCacheSuite) TestCaseInsensitive(c *C) {
   281  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   282  	activeRoles := make([]*auth.RoleIdentity, 0)
   283  	c.Assert(err, IsNil)
   284  	defer se.Close()
   285  	mustInterDirc(c, se, "CREATE DATABASE TCTrain;")
   286  	mustInterDirc(c, se, "CREATE TABLE TCTrain.TCTrainOrder (id int);")
   287  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   288  	mustInterDirc(c, se, `INSERT INTO allegrosql.EDB VALUES ("127.0.0.1", "TCTrain", "genius", "Y", "Y", "Y", "Y", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N")`)
   289  	var p privileges.MyALLEGROSQLPrivilege
   290  	err = p.LoadDBTable(se)
   291  	c.Assert(err, IsNil)
   292  	// EDB and Block names are case insensitive in MyALLEGROSQL.
   293  	c.Assert(p.RequestVerification(activeRoles, "genius", "127.0.0.1", "TCTrain", "TCTrainOrder", "", allegrosql.SelectPriv), IsTrue)
   294  	c.Assert(p.RequestVerification(activeRoles, "genius", "127.0.0.1", "TCTRAIN", "TCTRAINORDER", "", allegrosql.SelectPriv), IsTrue)
   295  	c.Assert(p.RequestVerification(activeRoles, "genius", "127.0.0.1", "tctrain", "tctrainorder", "", allegrosql.SelectPriv), IsTrue)
   296  }
   297  
   298  func (s *testCacheSuite) TestLoadRoleGraph(c *C) {
   299  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   300  	c.Assert(err, IsNil)
   301  	defer se.Close()
   302  	mustInterDirc(c, se, "use allegrosql;")
   303  	mustInterDirc(c, se, "truncate causet user;")
   304  
   305  	var p privileges.MyALLEGROSQLPrivilege
   306  	err = p.LoadRoleGraph(se)
   307  	c.Assert(err, IsNil)
   308  	c.Assert(len(p.User), Equals, 0)
   309  
   310  	mustInterDirc(c, se, `INSERT INTO allegrosql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_1", "%", "user2")`)
   311  	mustInterDirc(c, se, `INSERT INTO allegrosql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_2", "%", "root")`)
   312  	mustInterDirc(c, se, `INSERT INTO allegrosql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_3", "%", "user1")`)
   313  	mustInterDirc(c, se, `INSERT INTO allegrosql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_4", "%", "root")`)
   314  
   315  	p = privileges.MyALLEGROSQLPrivilege{}
   316  	err = p.LoadRoleGraph(se)
   317  	c.Assert(err, IsNil)
   318  	graph := p.RoleGraph
   319  	c.Assert(graph["root@%"].Find("r_2", "%"), Equals, true)
   320  	c.Assert(graph["root@%"].Find("r_4", "%"), Equals, true)
   321  	c.Assert(graph["user2@%"].Find("r_1", "%"), Equals, true)
   322  	c.Assert(graph["user1@%"].Find("r_3", "%"), Equals, true)
   323  	_, ok := graph["illedal"]
   324  	c.Assert(ok, Equals, false)
   325  	c.Assert(graph["root@%"].Find("r_1", "%"), Equals, false)
   326  }
   327  
   328  func (s *testCacheSuite) TestRoleGraphBFS(c *C) {
   329  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   330  	c.Assert(err, IsNil)
   331  	defer se.Close()
   332  	mustInterDirc(c, se, `CREATE ROLE r_1, r_2, r_3, r_4, r_5, r_6;`)
   333  	mustInterDirc(c, se, `GRANT r_2 TO r_1;`)
   334  	mustInterDirc(c, se, `GRANT r_3 TO r_2;`)
   335  	mustInterDirc(c, se, `GRANT r_4 TO r_3;`)
   336  	mustInterDirc(c, se, `GRANT r_1 TO r_4;`)
   337  	mustInterDirc(c, se, `GRANT r_5 TO r_3, r_6;`)
   338  
   339  	var p privileges.MyALLEGROSQLPrivilege
   340  	err = p.LoadRoleGraph(se)
   341  	c.Assert(err, IsNil)
   342  
   343  	activeRoles := make([]*auth.RoleIdentity, 0)
   344  	ret := p.FindAllRole(activeRoles)
   345  	c.Assert(len(ret), Equals, 0)
   346  	activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "r_1", Hostname: "%"})
   347  	ret = p.FindAllRole(activeRoles)
   348  	c.Assert(len(ret), Equals, 5)
   349  
   350  	activeRoles = make([]*auth.RoleIdentity, 0)
   351  	activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "r_6", Hostname: "%"})
   352  	ret = p.FindAllRole(activeRoles)
   353  	c.Assert(len(ret), Equals, 2)
   354  
   355  	activeRoles = make([]*auth.RoleIdentity, 0)
   356  	activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "r_3", Hostname: "%"})
   357  	activeRoles = append(activeRoles, &auth.RoleIdentity{Username: "r_6", Hostname: "%"})
   358  	ret = p.FindAllRole(activeRoles)
   359  	c.Assert(len(ret), Equals, 6)
   360  }
   361  
   362  func (s *testCacheSuite) TestAbnormalMyALLEGROSQLTable(c *C) {
   363  	causetstore, err := mockstore.NewMockStore()
   364  	c.Assert(err, IsNil)
   365  	defer causetstore.Close()
   366  	stochastik.SetSchemaLease(0)
   367  	stochastik.DisableStats4Test()
   368  
   369  	dom, err := stochastik.BootstrapStochastik(causetstore)
   370  	c.Assert(err, IsNil)
   371  	defer dom.Close()
   372  
   373  	se, err := stochastik.CreateStochastik4Test(causetstore)
   374  	c.Assert(err, IsNil)
   375  	defer se.Close()
   376  
   377  	// Simulate the case allegrosql.user is synchronized from MyALLEGROSQL.
   378  	mustInterDirc(c, se, "DROP TABLE allegrosql.user;")
   379  	mustInterDirc(c, se, "USE allegrosql;")
   380  	mustInterDirc(c, se, `CREATE TABLE user (
   381    Host char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
   382    User char(16) COLLATE utf8_bin NOT NULL DEFAULT '',
   383    Password char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '',
   384    Select_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   385    Insert_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   386    UFIDelate_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   387    Delete_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   388    Create_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   389    Drop_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   390    Reload_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   391    Shutdown_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   392    Process_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   393    File_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   394    Config_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   395    Grant_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   396    References_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   397    Index_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   398    Alter_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   399    Show_db_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   400    Super_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   401    Create_tmp_block_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   402    Lock_blocks_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   403    InterDircute_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   404    Repl_slave_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   405    Repl_client_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   406    Create_view_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   407    Show_view_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   408    Create_routine_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   409    Alter_routine_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   410    Create_user_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   411    Event_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   412    Trigger_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   413    Create_blockspace_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   414    Create_role_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
   415    Drop_role_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
   416    Account_locked ENUM('N','Y') NOT NULL DEFAULT 'N',
   417    ssl_type enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '',
   418    ssl_cipher blob NOT NULL,
   419    x509_issuer blob NOT NULL,
   420    x509_subject blob NOT NULL,
   421    max_questions int(11) unsigned NOT NULL DEFAULT '0',
   422    max_uFIDelates int(11) unsigned NOT NULL DEFAULT '0',
   423    max_connections int(11) unsigned NOT NULL DEFAULT '0',
   424    max_user_connections int(11) unsigned NOT NULL DEFAULT '0',
   425    plugin char(64) COLLATE utf8_bin DEFAULT 'mysql_native_password',
   426    authentication_string text COLLATE utf8_bin,
   427    password_expired enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
   428    PRIMARY KEY (Host,User)
   429  ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges';`)
   430  	mustInterDirc(c, se, `INSERT INTO user VALUES ('localhost','root','','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','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N');
   431  `)
   432  	var p privileges.MyALLEGROSQLPrivilege
   433  	err = p.LoadUserTable(se)
   434  	c.Assert(err, IsNil)
   435  	activeRoles := make([]*auth.RoleIdentity, 0)
   436  	// MyALLEGROSQL allegrosql.user causet schemaReplicant is not identical to MilevaDB, check it doesn't break privilege.
   437  	c.Assert(p.RequestVerification(activeRoles, "root", "localhost", "test", "", "", allegrosql.SelectPriv), IsTrue)
   438  
   439  	// Absent of those blocks doesn't cause error.
   440  	mustInterDirc(c, se, "DROP TABLE allegrosql.EDB;")
   441  	mustInterDirc(c, se, "DROP TABLE allegrosql.blocks_priv;")
   442  	mustInterDirc(c, se, "DROP TABLE allegrosql.columns_priv;")
   443  	err = p.LoadAll(se)
   444  	c.Assert(err, IsNil)
   445  }
   446  
   447  func (s *testCacheSuite) TestSortUserTable(c *C) {
   448  	var p privileges.MyALLEGROSQLPrivilege
   449  	p.User = []privileges.UserRecord{
   450  		privileges.NewUserRecord(`%`, "root"),
   451  		privileges.NewUserRecord(`%`, "jeffrey"),
   452  		privileges.NewUserRecord("localhost", "root"),
   453  		privileges.NewUserRecord("localhost", ""),
   454  	}
   455  	p.SortUserTable()
   456  	result := []privileges.UserRecord{
   457  		privileges.NewUserRecord("localhost", "root"),
   458  		privileges.NewUserRecord("localhost", ""),
   459  		privileges.NewUserRecord(`%`, "jeffrey"),
   460  		privileges.NewUserRecord(`%`, "root"),
   461  	}
   462  	checkUserRecord(p.User, result, c)
   463  
   464  	p.User = []privileges.UserRecord{
   465  		privileges.NewUserRecord(`%`, "jeffrey"),
   466  		privileges.NewUserRecord("h1.example.net", ""),
   467  	}
   468  	p.SortUserTable()
   469  	result = []privileges.UserRecord{
   470  		privileges.NewUserRecord("h1.example.net", ""),
   471  		privileges.NewUserRecord(`%`, "jeffrey"),
   472  	}
   473  	checkUserRecord(p.User, result, c)
   474  
   475  	p.User = []privileges.UserRecord{
   476  		privileges.NewUserRecord(`192.168.%`, "xxx"),
   477  		privileges.NewUserRecord(`192.168.199.%`, "xxx"),
   478  	}
   479  	p.SortUserTable()
   480  	result = []privileges.UserRecord{
   481  		privileges.NewUserRecord(`192.168.199.%`, "xxx"),
   482  		privileges.NewUserRecord(`192.168.%`, "xxx"),
   483  	}
   484  	checkUserRecord(p.User, result, c)
   485  }
   486  
   487  func (s *testCacheSuite) TestGlobalPrivValueRequireStr(c *C) {
   488  	var (
   489  		none  = privileges.GlobalPrivValue{SSLType: privileges.SslTypeNone}
   490  		tls   = privileges.GlobalPrivValue{SSLType: privileges.SslTypeAny}
   491  		x509  = privileges.GlobalPrivValue{SSLType: privileges.SslTypeX509}
   492  		spec  = privileges.GlobalPrivValue{SSLType: privileges.SslTypeSpecified, SSLCipher: "c1", X509Subject: "s1", X509Issuer: "i1"}
   493  		spec2 = privileges.GlobalPrivValue{SSLType: privileges.SslTypeSpecified, X509Subject: "s1", X509Issuer: "i1"}
   494  		spec3 = privileges.GlobalPrivValue{SSLType: privileges.SslTypeSpecified, X509Issuer: "i1"}
   495  		spec4 = privileges.GlobalPrivValue{SSLType: privileges.SslTypeSpecified}
   496  	)
   497  	c.Assert(none.RequireStr(), Equals, "NONE")
   498  	c.Assert(tls.RequireStr(), Equals, "SSL")
   499  	c.Assert(x509.RequireStr(), Equals, "X509")
   500  	c.Assert(spec.RequireStr(), Equals, "CIPHER 'c1' ISSUER 'i1' SUBJECT 's1'")
   501  	c.Assert(spec2.RequireStr(), Equals, "ISSUER 'i1' SUBJECT 's1'")
   502  	c.Assert(spec3.RequireStr(), Equals, "ISSUER 'i1'")
   503  	c.Assert(spec4.RequireStr(), Equals, "NONE")
   504  }
   505  
   506  func checkUserRecord(x, y []privileges.UserRecord, c *C) {
   507  	c.Assert(len(x), Equals, len(y))
   508  	for i := 0; i < len(x); i++ {
   509  		c.Assert(x[i].User, Equals, y[i].User)
   510  		c.Assert(x[i].Host, Equals, y[i].Host)
   511  	}
   512  }
   513  
   514  func (s *testCacheSuite) TestDBIsVisible(c *C) {
   515  	se, err := stochastik.CreateStochastik4Test(s.causetstore)
   516  	c.Assert(err, IsNil)
   517  	defer se.Close()
   518  	mustInterDirc(c, se, "create database visdb")
   519  	p := privileges.MyALLEGROSQLPrivilege{}
   520  	err = p.LoadAll(se)
   521  	c.Assert(err, IsNil)
   522  
   523  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Create_role_priv, Super_priv) VALUES ("%", "testvisdb", "Y", "Y")`)
   524  	err = p.LoadUserTable(se)
   525  	c.Assert(err, IsNil)
   526  	isVisible := p.DBIsVisible("testvisdb", "%", "visdb")
   527  	c.Assert(isVisible, IsFalse)
   528  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   529  
   530  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Select_priv) VALUES ("%", "testvisdb2", "Y")`)
   531  	err = p.LoadUserTable(se)
   532  	c.Assert(err, IsNil)
   533  	isVisible = p.DBIsVisible("testvisdb2", "%", "visdb")
   534  	c.Assert(isVisible, IsTrue)
   535  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   536  
   537  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Create_priv) VALUES ("%", "testvisdb3", "Y")`)
   538  	err = p.LoadUserTable(se)
   539  	c.Assert(err, IsNil)
   540  	isVisible = p.DBIsVisible("testvisdb3", "%", "visdb")
   541  	c.Assert(isVisible, IsTrue)
   542  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   543  
   544  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Insert_priv) VALUES ("%", "testvisdb4", "Y")`)
   545  	err = p.LoadUserTable(se)
   546  	c.Assert(err, IsNil)
   547  	isVisible = p.DBIsVisible("testvisdb4", "%", "visdb")
   548  	c.Assert(isVisible, IsTrue)
   549  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   550  
   551  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, UFIDelate_priv) VALUES ("%", "testvisdb5", "Y")`)
   552  	err = p.LoadUserTable(se)
   553  	c.Assert(err, IsNil)
   554  	isVisible = p.DBIsVisible("testvisdb5", "%", "visdb")
   555  	c.Assert(isVisible, IsTrue)
   556  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   557  
   558  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Create_view_priv) VALUES ("%", "testvisdb6", "Y")`)
   559  	err = p.LoadUserTable(se)
   560  	c.Assert(err, IsNil)
   561  	isVisible = p.DBIsVisible("testvisdb6", "%", "visdb")
   562  	c.Assert(isVisible, IsTrue)
   563  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   564  
   565  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, Trigger_priv) VALUES ("%", "testvisdb7", "Y")`)
   566  	err = p.LoadUserTable(se)
   567  	c.Assert(err, IsNil)
   568  	isVisible = p.DBIsVisible("testvisdb7", "%", "visdb")
   569  	c.Assert(isVisible, IsTrue)
   570  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   571  
   572  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, References_priv) VALUES ("%", "testvisdb8", "Y")`)
   573  	err = p.LoadUserTable(se)
   574  	c.Assert(err, IsNil)
   575  	isVisible = p.DBIsVisible("testvisdb8", "%", "visdb")
   576  	c.Assert(isVisible, IsTrue)
   577  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   578  
   579  	mustInterDirc(c, se, `INSERT INTO allegrosql.user (Host, User, InterDircute_priv) VALUES ("%", "testvisdb9", "Y")`)
   580  	err = p.LoadUserTable(se)
   581  	c.Assert(err, IsNil)
   582  	isVisible = p.DBIsVisible("testvisdb9", "%", "visdb")
   583  	c.Assert(isVisible, IsTrue)
   584  	mustInterDirc(c, se, "TRUNCATE TABLE allegrosql.user")
   585  }