vitess.io/vitess@v0.16.2/go/vt/wrangler/testlib/permissions_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testlib
    18  
    19  import (
    20  	"context"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"vitess.io/vitess/go/vt/discovery"
    26  	"vitess.io/vitess/go/vt/topo/topoproto"
    27  
    28  	"vitess.io/vitess/go/sqltypes"
    29  	"vitess.io/vitess/go/vt/logutil"
    30  	"vitess.io/vitess/go/vt/topo"
    31  	"vitess.io/vitess/go/vt/topo/memorytopo"
    32  	"vitess.io/vitess/go/vt/vttablet/tmclient"
    33  	"vitess.io/vitess/go/vt/wrangler"
    34  
    35  	querypb "vitess.io/vitess/go/vt/proto/query"
    36  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    37  )
    38  
    39  func TestPermissions(t *testing.T) {
    40  	delay := discovery.GetTabletPickerRetryDelay()
    41  	defer func() {
    42  		discovery.SetTabletPickerRetryDelay(delay)
    43  	}()
    44  	discovery.SetTabletPickerRetryDelay(5 * time.Millisecond)
    45  
    46  	// Initialize our environment
    47  	ctx := context.Background()
    48  	ts := memorytopo.NewServer("cell1", "cell2")
    49  	wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient())
    50  	vp := NewVtctlPipe(t, ts)
    51  	defer vp.Close()
    52  
    53  	primary := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, nil)
    54  	replica := NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, nil)
    55  
    56  	// mark the primary inside the shard
    57  	_, err := ts.UpdateShardFields(ctx, primary.Tablet.Keyspace, primary.Tablet.Shard, func(si *topo.ShardInfo) error {
    58  		si.PrimaryAlias = primary.Tablet.Alias
    59  		return nil
    60  	})
    61  	if err != nil {
    62  		t.Fatalf("UpdateShardFields failed: %v", err)
    63  	}
    64  
    65  	// primary will be asked for permissions
    66  	primary.FakeMysqlDaemon.FetchSuperQueryMap = map[string]*sqltypes.Result{
    67  		"SELECT * FROM mysql.user ORDER BY host, user": {
    68  			Fields: []*querypb.Field{
    69  				{
    70  					Name: "Host",
    71  					Type: sqltypes.Char,
    72  				},
    73  				{
    74  					Name: "User",
    75  					Type: sqltypes.Char,
    76  				},
    77  				{
    78  					Name: "Password",
    79  					Type: sqltypes.Char,
    80  				},
    81  				{
    82  					Name: "Select_priv",
    83  					Type: sqltypes.Char,
    84  				},
    85  				{
    86  					Name: "Insert_priv",
    87  					Type: sqltypes.Char,
    88  				},
    89  				{
    90  					Name: "Update_priv",
    91  					Type: sqltypes.Char,
    92  				},
    93  				{
    94  					Name: "Delete_priv",
    95  					Type: sqltypes.Char,
    96  				},
    97  				{
    98  					Name: "Create_priv",
    99  					Type: sqltypes.Char,
   100  				},
   101  				{
   102  					Name: "Drop_priv",
   103  					Type: sqltypes.Char,
   104  				},
   105  				{
   106  					Name: "Reload_priv",
   107  					Type: sqltypes.Char,
   108  				},
   109  				{
   110  					Name: "Shutdown_priv",
   111  					Type: sqltypes.Char,
   112  				},
   113  				{
   114  					Name: "Process_priv",
   115  					Type: sqltypes.Char,
   116  				},
   117  				{
   118  					Name: "File_priv",
   119  					Type: sqltypes.Char,
   120  				},
   121  				{
   122  					Name: "Grant_priv",
   123  					Type: sqltypes.Char,
   124  				},
   125  				{
   126  					Name: "References_priv",
   127  					Type: sqltypes.Char,
   128  				},
   129  				{
   130  					Name: "Index_priv",
   131  					Type: sqltypes.Char,
   132  				},
   133  				{
   134  					Name: "Alter_priv",
   135  					Type: sqltypes.Char,
   136  				},
   137  				{
   138  					Name: "Show_db_priv",
   139  					Type: sqltypes.Char,
   140  				},
   141  				{
   142  					Name: "Super_priv",
   143  					Type: sqltypes.Char,
   144  				},
   145  				{
   146  					Name: "Create_tmp_table_priv",
   147  					Type: sqltypes.Char,
   148  				},
   149  				{
   150  					Name: "Lock_tables_priv",
   151  					Type: sqltypes.Char,
   152  				},
   153  				{
   154  					Name: "Execute_priv",
   155  					Type: sqltypes.Char,
   156  				},
   157  				{
   158  					Name: "Repl_slave_priv",
   159  					Type: sqltypes.Char,
   160  				},
   161  				{
   162  					Name: "Repl_client_priv",
   163  					Type: sqltypes.Char,
   164  				},
   165  				{
   166  					Name: "Create_view_priv",
   167  					Type: sqltypes.Char,
   168  				},
   169  				{
   170  					Name: "Show_view_priv",
   171  					Type: sqltypes.Char,
   172  				},
   173  				{
   174  					Name: "Create_routine_priv",
   175  					Type: sqltypes.Char,
   176  				},
   177  				{
   178  					Name: "Alter_routine_priv",
   179  					Type: sqltypes.Char,
   180  				},
   181  				{
   182  					Name: "Create_user_priv",
   183  					Type: sqltypes.Char,
   184  				},
   185  				{
   186  					Name: "Event_priv",
   187  					Type: sqltypes.Char,
   188  				},
   189  				{
   190  					Name: "Trigger_priv",
   191  					Type: sqltypes.Char,
   192  				},
   193  				{
   194  					Name: "Create_tablespace_priv",
   195  					Type: sqltypes.Char,
   196  				},
   197  				{
   198  					Name: "ssl_type",
   199  					Type: sqltypes.Char,
   200  				},
   201  				{
   202  					Name: "ssl_cipher",
   203  					Type: 252,
   204  				},
   205  				{
   206  					Name: "x509_issuer",
   207  					Type: 252,
   208  				},
   209  				{
   210  					Name: "x509_subject",
   211  					Type: 252,
   212  				},
   213  				{
   214  					Name: "max_questions",
   215  					Type: 3,
   216  				},
   217  				{
   218  					Name: "max_updates",
   219  					Type: 3,
   220  				},
   221  				{
   222  					Name: "max_connections",
   223  					Type: 3,
   224  				},
   225  				{
   226  					Name: "max_user_connections",
   227  					Type: 3,
   228  				},
   229  				{
   230  					Name: "plugin",
   231  					Type: sqltypes.Char,
   232  				},
   233  				{
   234  					Name: "authentication_string",
   235  					Type: 252,
   236  				},
   237  				{
   238  					Name: "password_expired",
   239  					Type: sqltypes.Char,
   240  				},
   241  				{
   242  					Name: "is_role",
   243  					Type: sqltypes.Char,
   244  				}},
   245  			RowsAffected: 0x6,
   246  			InsertID:     0x0,
   247  			Rows: [][]sqltypes.Value{
   248  				{
   249  					sqltypes.NewVarBinary("test_host1"),
   250  					sqltypes.NewVarBinary("test_user1"),
   251  					sqltypes.NewVarBinary("test_password1"),
   252  					sqltypes.NewVarBinary("Y"),
   253  					sqltypes.NewVarBinary("Y"),
   254  					sqltypes.NewVarBinary("Y"),
   255  					sqltypes.NewVarBinary("Y"),
   256  					sqltypes.NewVarBinary("Y"),
   257  					sqltypes.NewVarBinary("Y"),
   258  					sqltypes.NewVarBinary("Y"),
   259  					sqltypes.NewVarBinary("Y"),
   260  					sqltypes.NewVarBinary("Y"),
   261  					sqltypes.NewVarBinary("Y"),
   262  					sqltypes.NewVarBinary("Y"),
   263  					sqltypes.NewVarBinary("Y"),
   264  					sqltypes.NewVarBinary("Y"),
   265  					sqltypes.NewVarBinary("Y"),
   266  					sqltypes.NewVarBinary("Y"),
   267  					sqltypes.NewVarBinary("Y"),
   268  					sqltypes.NewVarBinary("Y"),
   269  					sqltypes.NewVarBinary("Y"),
   270  					sqltypes.NewVarBinary("Y"),
   271  					sqltypes.NewVarBinary("Y"),
   272  					sqltypes.NewVarBinary("Y"),
   273  					sqltypes.NewVarBinary("Y"),
   274  					sqltypes.NewVarBinary("Y"),
   275  					sqltypes.NewVarBinary("Y"),
   276  					sqltypes.NewVarBinary("Y"),
   277  					sqltypes.NewVarBinary("Y"),
   278  					sqltypes.NewVarBinary("Y"),
   279  					sqltypes.NewVarBinary("Y"),
   280  					sqltypes.NewVarBinary("Y"),
   281  					sqltypes.NewVarBinary(""),
   282  					sqltypes.NewVarBinary(""),
   283  					sqltypes.NewVarBinary(""),
   284  					sqltypes.NewVarBinary(""),
   285  					sqltypes.NewVarBinary("0"),
   286  					sqltypes.NewVarBinary("0"),
   287  					sqltypes.NewVarBinary("0"),
   288  					sqltypes.NewVarBinary("0"),
   289  					sqltypes.NewVarBinary(""),
   290  					sqltypes.NewVarBinary(""),
   291  					sqltypes.NewVarBinary("N"),
   292  					sqltypes.NewVarBinary("N")},
   293  				{
   294  					sqltypes.NewVarBinary("test_host2"),
   295  					sqltypes.NewVarBinary("test_user2"),
   296  					sqltypes.NewVarBinary("test_password2"),
   297  					sqltypes.NewVarBinary("Y"),
   298  					sqltypes.NewVarBinary("Y"),
   299  					sqltypes.NewVarBinary("Y"),
   300  					sqltypes.NewVarBinary("Y"),
   301  					sqltypes.NewVarBinary("Y"),
   302  					sqltypes.NewVarBinary("Y"),
   303  					sqltypes.NewVarBinary("Y"),
   304  					sqltypes.NewVarBinary("Y"),
   305  					sqltypes.NewVarBinary("Y"),
   306  					sqltypes.NewVarBinary("Y"),
   307  					sqltypes.NewVarBinary("Y"),
   308  					sqltypes.NewVarBinary("Y"),
   309  					sqltypes.NewVarBinary("Y"),
   310  					sqltypes.NewVarBinary("Y"),
   311  					sqltypes.NewVarBinary("Y"),
   312  					sqltypes.NewVarBinary("Y"),
   313  					sqltypes.NewVarBinary("Y"),
   314  					sqltypes.NewVarBinary("Y"),
   315  					sqltypes.NewVarBinary("Y"),
   316  					sqltypes.NewVarBinary("Y"),
   317  					sqltypes.NewVarBinary("Y"),
   318  					sqltypes.NewVarBinary("Y"),
   319  					sqltypes.NewVarBinary("Y"),
   320  					sqltypes.NewVarBinary("Y"),
   321  					sqltypes.NewVarBinary("Y"),
   322  					sqltypes.NewVarBinary("Y"),
   323  					sqltypes.NewVarBinary("Y"),
   324  					sqltypes.NewVarBinary("Y"),
   325  					sqltypes.NewVarBinary("Y"),
   326  					sqltypes.NewVarBinary(""),
   327  					sqltypes.NewVarBinary(""),
   328  					sqltypes.NewVarBinary(""),
   329  					sqltypes.NewVarBinary(""),
   330  					sqltypes.NewVarBinary("0"),
   331  					sqltypes.NewVarBinary("0"),
   332  					sqltypes.NewVarBinary("0"),
   333  					sqltypes.NewVarBinary("0"),
   334  					sqltypes.NewVarBinary(""),
   335  					sqltypes.NewVarBinary(""),
   336  					sqltypes.NewVarBinary("N"),
   337  					sqltypes.NewVarBinary("N")},
   338  				{
   339  					sqltypes.NewVarBinary("test_host3"),
   340  					sqltypes.NewVarBinary("test_user3"),
   341  					sqltypes.NewVarBinary("test_password3"),
   342  					sqltypes.NewVarBinary("Y"),
   343  					sqltypes.NewVarBinary("Y"),
   344  					sqltypes.NewVarBinary("Y"),
   345  					sqltypes.NewVarBinary("Y"),
   346  					sqltypes.NewVarBinary("Y"),
   347  					sqltypes.NewVarBinary("Y"),
   348  					sqltypes.NewVarBinary("Y"),
   349  					sqltypes.NewVarBinary("N"),
   350  					sqltypes.NewVarBinary("Y"),
   351  					sqltypes.NewVarBinary("Y"),
   352  					sqltypes.NewVarBinary("N"),
   353  					sqltypes.NewVarBinary("Y"),
   354  					sqltypes.NewVarBinary("Y"),
   355  					sqltypes.NewVarBinary("Y"),
   356  					sqltypes.NewVarBinary("Y"),
   357  					sqltypes.NewVarBinary("N"),
   358  					sqltypes.NewVarBinary("Y"),
   359  					sqltypes.NewVarBinary("Y"),
   360  					sqltypes.NewVarBinary("Y"),
   361  					sqltypes.NewVarBinary("Y"),
   362  					sqltypes.NewVarBinary("Y"),
   363  					sqltypes.NewVarBinary("Y"),
   364  					sqltypes.NewVarBinary("Y"),
   365  					sqltypes.NewVarBinary("Y"),
   366  					sqltypes.NewVarBinary("Y"),
   367  					sqltypes.NewVarBinary("Y"),
   368  					sqltypes.NewVarBinary("Y"),
   369  					sqltypes.NewVarBinary("Y"),
   370  					sqltypes.NewVarBinary("N"),
   371  					sqltypes.NewVarBinary(""),
   372  					sqltypes.NewVarBinary(""),
   373  					sqltypes.NewVarBinary(""),
   374  					sqltypes.NewVarBinary(""),
   375  					sqltypes.NewVarBinary("0"),
   376  					sqltypes.NewVarBinary("0"),
   377  					sqltypes.NewVarBinary("0"),
   378  					sqltypes.NewVarBinary("0"),
   379  					sqltypes.NewVarBinary(""),
   380  					sqltypes.NewVarBinary(""),
   381  					sqltypes.NewVarBinary("N"),
   382  					sqltypes.NewVarBinary("N")},
   383  				{
   384  					sqltypes.NewVarBinary("test_host4"),
   385  					sqltypes.NewVarBinary("test_user4"),
   386  					sqltypes.NewVarBinary("test_password4"),
   387  					sqltypes.NewVarBinary("N"),
   388  					sqltypes.NewVarBinary("N"),
   389  					sqltypes.NewVarBinary("N"),
   390  					sqltypes.NewVarBinary("N"),
   391  					sqltypes.NewVarBinary("N"),
   392  					sqltypes.NewVarBinary("N"),
   393  					sqltypes.NewVarBinary("N"),
   394  					sqltypes.NewVarBinary("N"),
   395  					sqltypes.NewVarBinary("N"),
   396  					sqltypes.NewVarBinary("N"),
   397  					sqltypes.NewVarBinary("N"),
   398  					sqltypes.NewVarBinary("N"),
   399  					sqltypes.NewVarBinary("N"),
   400  					sqltypes.NewVarBinary("N"),
   401  					sqltypes.NewVarBinary("N"),
   402  					sqltypes.NewVarBinary("N"),
   403  					sqltypes.NewVarBinary("N"),
   404  					sqltypes.NewVarBinary("N"),
   405  					sqltypes.NewVarBinary("N"),
   406  					sqltypes.NewVarBinary("Y"),
   407  					sqltypes.NewVarBinary("N"),
   408  					sqltypes.NewVarBinary("N"),
   409  					sqltypes.NewVarBinary("N"),
   410  					sqltypes.NewVarBinary("N"),
   411  					sqltypes.NewVarBinary("N"),
   412  					sqltypes.NewVarBinary("N"),
   413  					sqltypes.NewVarBinary("N"),
   414  					sqltypes.NewVarBinary("N"),
   415  					sqltypes.NewVarBinary("N"),
   416  					sqltypes.NewVarBinary(""),
   417  					sqltypes.NewVarBinary(""),
   418  					sqltypes.NewVarBinary(""),
   419  					sqltypes.NewVarBinary(""),
   420  					sqltypes.NewVarBinary("0"),
   421  					sqltypes.NewVarBinary("0"),
   422  					sqltypes.NewVarBinary("0"),
   423  					sqltypes.NewVarBinary("0"),
   424  					sqltypes.NewVarBinary(""),
   425  					sqltypes.NewVarBinary(""),
   426  					sqltypes.NewVarBinary("N"),
   427  					sqltypes.NewVarBinary("N"),
   428  				},
   429  			},
   430  		},
   431  		"SELECT * FROM mysql.db ORDER BY host, db, user": {
   432  			Fields: []*querypb.Field{
   433  				{
   434  					Name: "Host",
   435  					Type: sqltypes.Char,
   436  				},
   437  				{
   438  					Name: "Db",
   439  					Type: sqltypes.Char,
   440  				},
   441  				{
   442  					Name: "User",
   443  					Type: sqltypes.Char,
   444  				},
   445  				{
   446  					Name: "Select_priv",
   447  					Type: sqltypes.Char,
   448  				},
   449  				{
   450  					Name: "Insert_priv",
   451  					Type: sqltypes.Char,
   452  				},
   453  				{
   454  					Name: "Update_priv",
   455  					Type: sqltypes.Char,
   456  				},
   457  				{
   458  					Name: "Delete_priv",
   459  					Type: sqltypes.Char,
   460  				},
   461  				{
   462  					Name: "Create_priv",
   463  					Type: sqltypes.Char,
   464  				},
   465  				{
   466  					Name: "Drop_priv",
   467  					Type: sqltypes.Char,
   468  				},
   469  				{
   470  					Name: "Grant_priv",
   471  					Type: sqltypes.Char,
   472  				},
   473  				{
   474  					Name: "References_priv",
   475  					Type: sqltypes.Char,
   476  				},
   477  				{
   478  					Name: "Index_priv",
   479  					Type: sqltypes.Char,
   480  				},
   481  				{
   482  					Name: "Alter_priv",
   483  					Type: sqltypes.Char,
   484  				},
   485  				{
   486  					Name: "Create_tmp_table_priv",
   487  					Type: sqltypes.Char,
   488  				},
   489  				{
   490  					Name: "Lock_tables_priv",
   491  					Type: sqltypes.Char,
   492  				},
   493  				{
   494  					Name: "Create_view_priv",
   495  					Type: sqltypes.Char,
   496  				},
   497  				{
   498  					Name: "Show_view_priv",
   499  					Type: sqltypes.Char,
   500  				},
   501  				{
   502  					Name: "Create_routine_priv",
   503  					Type: sqltypes.Char,
   504  				},
   505  				{
   506  					Name: "Alter_routine_priv",
   507  					Type: sqltypes.Char,
   508  				},
   509  				{
   510  					Name: "Execute_priv",
   511  					Type: sqltypes.Char,
   512  				},
   513  				{
   514  					Name: "Event_priv",
   515  					Type: sqltypes.Char,
   516  				},
   517  				{
   518  					Name: "Trigger_priv",
   519  					Type: sqltypes.Char,
   520  				},
   521  			},
   522  			RowsAffected: 0,
   523  			InsertID:     0,
   524  			Rows: [][]sqltypes.Value{
   525  				{
   526  					sqltypes.NewVarBinary("test_host"),
   527  					sqltypes.NewVarBinary("test_db"),
   528  					sqltypes.NewVarBinary("test_user"),
   529  					sqltypes.NewVarBinary("Y"),
   530  					sqltypes.NewVarBinary("Y"),
   531  					sqltypes.NewVarBinary("Y"),
   532  					sqltypes.NewVarBinary("Y"),
   533  					sqltypes.NewVarBinary("Y"),
   534  					sqltypes.NewVarBinary("Y"),
   535  					sqltypes.NewVarBinary("N"),
   536  					sqltypes.NewVarBinary("Y"),
   537  					sqltypes.NewVarBinary("Y"),
   538  					sqltypes.NewVarBinary("Y"),
   539  					sqltypes.NewVarBinary("Y"),
   540  					sqltypes.NewVarBinary("Y"),
   541  					sqltypes.NewVarBinary("N"),
   542  					sqltypes.NewVarBinary("Y"),
   543  					sqltypes.NewVarBinary("Y"),
   544  					sqltypes.NewVarBinary("Y"),
   545  					sqltypes.NewVarBinary("Y"),
   546  					sqltypes.NewVarBinary("Y"),
   547  					sqltypes.NewVarBinary("Y"),
   548  				},
   549  			},
   550  		},
   551  	}
   552  	primary.StartActionLoop(t, wr)
   553  	defer primary.StopActionLoop(t)
   554  
   555  	// Make a two-level-deep copy, so we can make them diverge later.
   556  	user := *primary.FakeMysqlDaemon.FetchSuperQueryMap["SELECT * FROM mysql.user ORDER BY host, user"]
   557  	user.Fields = append([]*querypb.Field{}, user.Fields...)
   558  
   559  	// replica will be asked for permissions
   560  	replica.FakeMysqlDaemon.FetchSuperQueryMap = map[string]*sqltypes.Result{
   561  		"SELECT * FROM mysql.user ORDER BY host, user":   &user,
   562  		"SELECT * FROM mysql.db ORDER BY host, db, user": primary.FakeMysqlDaemon.FetchSuperQueryMap["SELECT * FROM mysql.db ORDER BY host, db, user"],
   563  	}
   564  	replica.FakeMysqlDaemon.SetReplicationSourceInputs = append(replica.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet))
   565  	replica.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{
   566  		// These 4 statements come from tablet startup
   567  		"STOP SLAVE",
   568  		"RESET SLAVE ALL",
   569  		"FAKE SET MASTER",
   570  		"START SLAVE",
   571  	}
   572  	replica.StartActionLoop(t, wr)
   573  	defer replica.StopActionLoop(t)
   574  
   575  	// Overwrite with the correct value to make sure it passes.
   576  	replica.FakeMysqlDaemon.FetchSuperQueryMap["SELECT * FROM mysql.user ORDER BY host, user"].Fields[0] = &querypb.Field{
   577  		Name: "Host",
   578  		Type: sqltypes.Char,
   579  	}
   580  
   581  	// run ValidatePermissionsKeyspace, this should work
   582  	if err := vp.Run([]string{"ValidatePermissionsKeyspace", primary.Tablet.Keyspace}); err != nil {
   583  		t.Fatalf("ValidatePermissionsKeyspace failed: %v", err)
   584  	}
   585  
   586  	// modify one field, this should fail
   587  	replica.FakeMysqlDaemon.FetchSuperQueryMap["SELECT * FROM mysql.user ORDER BY host, user"].Fields[0] = &querypb.Field{
   588  		Name: "Wrong",
   589  		Type: sqltypes.Char,
   590  	}
   591  
   592  	// run ValidatePermissionsKeyspace again, this should now fail
   593  	if err := vp.Run([]string{"ValidatePermissionsKeyspace", primary.Tablet.Keyspace}); err == nil || !strings.Contains(err.Error(), "has an extra user") {
   594  		t.Fatalf("ValidatePermissionsKeyspace has unexpected err: %v", err)
   595  	}
   596  
   597  }