зеркало из https://github.com/github/vitess-gh.git
integrate tableacl with callerid
This commit is contained in:
Родитель
eb06af8676
Коммит
8bfb569cf3
|
@ -20,8 +20,15 @@ import (
|
|||
pb "github.com/youtube/vitess/go/vt/proto/tableacl"
|
||||
)
|
||||
|
||||
// ACLResult embeds an acl.ACL and also tell which table group it belongs to.
|
||||
type ACLResult struct {
|
||||
acl.ACL
|
||||
GroupName string
|
||||
}
|
||||
|
||||
type aclEntry struct {
|
||||
tableNameOrPrefix string
|
||||
groupName string
|
||||
acl map[Role]acl.ACL
|
||||
}
|
||||
|
||||
|
@ -108,6 +115,7 @@ func load(config *pb.Config) error {
|
|||
for _, tableNameOrPrefix := range group.TableNamesOrPrefixes {
|
||||
entries = append(entries, aclEntry{
|
||||
tableNameOrPrefix: tableNameOrPrefix,
|
||||
groupName: group.Name,
|
||||
acl: map[Role]acl.ACL{
|
||||
READER: readers,
|
||||
WRITER: writers,
|
||||
|
@ -177,7 +185,7 @@ func validateNameOrPrefix(nameOrPrefix string) error {
|
|||
}
|
||||
|
||||
// Authorized returns the list of entities who have the specified role on a tablel.
|
||||
func Authorized(table string, role Role) acl.ACL {
|
||||
func Authorized(table string, role Role) *ACLResult {
|
||||
currentACL.RLock()
|
||||
defer currentACL.RUnlock()
|
||||
start := 0
|
||||
|
@ -188,7 +196,10 @@ func Authorized(table string, role Role) acl.ACL {
|
|||
if table == val || (strings.HasSuffix(val, "%") && strings.HasPrefix(table, val[:len(val)-1])) {
|
||||
acl, ok := currentACL.entries[mid].acl[role]
|
||||
if ok {
|
||||
return acl
|
||||
return &ACLResult{
|
||||
ACL: acl,
|
||||
GroupName: currentACL.entries[mid].groupName,
|
||||
}
|
||||
}
|
||||
break
|
||||
} else if table < val {
|
||||
|
@ -197,7 +208,10 @@ func Authorized(table string, role Role) acl.ACL {
|
|||
start = mid + 1
|
||||
}
|
||||
}
|
||||
return acl.DenyAllACL{}
|
||||
return &ACLResult{
|
||||
ACL: acl.DenyAllACL{},
|
||||
GroupName: "",
|
||||
}
|
||||
}
|
||||
|
||||
// GetCurrentConfig returns a copy of current tableacl configuration.
|
||||
|
|
|
@ -48,8 +48,9 @@ func TestInitWithValidConfig(t *testing.T) {
|
|||
func TestInitFromProto(t *testing.T) {
|
||||
setUpTableACL(&simpleacl.Factory{})
|
||||
readerACL := Authorized("my_test_table", READER)
|
||||
if !reflect.DeepEqual(readerACL, acl.DenyAllACL{}) {
|
||||
t.Fatalf("tableacl has not been initialized, got: %v, want: %v", readerACL, acl.DenyAllACL{})
|
||||
want := &ACLResult{ACL: acl.DenyAllACL{}, GroupName: ""}
|
||||
if !reflect.DeepEqual(readerACL, want) {
|
||||
t.Fatalf("tableacl has not been initialized, got: %v, want: %v", readerACL, want)
|
||||
}
|
||||
config := &tableaclpb.Config{
|
||||
TableGroups: []*tableaclpb.TableGroupSpec{{
|
||||
|
@ -67,7 +68,7 @@ func TestInitFromProto(t *testing.T) {
|
|||
}
|
||||
|
||||
readerACL = Authorized("unknown_table", READER)
|
||||
if !reflect.DeepEqual(acl.DenyAllACL{}, readerACL) {
|
||||
if !reflect.DeepEqual(readerACL, want) {
|
||||
t.Fatalf("there is no config for unknown_table, should deny by default")
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/youtube/vitess/go/mysql"
|
||||
mproto "github.com/youtube/vitess/go/mysql/proto"
|
||||
"github.com/youtube/vitess/go/sqltypes"
|
||||
"github.com/youtube/vitess/go/vt/callerid"
|
||||
"github.com/youtube/vitess/go/vt/callinfo"
|
||||
"github.com/youtube/vitess/go/vt/schema"
|
||||
"github.com/youtube/vitess/go/vt/sqlparser"
|
||||
|
@ -215,21 +216,28 @@ func (qre *QueryExecutor) checkPermissions() error {
|
|||
return NewTabletError(ErrRetry, "Query disallowed due to rule: %s", desc)
|
||||
}
|
||||
|
||||
callerID := callerid.ImmediateCallerIDFromContext(qre.ctx)
|
||||
if callerID == nil {
|
||||
if qre.qe.strictTableAcl {
|
||||
return NewTabletError(ErrFail, "missing caller id")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// a superuser that exempts from table ACL checking.
|
||||
if qre.qe.exemptACL == username {
|
||||
if qre.qe.exemptACL == callerID.Username {
|
||||
qre.qe.tableaclExemptCount.Add(1)
|
||||
return nil
|
||||
}
|
||||
tableACLStatsKey := []string{
|
||||
qre.plan.TableName,
|
||||
// TODO(shengzhe): use table group instead of username.
|
||||
username,
|
||||
qre.plan.PlanId.String(),
|
||||
username,
|
||||
}
|
||||
if qre.plan.Authorized == nil {
|
||||
return NewTabletError(ErrFail, "table acl error: nil acl")
|
||||
}
|
||||
tableACLStatsKey := []string{
|
||||
qre.plan.TableName,
|
||||
qre.plan.Authorized.GroupName,
|
||||
qre.plan.PlanId.String(),
|
||||
callerID.Username,
|
||||
}
|
||||
// perform table ACL check if it is enabled.
|
||||
if !qre.plan.Authorized.IsMember(username) {
|
||||
if qre.qe.enableTableAclDryRun {
|
||||
|
|
|
@ -16,8 +16,8 @@ import (
|
|||
mproto "github.com/youtube/vitess/go/mysql/proto"
|
||||
"github.com/youtube/vitess/go/sqldb"
|
||||
"github.com/youtube/vitess/go/sqltypes"
|
||||
"github.com/youtube/vitess/go/vt/callerid"
|
||||
"github.com/youtube/vitess/go/vt/callinfo"
|
||||
tableaclpb "github.com/youtube/vitess/go/vt/proto/tableacl"
|
||||
"github.com/youtube/vitess/go/vt/tableacl"
|
||||
"github.com/youtube/vitess/go/vt/tableacl/simpleacl"
|
||||
"github.com/youtube/vitess/go/vt/tabletserver/fakecacheservice"
|
||||
|
@ -25,6 +25,9 @@ import (
|
|||
"github.com/youtube/vitess/go/vt/tabletserver/proto"
|
||||
"github.com/youtube/vitess/go/vt/vttest/fakesqldb"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
querypb "github.com/youtube/vitess/go/vt/proto/query"
|
||||
tableaclpb "github.com/youtube/vitess/go/vt/proto/tableacl"
|
||||
)
|
||||
|
||||
func TestQueryExecutorPlanDDL(t *testing.T) {
|
||||
|
@ -946,11 +949,10 @@ func TestQueryExecutorTableAcl(t *testing.T) {
|
|||
})
|
||||
|
||||
username := "u2"
|
||||
callInfo := &fakeCallInfo{
|
||||
remoteAddr: "1.2.3.4",
|
||||
username: username,
|
||||
callerID := &querypb.VTGateCallerID{
|
||||
Username: username,
|
||||
}
|
||||
ctx := callinfo.NewContext(context.Background(), callInfo)
|
||||
ctx := callerid.NewContext(context.Background(), nil, callerID)
|
||||
config := &tableaclpb.Config{
|
||||
TableGroups: []*tableaclpb.TableGroupSpec{{
|
||||
Name: "group01",
|
||||
|
@ -992,12 +994,10 @@ func TestQueryExecutorTableAclNoPermission(t *testing.T) {
|
|||
})
|
||||
|
||||
username := "u2"
|
||||
callInfo := &fakeCallInfo{
|
||||
remoteAddr: "1.2.3.4",
|
||||
username: username,
|
||||
callerID := &querypb.VTGateCallerID{
|
||||
Username: username,
|
||||
}
|
||||
ctx := callinfo.NewContext(context.Background(), callInfo)
|
||||
|
||||
ctx := callerid.NewContext(context.Background(), nil, callerID)
|
||||
config := &tableaclpb.Config{
|
||||
TableGroups: []*tableaclpb.TableGroupSpec{{
|
||||
Name: "group02",
|
||||
|
@ -1058,11 +1058,10 @@ func TestQueryExecutorTableAclExemptACL(t *testing.T) {
|
|||
})
|
||||
|
||||
username := "u2"
|
||||
callInfo := &fakeCallInfo{
|
||||
remoteAddr: "1.2.3.4",
|
||||
username: username,
|
||||
callerID := &querypb.VTGateCallerID{
|
||||
Username: username,
|
||||
}
|
||||
ctx := callinfo.NewContext(context.Background(), callInfo)
|
||||
ctx := callerid.NewContext(context.Background(), nil, callerID)
|
||||
|
||||
config := &tableaclpb.Config{
|
||||
TableGroups: []*tableaclpb.TableGroupSpec{{
|
||||
|
@ -1100,11 +1099,11 @@ func TestQueryExecutorTableAclExemptACL(t *testing.T) {
|
|||
// table acl should be ignored since this is an exempt user.
|
||||
username = "exempt-acl"
|
||||
sqlQuery.qe.exemptACL = username
|
||||
callInfo = &fakeCallInfo{
|
||||
remoteAddr: "1.2.3.4",
|
||||
username: username,
|
||||
callerID = &querypb.VTGateCallerID{
|
||||
Username: username,
|
||||
}
|
||||
ctx = callinfo.NewContext(context.Background(), callInfo)
|
||||
ctx = callerid.NewContext(context.Background(), nil, callerID)
|
||||
|
||||
qre = newTestQueryExecutor(ctx, sqlQuery, query, 0)
|
||||
_, err = qre.Execute()
|
||||
if err != nil {
|
||||
|
@ -1129,11 +1128,10 @@ func TestQueryExecutorTableAclDryRun(t *testing.T) {
|
|||
})
|
||||
|
||||
username := "u2"
|
||||
callInfo := &fakeCallInfo{
|
||||
remoteAddr: "1.2.3.4",
|
||||
username: username,
|
||||
callerID := &querypb.VTGateCallerID{
|
||||
Username: username,
|
||||
}
|
||||
ctx := callinfo.NewContext(context.Background(), callInfo)
|
||||
ctx := callerid.NewContext(context.Background(), nil, callerID)
|
||||
|
||||
config := &tableaclpb.Config{
|
||||
TableGroups: []*tableaclpb.TableGroupSpec{{
|
||||
|
@ -1149,7 +1147,7 @@ func TestQueryExecutorTableAclDryRun(t *testing.T) {
|
|||
|
||||
tableACLStatsKey := strings.Join([]string{
|
||||
"test_table",
|
||||
username,
|
||||
"group02",
|
||||
planbuilder.PLAN_PASS_SELECT.String(),
|
||||
username,
|
||||
}, ".")
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"github.com/youtube/vitess/go/timer"
|
||||
"github.com/youtube/vitess/go/vt/schema"
|
||||
"github.com/youtube/vitess/go/vt/tableacl"
|
||||
tacl "github.com/youtube/vitess/go/vt/tableacl/acl"
|
||||
"github.com/youtube/vitess/go/vt/tabletserver/planbuilder"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -45,7 +44,7 @@ type ExecPlan struct {
|
|||
TableInfo *TableInfo
|
||||
Fields []mproto.Field
|
||||
Rules *QueryRules
|
||||
Authorized tacl.ACL
|
||||
Authorized *tableacl.ACLResult
|
||||
|
||||
mu sync.Mutex
|
||||
QueryCount int64
|
||||
|
|
Загрузка…
Ссылка в новой задаче