Skip to content

Commit

Permalink
Fix/init oroder (#215)
Browse files Browse the repository at this point in the history
* fix:diable check the length of aclEntry when authentication is disabled (#205)

* fix:diable check the length of aclEntry when authentication is disabled

Signed-off-by: <[email protected]>

* fix:set default groupName to 'invalid group name'

Signed-off-by: <[email protected]>

* fix: modify default aclEntry groupName

Signed-off-by: <[email protected]>

---------

Signed-off-by: <[email protected]>

* chore: fix mysql deb dependency (#210)

Signed-off-by: lyq10085 <[email protected]>

* fix: adjust InitACL and InitDBcofig order

Signed-off-by: <[email protected]>

* feat: use stateManager to manage tableACL

Signed-off-by: <[email protected]>

* fix: recycle conn

Signed-off-by: <[email protected]>

* fix: split simple aclmode to init and set

Signed-off-by: <[email protected]>

---------

Signed-off-by: <[email protected]>
Signed-off-by: lyq10085 <[email protected]>
Co-authored-by: lyq10085 <[email protected]>
  • Loading branch information
gerayking and lyq10085 authored Jul 20, 2023
1 parent 9225885 commit 15518e8
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 83 deletions.
9 changes: 7 additions & 2 deletions go/cmd/vttablet/vttablet.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ var (

func registerFlags(fs *pflag.FlagSet) {
fs.BoolVar(&enforceTableACLConfig, "enforce-tableacl-config", enforceTableACLConfig, "if this flag is true, vttablet will fail to start if a valid tableacl config does not exist")
fs.StringVar(&tableACLConfig, "table-acl-config", tableACLConfig, "path to table access checker config file; send SIGHUP to reload this file")
fs.StringVar(&tableACLConfig, "table-acl-config", tableACLConfig, "path to table access checker config file;")
fs.StringVar(&tableACLMode, "table-acl-config-mode", global.TableACLModeSimple, "table acl config mode (simple or mysqlbased)")
fs.DurationVar(&tableACLConfigReloadInterval, "table-acl-config-reload-interval", tableACLConfigReloadInterval, "Ticker to reload ACLs. Duration flag, format e.g.: 30s. Default: do not reload")
fs.StringVar(&tabletPath, "tablet-path", tabletPath, "tablet alias")
Expand Down Expand Up @@ -139,6 +139,9 @@ func main() {
if err := tm.Start(tablet, config.Healthcheck.IntervalSeconds.Get()); err != nil {
log.Exitf("failed to parse --tablet-path or initialize DB credentials: %v", err)
}
if tableACLMode == global.TableACLModeMysqlBased {
qsc.InitACL(qsc, tableACLMode, tableACLConfig, enforceTableACLConfig, tableACLConfigReloadInterval)
}
servenv.OnClose(func() {
// Close the tm so that our topo entry gets pruned properly and any
// background goroutines that use the topo connection are stopped.
Expand Down Expand Up @@ -235,6 +238,8 @@ func createTabletServer(config *tabletenv.TabletConfig, ts *topo.Server, tabletA
})

servenv.OnClose(qsc.StopService)
qsc.InitACL(qsc, tableACLMode, tableACLConfig, enforceTableACLConfig, tableACLConfigReloadInterval)
if tableACLMode != global.TableACLModeMysqlBased {
qsc.InitACL(qsc, tableACLMode, tableACLConfig, enforceTableACLConfig, tableACLConfigReloadInterval)
}
return qsc
}
156 changes: 114 additions & 42 deletions go/vt/tableacl/tableacl.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ import (
"sort"
"strings"
"sync"

"vitess.io/vitess/go/mysql"
"time"

"vitess.io/vitess/go/internal/global"
"vitess.io/vitess/go/mysql"

"vitess.io/vitess/go/vt/dbconfigs"
"vitess.io/vitess/go/vt/vttablet/tabletserver/connpool"
Expand Down Expand Up @@ -84,7 +84,7 @@ var acls = make(map[string]acl.Factory)
// defaultACL tells the default ACL implementation to use.
var defaultACL string

type tableACL struct {
type TableACL struct {
// mutex protects entries, config, and callback
sync.RWMutex
entries aclEntries
Expand All @@ -93,6 +93,13 @@ type tableACL struct {
dbConfig dbconfigs.Connector
conns *connpool.Pool

tableACLMode string

ticker *time.Ticker
reloadACLConfigFileInterval time.Duration

configFile string

// callback is executed on successful reload.
callback func()
// ACL Factory override for testing
Expand All @@ -105,7 +112,7 @@ type PrivEntry struct {
}

// currentTableACL stores current effective ACL information.
var currentTableACL tableACL
var currentTableACL TableACL

// Init initiates table ACLs.
//
Expand All @@ -122,22 +129,65 @@ var currentTableACL tableACL
// }
// ]
// }
func Init(env tabletenv.Env, dbConfig dbconfigs.Connector, tableACLMode string, configFile string, aclCB func()) error {
return currentTableACL.init(env, dbConfig, tableACLMode, configFile, aclCB)
func Init(env tabletenv.Env, dbConfig dbconfigs.Connector, tableACLMode string, configFile string, reloadACLConfigFileInterval time.Duration, aclCB func()) error {
return currentTableACL.init(env, dbConfig, tableACLMode, configFile, reloadACLConfigFileInterval, aclCB)
}

func (tacl *tableACL) InitMysqlBasedACL(env tabletenv.Env) error {
config := &tableaclpb.Config{}
pool := connpool.NewPool(env, "", tabletenv.ConnPoolConfig{
Size: 3,
IdleTimeoutSeconds: env.Config().OltpReadPool.IdleTimeoutSeconds,
})
tacl.conns = pool
tacl.conns.Open(tacl.dbConfig, tacl.dbConfig, tacl.dbConfig)
return tacl.LoadFromMysql(config)
func (tacl *TableACL) Open() error {
log.Infof("tableACL : opening, aclMode: %v", tacl.tableACLMode)
if tacl.tableACLMode == global.TableACLModeMysqlBased {
tacl.conns.Open(tacl.dbConfig, tacl.dbConfig, tacl.dbConfig)
err := tacl.InitMysqlBasedACL()
if err != nil {
return err
}
} else if tacl.tableACLMode == global.TableACLModeSimple {
err := tacl.InitSimpleACL(tacl.configFile)
if err != nil {
return err
}
}
if tacl.reloadACLConfigFileInterval != 0 {
if tacl.ticker == nil {
tacl.ticker = time.NewTicker(tacl.reloadACLConfigFileInterval)
go func() {
for range tacl.ticker.C {
if tacl.tableACLMode == global.TableACLModeMysqlBased {
err := tacl.InitMysqlBasedACL()
if err != nil {
log.Errorf("InitMysqlBasedACL fail : %v", err)
}
} else if tacl.tableACLMode == global.TableACLModeSimple {
err := tacl.InitSimpleACL(tacl.configFile)
if err != nil {
log.Errorf("InitSimpleACL fail : %v", err)
}
} else {
log.Errorf("unrecognized tableACLMode : %v", tacl.tableACLMode)
}
}
}()
} else {
tacl.ticker.Reset(tacl.reloadACLConfigFileInterval)
}
}
return nil
}
func (tacl *tableACL) InitSimpleACL(configFile string) error {
config := &tableaclpb.Config{}

func (tacl *TableACL) Close() {
tacl.Lock()
defer tacl.Unlock()
if tacl.tableACLMode == global.TableACLModeMysqlBased {
log.Infof("tableACL - closing pool")
tacl.conns.Close()
}
tacl.ticker.Stop()
}
func (tacl *TableACL) InitMysqlBasedACL() error {
//tacl.conns.Open(tacl.dbConfig, tacl.dbConfig, tacl.dbConfig)
return tacl.LoadFromMysql(&tableaclpb.Config{})
}
func (tacl *TableACL) checkSimpleACL(configFile string, config *tableaclpb.Config) error {
data, err := os.ReadFile(configFile)
if err != nil {
log.Infof("unable to read tableACL config file: %v Error: %v", configFile, err)
Expand All @@ -150,25 +200,40 @@ func (tacl *tableACL) InitSimpleACL(configFile string) error {
return fmt.Errorf("unable to unmarshal Table ACL data: %s", data)
}
}
return nil
}
func (tacl *TableACL) InitSimpleACL(configFile string) error {
config := &tableaclpb.Config{}
err := tacl.checkSimpleACL(configFile, config)
if err != nil {
return err
}
return tacl.Set(config)
}

func (tacl *tableACL) init(env tabletenv.Env, dbConfig dbconfigs.Connector, tableACLMode string, configFile string, aclCB func()) error {
func (tacl *TableACL) init(env tabletenv.Env, dbConfig dbconfigs.Connector, tableACLMode string, configFile string, reloadACLConfigFileInterval time.Duration, aclCB func()) error {
tacl.SetCallback(aclCB)
tacl.dbConfig = dbConfig
tacl.tableACLMode = tableACLMode
tacl.reloadACLConfigFileInterval = reloadACLConfigFileInterval
if configFile == "" && tableACLMode == global.TableACLModeSimple {
return nil
}
if tableACLMode == global.TableACLModeMysqlBased {
return tacl.InitMysqlBasedACL(env)
tacl.conns = connpool.NewPool(env, "", tabletenv.ConnPoolConfig{
Size: 3,
IdleTimeoutSeconds: env.Config().OltpReadPool.IdleTimeoutSeconds,
})
} else if tableACLMode == global.TableACLModeSimple {
return tacl.InitSimpleACL(configFile)
} else {
return fmt.Errorf("unrecognized tableACLMode : %v", tableACLMode)
err := tacl.checkSimpleACL(configFile, &tableaclpb.Config{})
if err != nil {
return err
}
}
return nil
}

func (tacl *tableACL) SetCallback(callback func()) {
func (tacl *TableACL) SetCallback(callback func()) {
tacl.Lock()
defer tacl.Unlock()
tacl.callback = callback
Expand All @@ -182,26 +247,26 @@ func InitFromProto(config *tableaclpb.Config) error {
return currentTableACL.Set(config)
}

// LoadFromMysqlBase method retrieves privilege information from mysql.user, mysql.db, mysql.table_priv,
// loadFromMysqlBase method retrieves privilege information from mysql.user, mysql.db, mysql.table_priv,
// and uses this information to create aclEntry instances.
// For instance:
// For global-level privileges, '*.*' is converted to '%'
// For database-level privileges, 'database.*' is converted to 'database.%'
// For table-level privileges, 'database.table' is used directly
func (tacl *tableACL) LoadFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
func (tacl *TableACL) loadFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
entries := aclEntries{}
//
globalEntries, err := tacl.LoadGlobalFromMysqlBase(newACL)
globalEntries, err := tacl.loadGlobalFromMysqlBase(newACL)
if err != nil {
return nil, err
}
entries = append(entries, globalEntries...)
tableEntries, err := tacl.LoadTablePrivFromMysqlBase(newACL)
tableEntries, err := tacl.loadTablePrivFromMysqlBase(newACL)
if err != nil {
return nil, err
}
entries = append(entries, tableEntries...)
dbEntries, err := tacl.LoadDatabasePrivFromMysqlBase(newACL)
dbEntries, err := tacl.loadDatabasePrivFromMysqlBase(newACL)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -255,10 +320,11 @@ func buildACLEntriesFromPrivMap(privMap map[string][]PrivEntry, newACL func([]st
return entries, nil
}

// LoadDatabasePrivFromMysqlBase implement database-level authority authentication
func (tacl *tableACL) LoadDatabasePrivFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
// loadDatabasePrivFromMysqlBase implement database-level authority authentication
func (tacl *TableACL) loadDatabasePrivFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
ctx := context.Background()
conn, err := tacl.conns.Get(ctx, nil)
defer conn.Recycle()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -309,10 +375,11 @@ func (tacl *tableACL) LoadDatabasePrivFromMysqlBase(newACL func([]string) (acl.A
return buildACLEntriesFromPrivMap(privMap, newACL)
}

// LoadTablePrivFromMysqlBase implement table-level authority authentication
func (tacl *tableACL) LoadTablePrivFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
// loadTablePrivFromMysqlBase implement table-level authority authentication
func (tacl *TableACL) loadTablePrivFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
ctx := context.Background()
conn, err := tacl.conns.Get(ctx, nil)
defer conn.Recycle()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -373,11 +440,12 @@ func (tacl *tableACL) LoadTablePrivFromMysqlBase(newACL func([]string) (acl.ACL,
return buildACLEntriesFromPrivMap(privMap, newACL)
}

// LoadGlobalFromMysqlBase implement global-level authority authentication
func (tacl *tableACL) LoadGlobalFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
// loadGlobalFromMysqlBase implement global-level authority authentication
func (tacl *TableACL) loadGlobalFromMysqlBase(newACL func([]string) (acl.ACL, error)) (aclEntries, error) {
ctx := context.Background()
entries := aclEntries{}
conn, err := tacl.conns.Get(ctx, nil)
defer conn.Recycle()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -474,20 +542,20 @@ func load(config *tableaclpb.Config, newACL func([]string) (acl.ACL, error)) (en
return entries, nil
}

func (tacl *tableACL) aclFactory() (acl.Factory, error) {
func (tacl *TableACL) aclFactory() (acl.Factory, error) {
if tacl.factory == nil {
return GetCurrentACLFactory()
}
return tacl.factory, nil
}

// LoadFromMysql construct aclEntries and call callback function to clear plan cache.
func (tacl *tableACL) LoadFromMysql(config *tableaclpb.Config) error {
func (tacl *TableACL) LoadFromMysql(config *tableaclpb.Config) error {
factory, err := tacl.aclFactory()
if err != nil {
return err
}
entries, err := tacl.LoadFromMysqlBase(factory.New)
entries, err := tacl.loadFromMysqlBase(factory.New)
if err != nil {
return err
}
Expand All @@ -504,7 +572,7 @@ func (tacl *tableACL) LoadFromMysql(config *tableaclpb.Config) error {
}
return nil
}
func (tacl *tableACL) Set(config *tableaclpb.Config) error {
func (tacl *TableACL) Set(config *tableaclpb.Config) error {
factory, err := tacl.aclFactory()
if err != nil {
return err
Expand All @@ -526,7 +594,7 @@ func (tacl *tableACL) Set(config *tableaclpb.Config) error {

// Valid returns whether the tableACL is valid.
// Currently it only checks that it has been initialized.
func (tacl *tableACL) Valid() bool {
func (tacl *TableACL) Valid() bool {
tacl.RLock()
defer tacl.RUnlock()
return tacl.entries != nil
Expand Down Expand Up @@ -572,7 +640,7 @@ func AuthorizedList(table string, role Role) []*ACLResult {
return currentTableACL.AuthorizedList(table, role)
}

func (tacl *tableACL) AuthorizedList(table string, role Role) []*ACLResult {
func (tacl *TableACL) AuthorizedList(table string, role Role) []*ACLResult {
tacl.RLock()
defer tacl.RUnlock()
var entries []*ACLResult
Expand All @@ -591,7 +659,7 @@ func (tacl *tableACL) AuthorizedList(table string, role Role) []*ACLResult {
return entries
}

func (tacl *tableACL) Authorized(table string, role Role) *ACLResult {
func (tacl *TableACL) Authorized(table string, role Role) *ACLResult {
tacl.RLock()
defer tacl.RUnlock()
start := 0
Expand Down Expand Up @@ -625,7 +693,11 @@ func GetCurrentConfig() *tableaclpb.Config {
return currentTableACL.Config()
}

func (tacl *tableACL) Config() *tableaclpb.Config {
func GetCurrentACL() *TableACL {
return &currentTableACL
}

func (tacl *TableACL) Config() *tableaclpb.Config {
tacl.RLock()
defer tacl.RUnlock()
return proto.Clone(tacl.config).(*tableaclpb.Config)
Expand Down
Loading

0 comments on commit 15518e8

Please sign in to comment.