func TestQueryExecutorTableAclDryRun(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callInfo := &fakeCallInfo{ remoteAddr: "1.2.3.4", username: username, } ctx := callinfo.NewContext(context.Background(), callInfo) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"u1"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } tableACLStatsKey := strings.Join([]string{ "test_table", username, planbuilder.PLAN_PASS_SELECT.String(), username, }, ".") // enable Config.StrictTableAcl sqlQuery := newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl) sqlQuery.qe.enableTableAclDryRun = true qre := newTestQueryExecutor(ctx, sqlQuery, query, 0) defer sqlQuery.disallowQueries() checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) beforeCount := sqlQuery.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey] // query should fail because current user do not have read permissions _, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want: nil", err) } afterCount := sqlQuery.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey] if afterCount-beforeCount != 1 { t.Fatalf("table acl pseudo denied count should increase by one. got: %d, want: %d", afterCount, beforeCount+1) } }
func TestQueryExecutorTableAclDryRun(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &sqltypes.Result{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &sqltypes.Result{ Fields: getTestTableFields(), }) username := "******" callerID := &querypb.VTGateCallerID{ Username: username, } ctx := callerid.NewContext(context.Background(), nil, callerID) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"u1"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } tableACLStatsKey := strings.Join([]string{ "test_table", "group02", planbuilder.PlanPassSelect.String(), username, }, ".") // enable Config.StrictTableAcl tsv := newTestTabletServer(ctx, enableStrict|enableStrictTableAcl, db) tsv.qe.enableTableAclDryRun = true qre := newTestQueryExecutor(ctx, tsv, query, 0) defer tsv.StopService() checkPlanID(t, planbuilder.PlanPassSelect, qre.plan.PlanID) beforeCount := tsv.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey] // query should fail because current user do not have read permissions _, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want: nil", err) } afterCount := tsv.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey] if afterCount-beforeCount != 1 { t.Fatalf("table acl pseudo denied count should increase by one. got: %d, want: %d", afterCount, beforeCount+1) } }
// TestSuite tests a concrete acl.Factory implementation. func TestSuite(t *testing.T, factory acl.Factory) { name := fmt.Sprintf("tableacl-test-%d", rand.Int63()) tableacl.Register(name, factory) tableacl.SetDefaultACL(name) testValidConfigs(t) testDenyReaderInsert(t) testAllowReaderSelect(t) testDenyReaderDDL(t) //testAllowUnmatchedTable(t) }
func TestQueryExecutorTableAcl(t *testing.T) { testUtils := &testUtils{} aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" expected := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, expected) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callInfo := &fakeCallInfo{ remoteAddr: "1.2.3.4", username: username, } ctx := callinfo.NewContext(context.Background(), callInfo) if err := tableacl.InitFromBytes( []byte(fmt.Sprintf(`{"test_table":{"READER":"%s"}}`, username))); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } qre, sqlQuery := newTestQueryExecutor( query, ctx, enableRowCache|enableSchemaOverrides|enableStrict) checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) testUtils.checkEqual(t, expected, qre.Execute()) sqlQuery.disallowQueries() if err := tableacl.InitFromBytes([]byte(`{"test_table":{"READER":"superuser"}}`)); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } // without enabling Config.StrictTableAcl qre, sqlQuery = newTestQueryExecutor( query, ctx, enableRowCache|enableSchemaOverrides|enableStrict) checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) qre.Execute() sqlQuery.disallowQueries() // enable Config.StrictTableAcl qre, sqlQuery = newTestQueryExecutor( query, ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl) defer sqlQuery.disallowQueries() checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) defer handleAndVerifyTabletError(t, "query should fail because current user do not have read permissions", ErrFail) qre.Execute() }
// TestSuite tests a concrete acl.Factory implementation. func TestSuite(t *testing.T, factory acl.Factory) { name := fmt.Sprintf("tableacl-test-%d", rand.Int63()) tableacl.Register(name, factory) tableacl.SetDefaultACL(name) testParseInvalidJSON(t) testInvalidRoleName(t) testInvalidRegex(t) testValidConfigs(t) testDenyReaderInsert(t) testAllowReaderSelect(t) testDenyReaderDDL(t) testAllowUnmatchedTable(t) testAllUserReadAccess(t) testAllUserWriteAccess(t) }
func TestQueryExecutorTableAcl(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callInfo := &fakeCallInfo{ remoteAddr: "1.2.3.4", username: username, } ctx := callinfo.NewContext(context.Background(), callInfo) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group01", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{username}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } sqlQuery := newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict) qre := newTestQueryExecutor(ctx, sqlQuery, query, 0) defer sqlQuery.disallowQueries() checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) got, err := qre.Execute() if err != nil { t.Fatalf("got: %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("qre.Execute() = %v, want: %v", got, want) } }
func TestQueryExecutorTableAcl(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callerID := &querypb.VTGateCallerID{ Username: username, } ctx := callerid.NewContext(context.Background(), nil, callerID) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group01", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{username}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } tsv := newTestTabletServer(ctx, enableRowCache|enableSchemaOverrides|enableStrict, db) qre := newTestQueryExecutor(ctx, tsv, query, 0) defer tsv.StopService() checkPlanID(t, planbuilder.PlanPassSelect, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("got: %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("qre.Execute() = %v, want: %v", got, want) } }
func initTableACL() error { file, err := ioutil.TempFile("", "tableacl.json") if err != nil { return err } defer os.Remove(file.Name()) n, err := file.WriteString(tableACLConfig) if err != nil { return err } if n != len(tableACLConfig) { return errors.New("table acl: short write") } file.Close() tableacl.Register("simpleacl", &simpleacl.Factory{}) tableacl.Init(file.Name()) return nil }
func TestQueryExecutorTableAclNoPermission(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callerID := &querypb.VTGateCallerID{ Username: username, } ctx := callerid.NewContext(context.Background(), nil, callerID) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"superuser"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } // without enabling Config.StrictTableAcl sqlQuery := newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict) qre := newTestQueryExecutor(ctx, sqlQuery, query, 0) checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) got, err := qre.Execute() if err != nil { t.Fatalf("got: %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("qre.Execute() = %v, want: %v", got, want) } sqlQuery.disallowQueries() // enable Config.StrictTableAcl sqlQuery = newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl) qre = newTestQueryExecutor(ctx, sqlQuery, query, 0) defer sqlQuery.disallowQueries() checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) // query should fail because current user do not have read permissions _, err = qre.Execute() if err == nil { t.Fatal("got: nil, want: error") } tabletError, ok := err.(*TabletError) if !ok { t.Fatalf("got: %v, want: *TabletError", err) } if tabletError.ErrorType != ErrFail { t.Fatalf("got: %s, want: ErrFail", getTabletErrorString(tabletError.ErrorType)) } }
func TestQueryExecutorTableAclExemptACL(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callInfo := &fakeCallInfo{ remoteAddr: "1.2.3.4", username: username, } ctx := callinfo.NewContext(context.Background(), callInfo) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"u1"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } // enable Config.StrictTableAcl sqlQuery := newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl) qre := newTestQueryExecutor(ctx, sqlQuery, query, 0) defer sqlQuery.disallowQueries() checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId) // query should fail because current user do not have read permissions _, err := qre.Execute() if err == nil { t.Fatal("got: nil, want: error") } tabletError, ok := err.(*TabletError) if !ok { t.Fatalf("got: %v, want: *TabletError", err) } if tabletError.ErrorType != ErrFail { t.Fatalf("got: %s, want: ErrFail", getTabletErrorString(tabletError.ErrorType)) } if !strings.Contains(tabletError.Error(), "table acl error") { t.Fatalf("got %s, want tablet errorL table acl error", tabletError.Error()) } // table acl should be ignored since this is an exempt user. username = "******" sqlQuery.qe.exemptACL = username callInfo = &fakeCallInfo{ remoteAddr: "1.2.3.4", username: username, } ctx = callinfo.NewContext(context.Background(), callInfo) qre = newTestQueryExecutor(ctx, sqlQuery, query, 0) _, err = qre.Execute() if err != nil { t.Fatal("qre.Execute: nil, want: error") } }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() tabletserver.Init() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vttablet doesn't take any positional arguments") exit.Return(1) } servenv.Init() if *tabletPath == "" { log.Errorf("tabletPath required") exit.Return(1) } tabletAlias, err := topoproto.ParseTabletAlias(*tabletPath) if err != nil { log.Error(err) exit.Return(1) } mycnf, err := mysqlctl.NewMycnfFromFlags(tabletAlias.Uid) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } dbcfgs.App.EnableRowcache = *enableRowcache // creates and registers the query service qsc := tabletserver.NewServer() qsc.Register() binlog.RegisterUpdateStreamService(mycnf) if *tableAclConfig != "" { tableacl.Register("simpleacl", &simpleacl.Factory{}) tableacl.Init( *tableAclConfig, func() { qsc.ClearQueryPlanCache() }, ) } else if *enforceTableACLConfig { log.Error("table acl config has to be specified with table-acl-config flag because enforce-tableacl-config is set.") exit.Return(1) } // Create mysqld and register the health reporter (needs to be done // before initializing the agent, so the initial health check // done by the agent has the right reporter) mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) registerHealthReporter(mysqld) // Depends on both query and updateStream. gRPCPort := int32(0) if servenv.GRPCPort != nil { gRPCPort = int32(*servenv.GRPCPort) } agent, err = tabletmanager.NewActionAgent(context.Background(), mysqld, qsc, tabletAlias, dbcfgs, mycnf, int32(*servenv.Port), gRPCPort, *overridesFile, *lockTimeout) if err != nil { log.Error(err) exit.Return(1) } servenv.OnRun(func() { addStatusParts(qsc) }) servenv.OnTerm(func() { qsc.StopService() binlog.DisableUpdateStreamService() agent.Stop() }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func TestQueryExecutorTableAclExemptACL(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &mproto.QueryResult{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{ Fields: getTestTableFields(), }) username := "******" callerID := &querypb.VTGateCallerID{ Username: username, } ctx := callerid.NewContext(context.Background(), nil, callerID) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"u1"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } // enable Config.StrictTableAcl tsv := newTestTabletServer(ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl, db) qre := newTestQueryExecutor(ctx, tsv, query, 0) defer tsv.StopService() checkPlanID(t, planbuilder.PlanPassSelect, qre.plan.PlanID) // query should fail because current user do not have read permissions _, err := qre.Execute() if err == nil { t.Fatal("got: nil, want: error") } tabletError, ok := err.(*TabletError) if !ok { t.Fatalf("got: %v, want: *TabletError", err) } if tabletError.ErrorType != ErrFail { t.Fatalf("got: %s, want: ErrFail", getTabletErrorString(tabletError.ErrorType)) } if !strings.Contains(tabletError.Error(), "table acl error") { t.Fatalf("got %s, want tablet errorL table acl error", tabletError.Error()) } // table acl should be ignored since this is an exempt user. username = "******" f, _ := tableacl.GetCurrentAclFactory() if tsv.qe.exemptACL, err = f.New([]string{username}); err != nil { t.Fatalf("Cannot load exempt ACL for Table ACL: %v", err) } callerID = &querypb.VTGateCallerID{ Username: username, } ctx = callerid.NewContext(context.Background(), nil, callerID) qre = newTestQueryExecutor(ctx, tsv, query, 0) _, err = qre.Execute() if err != nil { t.Fatal("qre.Execute: nil, want: error") } }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtocc doesn't take any positional arguments") exit.Return(1) } servenv.Init() dbConfigs, err := dbconfigs.Init("", flags) if err != nil { log.Errorf("Cannot initialize App dbconfig: %v", err) exit.Return(1) } if *enableRowcache { dbConfigs.App.EnableRowcache = true if *enableInvalidator { dbConfigs.App.EnableInvalidator = true } } mycnf := &mysqlctl.Mycnf{BinLogPath: *binlogPath} mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbConfigs.Dba, &dbConfigs.App.ConnParams, &dbConfigs.Repl) if err := unmarshalFile(*overridesFile, &schemaOverrides); err != nil { log.Error(err) exit.Return(1) } data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) if *tableAclConfig != "" { tableacl.Register("simpleacl", &simpleacl.Factory{}) tableacl.Init(*tableAclConfig) } qsc := tabletserver.NewQueryServiceControl() tabletserver.InitQueryService(qsc) // Query service can go into NOT_SERVING state if mysql goes down. // So, continuously retry starting the service. So, it tries to come // back up if it went down. go func() { for { _ = qsc.AllowQueries(nil, dbConfigs, schemaOverrides, mysqld) time.Sleep(30 * time.Second) } }() log.Infof("starting vtocc %v", *servenv.Port) servenv.OnRun(func() { addStatusParts(qsc) }) servenv.OnTerm(func() { qsc.DisallowQueries() mysqld.Close() }) servenv.RunDefault() }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.AllPrivsConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() tabletserver.Init() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vttablet doesn't take any positional arguments") exit.Return(1) } servenv.Init() if *tabletPath == "" { log.Errorf("tabletPath required") exit.Return(1) } tabletAlias, err := topoproto.ParseTabletAlias(*tabletPath) if err != nil { log.Error(err) exit.Return(1) } mycnf, err := mysqlctl.NewMycnfFromFlags(tabletAlias.Uid) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } // creates and registers the query service qsc := tabletserver.NewServer() servenv.OnRun(func() { qsc.Register() addStatusParts(qsc) }) servenv.OnClose(func() { // We now leave the queryservice running during lameduck, // so stop it in OnClose(), after lameduck is over. qsc.StopService() }) if *tableAclConfig != "" { // To override default simpleacl, other ACL plugins must set themselves to be default ACL factory tableacl.Register("simpleacl", &simpleacl.Factory{}) } else if *enforceTableACLConfig { log.Error("table acl config has to be specified with table-acl-config flag because enforce-tableacl-config is set.") exit.Return(1) } // tabletacl.Init loads ACL from file if *tableAclConfig is not empty err = tableacl.Init( *tableAclConfig, func() { qsc.ClearQueryPlanCache() }, ) if err != nil { log.Errorf("Fail to initialize Table ACL: %v", err) if *enforceTableACLConfig { log.Error("Need a valid initial Table ACL when enforce-tableacl-config is set, exiting.") exit.Return(1) } } // Create mysqld and register the health reporter (needs to be done // before initializing the agent, so the initial health check // done by the agent has the right reporter) mysqld := mysqlctl.NewMysqld(mycnf, &dbcfgs.Dba, &dbcfgs.AllPrivs, &dbcfgs.App, &dbcfgs.Repl, true /* enablePublishStats */) servenv.OnClose(mysqld.Close) // Depends on both query and updateStream. gRPCPort := int32(0) if servenv.GRPCPort != nil { gRPCPort = int32(*servenv.GRPCPort) } agent, err = tabletmanager.NewActionAgent(context.Background(), mysqld, qsc, tabletAlias, dbcfgs, mycnf, int32(*servenv.Port), gRPCPort) if err != nil { log.Error(err) exit.Return(1) } servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func TestQueryExecutorTableAclNoPermission(t *testing.T) { aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63()) tableacl.Register(aclName, &simpleacl.Factory{}) tableacl.SetDefaultACL(aclName) db := setUpQueryExecutorTest() query := "select * from test_table limit 1000" want := &sqltypes.Result{ Fields: getTestTableFields(), RowsAffected: 0, Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) db.AddQuery("select * from test_table where 1 != 1", &sqltypes.Result{ Fields: getTestTableFields(), }) username := "******" callerID := &querypb.VTGateCallerID{ Username: username, } ctx := callerid.NewContext(context.Background(), nil, callerID) config := &tableaclpb.Config{ TableGroups: []*tableaclpb.TableGroupSpec{{ Name: "group02", TableNamesOrPrefixes: []string{"test_table"}, Readers: []string{"superuser"}, }}, } if err := tableacl.InitFromProto(config); err != nil { t.Fatalf("unable to load tableacl config, error: %v", err) } // without enabling Config.StrictTableAcl tsv := newTestTabletServer(ctx, enableStrict, db) qre := newTestQueryExecutor(ctx, tsv, query, 0) checkPlanID(t, planbuilder.PlanPassSelect, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("got: %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("qre.Execute() = %v, want: %v", got, want) } tsv.StopService() // enable Config.StrictTableAcl tsv = newTestTabletServer(ctx, enableStrict|enableStrictTableAcl, db) qre = newTestQueryExecutor(ctx, tsv, query, 0) defer tsv.StopService() checkPlanID(t, planbuilder.PlanPassSelect, qre.plan.PlanID) // query should fail because current user do not have read permissions _, err = qre.Execute() if err == nil { t.Fatal("got: nil, want: error") } tabletError, ok := err.(*TabletError) if !ok { t.Fatalf("got: %v, want: *TabletError", err) } if tabletError.ErrorCode != vtrpcpb.ErrorCode_PERMISSION_DENIED { t.Fatalf("got: %s, want: PERMISSION_DENIED", tabletError.ErrorCode) } }