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 }