integrate tableacl with callerid

This commit is contained in:
Shengzhe Yao 2015-07-27 17:55:39 -07:00
Родитель eb06af8676
Коммит 8bfb569cf3
5 изменённых файлов: 59 добавлений и 39 удалений

Просмотреть файл

@ -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