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) } }
func checkLoad(config *tableaclpb.Config, valid bool) error { err := tableacl.InitFromProto(config) if !valid && err == nil { return errors.New("expecting parse error none returned") } if valid && err != nil { return fmt.Errorf("unexpected load error: %v", err) } return nil }
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 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 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 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) } }
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) 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) } 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() 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 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() }