vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/planbuilder/permission.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package planbuilder
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"vitess.io/vitess/go/vt/sqlparser"
    23  	"vitess.io/vitess/go/vt/tableacl"
    24  )
    25  
    26  // Permission associates the required access permission
    27  // for each table.
    28  type Permission struct {
    29  	TableName string
    30  	Role      tableacl.Role
    31  }
    32  
    33  // BuildPermissions builds the list of required permissions for all the
    34  // tables referenced in a query.
    35  func BuildPermissions(stmt sqlparser.Statement) []Permission {
    36  	var permissions []Permission
    37  	// All Statement types myst be covered here.
    38  	switch node := stmt.(type) {
    39  	case *sqlparser.Union, *sqlparser.Select:
    40  		permissions = buildSubqueryPermissions(node, tableacl.READER, permissions)
    41  	case *sqlparser.Insert:
    42  		permissions = buildTableNamePermissions(node.Table, tableacl.WRITER, permissions)
    43  		permissions = buildSubqueryPermissions(node, tableacl.READER, permissions)
    44  	case *sqlparser.Update:
    45  		permissions = buildTableExprsPermissions(node.TableExprs, tableacl.WRITER, permissions)
    46  		permissions = buildSubqueryPermissions(node, tableacl.READER, permissions)
    47  	case *sqlparser.Delete:
    48  		permissions = buildTableExprsPermissions(node.TableExprs, tableacl.WRITER, permissions)
    49  		permissions = buildSubqueryPermissions(node, tableacl.READER, permissions)
    50  	case sqlparser.DDLStatement:
    51  		for _, t := range node.AffectedTables() {
    52  			permissions = buildTableNamePermissions(t, tableacl.ADMIN, permissions)
    53  		}
    54  	case
    55  		*sqlparser.AlterMigration,
    56  		*sqlparser.RevertMigration,
    57  		*sqlparser.ShowMigrationLogs,
    58  		*sqlparser.ShowThrottledApps,
    59  		*sqlparser.ShowThrottlerStatus:
    60  		permissions = []Permission{} // TODO(shlomi) what are the correct permissions here? Table is unknown
    61  	case *sqlparser.Flush:
    62  		for _, t := range node.TableNames {
    63  			permissions = buildTableNamePermissions(t, tableacl.ADMIN, permissions)
    64  		}
    65  	case *sqlparser.OtherAdmin, *sqlparser.CallProc, *sqlparser.Begin, *sqlparser.Commit, *sqlparser.Rollback,
    66  		*sqlparser.Load, *sqlparser.Savepoint, *sqlparser.Release, *sqlparser.SRollback, *sqlparser.Set, *sqlparser.Show,
    67  		*sqlparser.OtherRead, sqlparser.Explain:
    68  		// no op
    69  	default:
    70  		panic(fmt.Errorf("BUG: unexpected statement type: %T", node))
    71  	}
    72  	return permissions
    73  }
    74  
    75  func buildSubqueryPermissions(stmt sqlparser.Statement, role tableacl.Role, permissions []Permission) []Permission {
    76  	_ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) {
    77  		switch node := node.(type) {
    78  		case *sqlparser.Select:
    79  			permissions = buildTableExprsPermissions(node.From, role, permissions)
    80  		case sqlparser.TableExprs:
    81  			return false, nil
    82  		}
    83  		return true, nil
    84  	}, stmt)
    85  	return permissions
    86  }
    87  
    88  func buildTableExprsPermissions(node sqlparser.TableExprs, role tableacl.Role, permissions []Permission) []Permission {
    89  	for _, node := range node {
    90  		permissions = buildTableExprPermissions(node, role, permissions)
    91  	}
    92  	return permissions
    93  }
    94  
    95  func buildTableExprPermissions(node sqlparser.TableExpr, role tableacl.Role, permissions []Permission) []Permission {
    96  	switch node := node.(type) {
    97  	case *sqlparser.AliasedTableExpr:
    98  		// An AliasedTableExpr can also be a subquery, but we should skip them here
    99  		// because the buildSubQueryPermissions walker will catch them and extract
   100  		// the corresponding table names.
   101  		switch node := node.Expr.(type) {
   102  		case sqlparser.TableName:
   103  			permissions = buildTableNamePermissions(node, role, permissions)
   104  		case *sqlparser.DerivedTable:
   105  			permissions = buildSubqueryPermissions(node.Select, role, permissions)
   106  		}
   107  	case *sqlparser.ParenTableExpr:
   108  		permissions = buildTableExprsPermissions(node.Exprs, role, permissions)
   109  	case *sqlparser.JoinTableExpr:
   110  		permissions = buildTableExprPermissions(node.LeftExpr, role, permissions)
   111  		permissions = buildTableExprPermissions(node.RightExpr, role, permissions)
   112  	}
   113  	return permissions
   114  }
   115  
   116  func buildTableNamePermissions(node sqlparser.TableName, role tableacl.Role, permissions []Permission) []Permission {
   117  	permissions = append(permissions, Permission{
   118  		TableName: node.Name.String(),
   119  		Role:      role,
   120  	})
   121  	return permissions
   122  }