diff --git a/docs/generated/sql/bnf/drop_owned_by_stmt.bnf b/docs/generated/sql/bnf/drop_owned_by_stmt.bnf index 9ace203cbdcc..5207ec50dbe4 100644 --- a/docs/generated/sql/bnf/drop_owned_by_stmt.bnf +++ b/docs/generated/sql/bnf/drop_owned_by_stmt.bnf @@ -1,2 +1,2 @@ drop_owned_by_stmt ::= - 'DROP' 'OWNED' 'BY' name_list opt_drop_behavior + 'DROP' 'OWNED' 'BY' role_spec_list opt_drop_behavior diff --git a/docs/generated/sql/bnf/grant_stmt.bnf b/docs/generated/sql/bnf/grant_stmt.bnf index 18bbf14d8b26..c532da5452f9 100644 --- a/docs/generated/sql/bnf/grant_stmt.bnf +++ b/docs/generated/sql/bnf/grant_stmt.bnf @@ -1,6 +1,6 @@ grant_stmt ::= - 'GRANT' 'ALL' 'PRIVILEGES' 'ON' targets 'TO' name_list - | 'GRANT' 'ALL' 'ON' targets 'TO' name_list - | 'GRANT' privilege_list 'ON' targets 'TO' name_list - | 'GRANT' privilege_list 'TO' name_list - | 'GRANT' privilege_list 'TO' name_list 'WITH' 'ADMIN' 'OPTION' + 'GRANT' 'ALL' 'PRIVILEGES' 'ON' targets 'TO' role_spec_list + | 'GRANT' 'ALL' 'ON' targets 'TO' role_spec_list + | 'GRANT' privilege_list 'ON' targets 'TO' role_spec_list + | 'GRANT' privilege_list 'TO' role_spec_list + | 'GRANT' privilege_list 'TO' role_spec_list 'WITH' 'ADMIN' 'OPTION' diff --git a/docs/generated/sql/bnf/reassign_owned_by_stmt.bnf b/docs/generated/sql/bnf/reassign_owned_by_stmt.bnf index 9eb4edc91f3d..ead3d8cfdecc 100644 --- a/docs/generated/sql/bnf/reassign_owned_by_stmt.bnf +++ b/docs/generated/sql/bnf/reassign_owned_by_stmt.bnf @@ -1,2 +1,2 @@ reassign_owned_by_stmt ::= - 'REASSIGN' 'OWNED' 'BY' name_list 'TO' role_spec + 'REASSIGN' 'OWNED' 'BY' role_spec_list 'TO' role_spec diff --git a/docs/generated/sql/bnf/revoke_stmt.bnf b/docs/generated/sql/bnf/revoke_stmt.bnf index 4936de4a208e..4f23347ed806 100644 --- a/docs/generated/sql/bnf/revoke_stmt.bnf +++ b/docs/generated/sql/bnf/revoke_stmt.bnf @@ -1,6 +1,6 @@ revoke_stmt ::= - 'REVOKE' 'ALL' 'PRIVILEGES' 'ON' targets 'FROM' name_list - | 'REVOKE' 'ALL' 'ON' targets 'FROM' name_list - | 'REVOKE' privilege_list 'ON' targets 'FROM' name_list - | 'REVOKE' privilege_list 'FROM' name_list - | 'REVOKE' 'ADMIN' 'OPTION' 'FOR' privilege_list 'FROM' name_list + 'REVOKE' 'ALL' 'PRIVILEGES' 'ON' targets 'FROM' role_spec_list + | 'REVOKE' 'ALL' 'ON' targets 'FROM' role_spec_list + | 'REVOKE' privilege_list 'ON' targets 'FROM' role_spec_list + | 'REVOKE' privilege_list 'FROM' role_spec_list + | 'REVOKE' 'ADMIN' 'OPTION' 'FOR' privilege_list 'FROM' role_spec_list diff --git a/docs/generated/sql/bnf/show_grants_stmt.bnf b/docs/generated/sql/bnf/show_grants_stmt.bnf index bb72048cb30a..149afc63df76 100644 --- a/docs/generated/sql/bnf/show_grants_stmt.bnf +++ b/docs/generated/sql/bnf/show_grants_stmt.bnf @@ -1,11 +1,11 @@ show_grants_stmt ::= - 'SHOW' 'GRANTS' 'ON' 'ROLE' name ( ( ',' name ) )* 'FOR' name ( ( ',' name ) )* - | 'SHOW' 'GRANTS' 'ON' 'ROLE' name ( ( ',' name ) )* - | 'SHOW' 'GRANTS' 'ON' 'SCHEMA' schema_name ( ( ',' schema_name ) )* 'FOR' name ( ( ',' name ) )* + 'SHOW' 'GRANTS' 'ON' 'ROLE' role_spec_list 'FOR' role_spec_list + | 'SHOW' 'GRANTS' 'ON' 'ROLE' role_spec_list + | 'SHOW' 'GRANTS' 'ON' 'SCHEMA' schema_name ( ( ',' schema_name ) )* 'FOR' role_spec_list | 'SHOW' 'GRANTS' 'ON' 'SCHEMA' schema_name ( ( ',' schema_name ) )* - | 'SHOW' 'GRANTS' 'ON' 'TYPE' type_name ( ( ',' type_name ) )* 'FOR' name ( ( ',' name ) )* + | 'SHOW' 'GRANTS' 'ON' 'TYPE' type_name ( ( ',' type_name ) )* 'FOR' role_spec_list | 'SHOW' 'GRANTS' 'ON' 'TYPE' type_name ( ( ',' type_name ) )* - | 'SHOW' 'GRANTS' 'ON' ( | 'TABLE' table_name ( ( ',' table_name ) )* | 'DATABASE' database_name ( ( ',' database_name ) )* ) 'FOR' name ( ( ',' name ) )* + | 'SHOW' 'GRANTS' 'ON' ( | 'TABLE' table_name ( ( ',' table_name ) )* | 'DATABASE' database_name ( ( ',' database_name ) )* ) 'FOR' role_spec_list | 'SHOW' 'GRANTS' 'ON' ( | 'TABLE' table_name ( ( ',' table_name ) )* | 'DATABASE' database_name ( ( ',' database_name ) )* ) - | 'SHOW' 'GRANTS' 'FOR' name ( ( ',' name ) )* + | 'SHOW' 'GRANTS' 'FOR' role_spec_list | 'SHOW' 'GRANTS' diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index cc7b11f7ded7..6b78c47b6366 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -74,32 +74,32 @@ discard_stmt ::= 'DISCARD' 'ALL' grant_stmt ::= - 'GRANT' privileges 'ON' targets 'TO' name_list - | 'GRANT' privilege_list 'TO' name_list - | 'GRANT' privilege_list 'TO' name_list 'WITH' 'ADMIN' 'OPTION' - | 'GRANT' privileges 'ON' 'TYPE' target_types 'TO' name_list - | 'GRANT' privileges 'ON' 'SCHEMA' schema_name_list 'TO' name_list - | 'GRANT' privileges 'ON' 'ALL' 'TABLES' 'IN' 'SCHEMA' schema_name_list 'TO' name_list + 'GRANT' privileges 'ON' targets 'TO' role_spec_list + | 'GRANT' privilege_list 'TO' role_spec_list + | 'GRANT' privilege_list 'TO' role_spec_list 'WITH' 'ADMIN' 'OPTION' + | 'GRANT' privileges 'ON' 'TYPE' target_types 'TO' role_spec_list + | 'GRANT' privileges 'ON' 'SCHEMA' schema_name_list 'TO' role_spec_list + | 'GRANT' privileges 'ON' 'ALL' 'TABLES' 'IN' 'SCHEMA' schema_name_list 'TO' role_spec_list prepare_stmt ::= 'PREPARE' table_alias_name prep_type_clause 'AS' preparable_stmt revoke_stmt ::= - 'REVOKE' privileges 'ON' targets 'FROM' name_list - | 'REVOKE' privilege_list 'FROM' name_list - | 'REVOKE' 'ADMIN' 'OPTION' 'FOR' privilege_list 'FROM' name_list - | 'REVOKE' privileges 'ON' 'TYPE' target_types 'FROM' name_list - | 'REVOKE' privileges 'ON' 'SCHEMA' schema_name_list 'FROM' name_list - | 'REVOKE' privileges 'ON' 'ALL' 'TABLES' 'IN' 'SCHEMA' schema_name_list 'FROM' name_list + 'REVOKE' privileges 'ON' targets 'FROM' role_spec_list + | 'REVOKE' privilege_list 'FROM' role_spec_list + | 'REVOKE' 'ADMIN' 'OPTION' 'FOR' privilege_list 'FROM' role_spec_list + | 'REVOKE' privileges 'ON' 'TYPE' target_types 'FROM' role_spec_list + | 'REVOKE' privileges 'ON' 'SCHEMA' schema_name_list 'FROM' role_spec_list + | 'REVOKE' privileges 'ON' 'ALL' 'TABLES' 'IN' 'SCHEMA' schema_name_list 'FROM' role_spec_list savepoint_stmt ::= 'SAVEPOINT' name reassign_owned_by_stmt ::= - 'REASSIGN' 'OWNED' 'BY' name_list 'TO' role_spec + 'REASSIGN' 'OWNED' 'BY' role_spec_list 'TO' role_spec drop_owned_by_stmt ::= - 'DROP' 'OWNED' 'BY' name_list opt_drop_behavior + 'DROP' 'OWNED' 'BY' role_spec_list opt_drop_behavior release_stmt ::= 'RELEASE' savepoint_name @@ -320,8 +320,8 @@ targets ::= | 'TENANT' iconst64 | 'DATABASE' name_list -name_list ::= - ( name ) ( ( ',' name ) )* +role_spec_list ::= + ( role_spec ) ( ( ',' role_spec ) )* privilege_list ::= ( privilege ) ( ( ',' privilege ) )* @@ -337,7 +337,8 @@ prep_type_clause ::= | role_spec ::= - username_or_sconst + 'identifier' + | unreserved_keyword | 'CURRENT_USER' | 'SESSION_USER' @@ -808,6 +809,9 @@ db_object_name ::= simple_db_object_name | complex_db_object_name +name_list ::= + ( name ) ( ( ',' name ) )* + opt_with ::= 'WITH' | @@ -1287,10 +1291,6 @@ qualifiable_schema_name ::= type_list ::= ( typename ) ( ( ',' typename ) )* -username_or_sconst ::= - non_reserved_word - | 'SCONST' - transaction_mode_list ::= ( transaction_mode ) ( ( opt_comma transaction_mode ) )* @@ -1625,7 +1625,7 @@ opt_on_targets_roles ::= | for_grantee_clause ::= - 'FOR' name_list + 'FOR' role_spec_list | opt_schedule_executor_type ::= @@ -1662,7 +1662,7 @@ partition_name ::= unrestricted_name opt_for_roles ::= - 'FOR' role_or_group_or_user name_list + 'FOR' role_or_group_or_user role_spec_list | relation_expr ::= @@ -1711,12 +1711,6 @@ typename ::= simple_typename opt_array_bounds | simple_typename 'ARRAY' -non_reserved_word ::= - 'identifier' - | unreserved_keyword - | col_name_keyword - | type_func_name_keyword - transaction_mode ::= transaction_user_priority | transaction_read_mode @@ -1864,11 +1858,11 @@ opt_in_schemas ::= | abbreviated_grant_stmt ::= - 'GRANT' privileges 'ON' alter_default_privileges_target_object 'TO' name_list opt_with_grant_option + 'GRANT' privileges 'ON' alter_default_privileges_target_object 'TO' role_spec_list opt_with_grant_option abbreviated_revoke_stmt ::= - 'REVOKE' privileges 'ON' alter_default_privileges_target_object 'FROM' name_list opt_drop_behavior - | 'REVOKE' 'GRANT' 'OPTION' 'FOR' privileges 'ON' alter_default_privileges_target_object 'FROM' name_list opt_drop_behavior + 'REVOKE' privileges 'ON' alter_default_privileges_target_object 'FROM' role_spec_list opt_drop_behavior + | 'REVOKE' 'GRANT' 'OPTION' 'FOR' privileges 'ON' alter_default_privileges_target_object 'FROM' role_spec_list opt_drop_behavior role_options ::= ( role_option ) ( ( role_option ) )* @@ -2085,6 +2079,12 @@ table_index_name_list ::= table_name_list ::= ( table_name ) ( ( ',' table_name ) )* +non_reserved_word ::= + 'identifier' + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + kv_option ::= name '=' string_or_placeholder | name @@ -2166,7 +2166,7 @@ extra_var_value ::= | cockroachdb_extra_reserved_keyword targets_roles ::= - 'ROLE' name_list + 'ROLE' role_spec_list | 'SCHEMA' schema_name_list | 'TYPE' type_name_list | targets diff --git a/pkg/ccl/importccl/read_import_pgdump.go b/pkg/ccl/importccl/read_import_pgdump.go index 360a9a40cd88..e8be4686185b 100644 --- a/pkg/ccl/importccl/read_import_pgdump.go +++ b/pkg/ccl/importccl/read_import_pgdump.go @@ -35,6 +35,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/row" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util" "github.com/cockroachdb/cockroach/pkg/util/ctxgroup" @@ -241,14 +242,14 @@ func createPostgresSchemas( parentID descpb.ID, schemasToCreate map[string]*tree.CreateSchema, execCfg *sql.ExecutorConfig, - user security.SQLUsername, + sessionData *sessiondata.SessionData, ) ([]*schemadesc.Mutable, error) { createSchema := func( ctx context.Context, txn *kv.Txn, descriptors *descs.Collection, dbDesc catalog.DatabaseDescriptor, schema *tree.CreateSchema, ) (*schemadesc.Mutable, error) { desc, _, err := sql.CreateUserDefinedSchemaDescriptor( - ctx, user, schema, txn, descriptors, execCfg, dbDesc, false, /* allocateID */ + ctx, sessionData, schema, txn, descriptors, execCfg, dbDesc, false, /* allocateID */ ) if err != nil { return nil, err @@ -494,7 +495,7 @@ func readPostgresCreateTable( tables := make([]*tabledesc.Mutable, 0, len(schemaObjects.createTbl)) schemaNameToDesc := make(map[string]*schemadesc.Mutable) schemaDescs, err := createPostgresSchemas(ctx, parentDB.GetID(), schemaObjects.createSchema, - p.ExecCfg(), p.User()) + p.ExecCfg(), p.SessionData()) if err != nil { return nil, nil, err } diff --git a/pkg/cmd/docgen/diagrams.go b/pkg/cmd/docgen/diagrams.go index 56e235c3d1e3..5121d2c992ae 100644 --- a/pkg/cmd/docgen/diagrams.go +++ b/pkg/cmd/docgen/diagrams.go @@ -652,7 +652,7 @@ var specs = []stmtSpec{ }, { name: "create_schedule_for_backup_stmt", - inline: []string{"opt_description", "string_or_placeholder_opt_list", "string_or_placeholder_list", "opt_with_backup_options", "cron_expr", "opt_full_backup_clause", "opt_with_schedule_options", "opt_backup_targets"}, + inline: []string{"string_or_placeholder_opt_list", "string_or_placeholder_list", "opt_with_backup_options", "cron_expr", "opt_full_backup_clause", "opt_with_schedule_options", "opt_backup_targets"}, replace: map[string]string{ "string_or_placeholder 'FOR'": "label 'FOR'", "'RECURRING' sconst_or_placeholder": "'RECURRING' cronexpr", diff --git a/pkg/sql/alter_database.go b/pkg/sql/alter_database.go index 7501f222ff75..15dbb94c80ee 100644 --- a/pkg/sql/alter_database.go +++ b/pkg/sql/alter_database.go @@ -64,7 +64,10 @@ func (p *planner) AlterDatabaseOwner( } func (n *alterDatabaseOwnerNode) startExec(params runParams) error { - newOwner := n.n.Owner + newOwner, err := n.n.Owner.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } oldOwner := n.desc.GetPrivileges().Owner() if err := params.p.checkCanAlterToNewOwner(params.ctx, n.desc, newOwner); err != nil { diff --git a/pkg/sql/alter_default_privileges.go b/pkg/sql/alter_default_privileges.go index d514c29e1770..086b322cd11e 100644 --- a/pkg/sql/alter_default_privileges.go +++ b/pkg/sql/alter_default_privileges.go @@ -14,7 +14,6 @@ import ( "context" "github.com/cockroachdb/cockroach/pkg/clusterversion" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/catalog/catprivilege" "github.com/cockroachdb/cockroach/pkg/sql/catalog/dbdesc" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" @@ -77,7 +76,7 @@ func (p *planner) alterDefaultPrivileges( } func (n *alterDefaultPrivilegesNode) startExec(params runParams) error { - targetRoles, err := n.n.Roles.ToSQLUsernames() + targetRoles, err := n.n.Roles.ToSQLUsernames(params.SessionData()) if err != nil { return err } @@ -99,13 +98,9 @@ func (n *alterDefaultPrivilegesNode) startExec(params runParams) error { objectType = n.n.Revoke.Target } - granteeSQLUsernames := make([]security.SQLUsername, len(grantees)) - for i, grantee := range grantees { - user, err := security.MakeSQLUsernameFromUserInput(string(grantee), security.UsernameValidation) - if err != nil { - return err - } - granteeSQLUsernames[i] = user + granteeSQLUsernames, err := grantees.ToSQLUsernames(params.p.SessionData()) + if err != nil { + return err } if err := params.p.validateRoles(params.ctx, granteeSQLUsernames, true /* isPublicValid */); err != nil { @@ -162,7 +157,7 @@ func (n *alterDefaultPrivilegesNode) startExec(params runParams) error { } var events []eventLogEntry - granteeSQLUsernames, err = grantees.ToSQLUsernames() + granteeSQLUsernames, err = grantees.ToSQLUsernames(params.SessionData()) if err != nil { return err } diff --git a/pkg/sql/alter_schema.go b/pkg/sql/alter_schema.go index a07de13ad428..8bb4f35f9cb5 100644 --- a/pkg/sql/alter_schema.go +++ b/pkg/sql/alter_schema.go @@ -118,7 +118,10 @@ func (n *alterSchemaNode) startExec(params runParams) error { NewSchemaName: newQualifiedSchemaName.String(), }) case *tree.AlterSchemaOwner: - newOwner := t.Owner + newOwner, err := t.Owner.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } return params.p.alterSchemaOwner( params.ctx, n.desc, newOwner, tree.AsStringWithFQNames(n.n, params.Ann()), ) diff --git a/pkg/sql/alter_table_owner.go b/pkg/sql/alter_table_owner.go index b6b0825e4c07..16ec5d545d96 100644 --- a/pkg/sql/alter_table_owner.go +++ b/pkg/sql/alter_table_owner.go @@ -63,8 +63,12 @@ func (p *planner) AlterTableOwner(ctx context.Context, n *tree.AlterTableOwner) return nil, err } + owner, err := n.Owner.ToSQLUsername(p.SessionData()) + if err != nil { + return nil, err + } return &alterTableOwnerNode{ - owner: n.Owner, + owner: owner, desc: tableDesc, n: n, prefix: prefix, diff --git a/pkg/sql/alter_type.go b/pkg/sql/alter_type.go index a8109cf3d658..55c08d019412 100644 --- a/pkg/sql/alter_type.go +++ b/pkg/sql/alter_type.go @@ -111,7 +111,11 @@ func (n *alterTypeNode) startExec(params runParams) error { // See https://github.com/cockroachdb/cockroach/issues/57741 err = params.p.setTypeSchema(params.ctx, n, string(t.Schema)) case *tree.AlterTypeOwner: - if err = params.p.alterTypeOwner(params.ctx, n, t.Owner); err != nil { + owner, err := t.Owner.ToSQLUsername(params.SessionData()) + if err != nil { + return err + } + if err = params.p.alterTypeOwner(params.ctx, n, owner); err != nil { return err } eventLogDone = true // done inside alterTypeOwner(). diff --git a/pkg/sql/create_schema.go b/pkg/sql/create_schema.go index b62bc4647a4e..e9dd9b41d379 100644 --- a/pkg/sql/create_schema.go +++ b/pkg/sql/create_schema.go @@ -16,7 +16,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/kv" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/catalog" "github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkeys" "github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkv" @@ -27,6 +26,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/privilege" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" "github.com/cockroachdb/cockroach/pkg/sql/sqlerrors" "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" @@ -43,7 +43,7 @@ func (n *createSchemaNode) startExec(params runParams) error { // CreateUserDefinedSchemaDescriptor constructs a mutable schema descriptor. func CreateUserDefinedSchemaDescriptor( ctx context.Context, - user security.SQLUsername, + sessionData *sessiondata.SessionData, n *tree.CreateSchema, txn *kv.Txn, descriptors *descs.Collection, @@ -51,9 +51,14 @@ func CreateUserDefinedSchemaDescriptor( db catalog.DatabaseDescriptor, allocateID bool, ) (*schemadesc.Mutable, *descpb.PrivilegeDescriptor, error) { + authRole, err := n.AuthRole.ToSQLUsername(sessionData) + if err != nil { + return nil, nil, err + } + user := sessionData.User() var schemaName string if !n.Schema.ExplicitSchema { - schemaName = n.AuthRole.Normalized() + schemaName = authRole.Normalized() } else { schemaName = n.Schema.Schema() } @@ -109,7 +114,7 @@ func CreateUserDefinedSchemaDescriptor( ) if !n.AuthRole.Undefined() { - exists, err := RoleExists(ctx, execCfg, txn, n.AuthRole) + exists, err := RoleExists(ctx, execCfg, txn, authRole) if err != nil { return nil, nil, err } @@ -117,7 +122,7 @@ func CreateUserDefinedSchemaDescriptor( return nil, nil, pgerror.Newf(pgcode.UndefinedObject, "role/user %q does not exist", n.AuthRole) } - privs.SetOwner(n.AuthRole) + privs.SetOwner(authRole) } else { privs.SetOwner(user) } @@ -170,7 +175,7 @@ func (p *planner) createUserDefinedSchema(params runParams, n *tree.CreateSchema return err } - desc, privs, err := CreateUserDefinedSchemaDescriptor(params.ctx, params.SessionData().User(), n, + desc, privs, err := CreateUserDefinedSchemaDescriptor(params.ctx, params.SessionData(), n, p.Txn(), p.Descriptors(), p.ExecCfg(), db, true /* allocateID */) if err != nil { return err diff --git a/pkg/sql/delegate/BUILD.bazel b/pkg/sql/delegate/BUILD.bazel index de248e693472..b5fae2c87a00 100644 --- a/pkg/sql/delegate/BUILD.bazel +++ b/pkg/sql/delegate/BUILD.bazel @@ -40,7 +40,6 @@ go_library( "//pkg/jobs", "//pkg/jobs/jobspb", "//pkg/keys", - "//pkg/security", "//pkg/settings", "//pkg/sql/catalog/catconstants", "//pkg/sql/catalog/colinfo", diff --git a/pkg/sql/delegate/show_default_privileges.go b/pkg/sql/delegate/show_default_privileges.go index de182509fc0c..381bad7dcc87 100644 --- a/pkg/sql/delegate/show_default_privileges.go +++ b/pkg/sql/delegate/show_default_privileges.go @@ -33,7 +33,7 @@ func (d *delegator) delegateShowDefaultPrivileges( if n.ForAllRoles { query += " AND for_all_roles=true" } else if len(n.Roles) > 0 { - targetRoles, err := n.Roles.ToSQLUsernames() + targetRoles, err := n.Roles.ToSQLUsernames(d.evalCtx.SessionData()) if err != nil { return nil, err } diff --git a/pkg/sql/delegate/show_grants.go b/pkg/sql/delegate/show_grants.go index 7cb5e3fe1909..a4d90a7ca3bc 100644 --- a/pkg/sql/delegate/show_grants.go +++ b/pkg/sql/delegate/show_grants.go @@ -15,7 +15,6 @@ import ( "fmt" "strings" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/lexbase" "github.com/cockroachdb/cockroach/pkg/sql/opt/cat" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" @@ -228,8 +227,12 @@ FROM "".information_schema.type_privileges` if n.Grantees != nil { params = params[:0] - for _, grantee := range n.Grantees.ToStrings() { - params = append(params, lexbase.EscapeSQLString(grantee)) + grantees, err := n.Grantees.ToSQLUsernames(d.evalCtx.SessionData()) + if err != nil { + return nil, err + } + for _, grantee := range grantees { + params = append(params, lexbase.EscapeSQLString(grantee.Normalized())) } fmt.Fprintf(&cond, ` AND grantee IN (%s)`, strings.Join(params, ",")) } @@ -239,7 +242,8 @@ FROM "".information_schema.type_privileges` // Terminate on invalid users. for _, p := range n.Grantees { - user, err := security.MakeSQLUsernameFromUserInput(string(p), security.UsernameValidation) + + user, err := p.ToSQLUsername(d.evalCtx.SessionData()) if err != nil { return nil, err } diff --git a/pkg/sql/delegate/show_role_grants.go b/pkg/sql/delegate/show_role_grants.go index afabfe720864..21c27007adc0 100644 --- a/pkg/sql/delegate/show_role_grants.go +++ b/pkg/sql/delegate/show_role_grants.go @@ -34,8 +34,12 @@ SELECT role AS role_name, if n.Roles != nil { var roles []string - for _, r := range n.Roles.ToStrings() { - roles = append(roles, lexbase.EscapeSQLString(r)) + sqlUsernames, err := n.Roles.ToSQLUsernames(d.evalCtx.SessionData()) + if err != nil { + return nil, err + } + for _, r := range sqlUsernames { + roles = append(roles, lexbase.EscapeSQLString(r.Normalized())) } fmt.Fprintf(&query, ` WHERE "role" IN (%s)`, strings.Join(roles, ",")) } @@ -50,8 +54,12 @@ SELECT role AS role_name, } var grantees []string - for _, g := range n.Grantees.ToStrings() { - grantees = append(grantees, lexbase.EscapeSQLString(g)) + granteeSQLUsernames, err := n.Grantees.ToSQLUsernames(d.evalCtx.SessionData()) + if err != nil { + return nil, err + } + for _, g := range granteeSQLUsernames { + grantees = append(grantees, lexbase.EscapeSQLString(g.Normalized())) } fmt.Fprintf(&query, ` member IN (%s)`, strings.Join(grantees, ",")) diff --git a/pkg/sql/grant_revoke.go b/pkg/sql/grant_revoke.go index 94174b28dfb9..00af336f9274 100644 --- a/pkg/sql/grant_revoke.go +++ b/pkg/sql/grant_revoke.go @@ -47,7 +47,7 @@ func (p *planner) Grant(ctx context.Context, n *tree.Grant) (planNode, error) { return nil, err } - grantees, err := n.Grantees.ToSQLUsernames() + grantees, err := n.Grantees.ToSQLUsernames(p.SessionData()) if err != nil { return nil, err } @@ -77,7 +77,7 @@ func (p *planner) Revoke(ctx context.Context, n *tree.Revoke) (planNode, error) return nil, err } - grantees, err := n.Grantees.ToSQLUsernames() + grantees, err := n.Grantees.ToSQLUsernames(p.SessionData()) if err != nil { return nil, err } @@ -105,7 +105,7 @@ type changePrivilegesNode struct { // granteesNameList is used for creating an AST node for alter default // privileges inside changePrivilegesNode's startExec. // This is required for getting the pre-normalized name to construct the AST. - granteesNameList tree.NameList + granteesNameList tree.RoleSpecList } // ReadingOwnWrites implements the planNodeReadingOwnWrites interface. diff --git a/pkg/sql/grant_role.go b/pkg/sql/grant_role.go index aa14723458b5..3011297c0909 100644 --- a/pkg/sql/grant_role.go +++ b/pkg/sql/grant_role.go @@ -60,21 +60,13 @@ func (p *planner) GrantRoleNode(ctx context.Context, n *tree.GrantRole) (*GrantR return nil, err } - inputRoles := make([]security.SQLUsername, len(n.Roles)) - inputMembers := make([]security.SQLUsername, len(n.Members)) - for i, role := range n.Roles { - normalizedRole, err := security.MakeSQLUsernameFromUserInput(string(role), security.UsernameValidation) - if err != nil { - return nil, err - } - inputRoles[i] = normalizedRole + inputRoles, err := n.Roles.ToSQLUsernames() + if err != nil { + return nil, err } - for i, member := range n.Members { - normalizedMember, err := security.MakeSQLUsernameFromUserInput(string(member), security.UsernameValidation) - if err != nil { - return nil, err - } - inputMembers[i] = normalizedMember + inputMembers, err := n.Members.ToSQLUsernames(p.SessionData()) + if err != nil { + return nil, err } for _, r := range inputRoles { diff --git a/pkg/sql/logictest/testdata/logic_test/alter_schema_owner b/pkg/sql/logictest/testdata/logic_test/alter_schema_owner index 24e637db31db..5c6d07c666b1 100644 --- a/pkg/sql/logictest/testdata/logic_test/alter_schema_owner +++ b/pkg/sql/logictest/testdata/logic_test/alter_schema_owner @@ -54,3 +54,22 @@ query T SELECT pg_get_userbyid(nspowner) FROM pg_namespace WHERE nspname = 's'; ---- testuser2 + +statement ok +ALTER SCHEMA s OWNER TO CURRENT_USER + +query T +SELECT pg_get_userbyid(nspowner) FROM pg_namespace WHERE nspname = 's'; +---- +testuser + +statement ok +ALTER SCHEMA s OWNER TO testuser2 + +statement ok +ALTER SCHEMA s OWNER TO SESSION_USER + +query T +SELECT pg_get_userbyid(nspowner) FROM pg_namespace WHERE nspname = 's'; +---- +testuser diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 7578526c43bc..d800088f634f 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -266,6 +266,12 @@ func (u *sqlSymUnion) strPtr() *string { func (u *sqlSymUnion) strs() []string { return u.val.([]string) } +func (u *sqlSymUnion) roleSpec() tree.RoleSpec { + return u.val.(tree.RoleSpec) +} +func (u *sqlSymUnion) roleSpecList() tree.RoleSpecList { + return u.val.(tree.RoleSpecList) +} func (u *sqlSymUnion) user() security.SQLUsername { return u.val.(security.SQLUsername) } @@ -1326,10 +1332,8 @@ func (u *sqlSymUnion) setVar() *tree.SetVar { %type unrestricted_name type_function_name type_function_name_no_crdb_extra %type non_reserved_word %type non_reserved_word_or_sconst -%type username_or_sconst -// TODO(solon): The type for role_spec needs to be updated to fix -// https://github.com/cockroachdb/cockroach/issues/54696 -%type role_spec +%type role_spec +%type role_spec_list %type zone_value %type string_or_placeholder %type string_or_placeholder_list @@ -1374,7 +1378,7 @@ func (u *sqlSymUnion) setVar() *tree.SetVar { %type targets targets_roles target_types changefeed_targets %type <*tree.TargetList> opt_on_targets_roles opt_backup_targets -%type for_grantee_clause +%type for_grantee_clause %type privileges %type <[]tree.KVOption> opt_role_options role_options %type audit_mode @@ -1391,7 +1395,7 @@ func (u *sqlSymUnion) setVar() *tree.SetVar { %type role_or_group_or_user %type <*tree.ScheduleLabelSpec> schedule_label_spec -%type cron_expr opt_description sconst_or_placeholder +%type cron_expr sconst_or_placeholder %type <*tree.FullBackupClause> opt_full_backup_clause %type schedule_state %type opt_schedule_executor_type @@ -1685,7 +1689,7 @@ alter_database_stmt: alter_database_owner: ALTER DATABASE database_name OWNER TO role_spec { - $$.val = &tree.AlterDatabaseOwner{Name: tree.Name($3), Owner: $6.user()} + $$.val = &tree.AlterDatabaseOwner{Name: tree.Name($3), Owner: $6.roleSpec()} } // This form is an alias for ALTER ROLE ALL IN DATABASE SET ... @@ -2458,7 +2462,7 @@ alter_type_stmt: $$.val = &tree.AlterType{ Type: $3.unresolvedObjectName(), Cmd: &tree.AlterTypeOwner{ - Owner: $6.user(), + Owner: $6.roleSpec(), }, } } @@ -2493,33 +2497,41 @@ opt_add_val_placement: } role_spec: - username_or_sconst { $$.val = $1.user() } + IDENT + { + $$.val = tree.RoleSpec{ + RoleSpecType: tree.RoleName, + Name: $1, + } + } +| unreserved_keyword + { + $$.val = tree.RoleSpec{ + RoleSpecType: tree.RoleName, + Name: $1, + } + } | CURRENT_USER { - // This is incorrect, see https://github.com/cockroachdb/cockroach/issues/54696 - $$.val = security.MakeSQLUsernameFromPreNormalizedString($1) + $$.val = tree.RoleSpec{ + RoleSpecType: tree.CurrentUser, + } } | SESSION_USER { - // This is incorrect, see https://github.com/cockroachdb/cockroach/issues/54696 - $$.val = security.MakeSQLUsernameFromPreNormalizedString($1) + $$.val = tree.RoleSpec{ + RoleSpecType: tree.SessionUser, + } } -username_or_sconst: - non_reserved_word +role_spec_list: + role_spec { - // Username was entered as a SQL keyword, or as a SQL identifier - // already subject to case normalization and NFC reduction. - // (or is it? In fact, there is a bug here: https://github.com/cockroachdb/cockroach/issues/55396 - // which needs to be fixed to make this fully correct.) - $$.val = security.MakeSQLUsernameFromPreNormalizedString($1) + $$.val = tree.RoleSpecList{$1.roleSpec()} } -| SCONST +| role_spec_list ',' role_spec { - // We use UsernameValidation because username_or_sconst and role_spec - // are only used for usernames of existing accounts, not when - // creating new users or roles. - $$.val, _ = security.MakeSQLUsernameFromUserInput($1, security.UsernameValidation) + $$.val = append($1.roleSpecList(), $3.roleSpec()) } alter_attribute_action_list: @@ -2785,14 +2797,6 @@ create_schedule_for_backup_stmt: } | CREATE SCHEDULE error // SHOW HELP: CREATE SCHEDULE FOR BACKUP -opt_description: - string_or_placeholder -| /* EMPTY */ - { - $$.val = nil - } - - // sconst_or_placeholder matches a simple string, or a placeholder. sconst_or_placeholder: SCONST @@ -4289,37 +4293,37 @@ deallocate_stmt: // // %SeeAlso: REVOKE, WEBDOCS/grant.html grant_stmt: - GRANT privileges ON targets TO name_list + GRANT privileges ON targets TO role_spec_list { - $$.val = &tree.Grant{Privileges: $2.privilegeList(), Grantees: $6.nameList(), Targets: $4.targetList()} + $$.val = &tree.Grant{Privileges: $2.privilegeList(), Grantees: $6.roleSpecList(), Targets: $4.targetList()} } -| GRANT privilege_list TO name_list +| GRANT privilege_list TO role_spec_list { - $$.val = &tree.GrantRole{Roles: $2.nameList(), Members: $4.nameList(), AdminOption: false} + $$.val = &tree.GrantRole{Roles: $2.nameList(), Members: $4.roleSpecList(), AdminOption: false} } -| GRANT privilege_list TO name_list WITH ADMIN OPTION +| GRANT privilege_list TO role_spec_list WITH ADMIN OPTION { - $$.val = &tree.GrantRole{Roles: $2.nameList(), Members: $4.nameList(), AdminOption: true} + $$.val = &tree.GrantRole{Roles: $2.nameList(), Members: $4.roleSpecList(), AdminOption: true} } -| GRANT privileges ON TYPE target_types TO name_list +| GRANT privileges ON TYPE target_types TO role_spec_list { - $$.val = &tree.Grant{Privileges: $2.privilegeList(), Targets: $5.targetList(), Grantees: $7.nameList()} + $$.val = &tree.Grant{Privileges: $2.privilegeList(), Targets: $5.targetList(), Grantees: $7.roleSpecList()} } -| GRANT privileges ON SCHEMA schema_name_list TO name_list +| GRANT privileges ON SCHEMA schema_name_list TO role_spec_list { $$.val = &tree.Grant{ Privileges: $2.privilegeList(), Targets: tree.TargetList{ Schemas: $5.objectNamePrefixList(), }, - Grantees: $7.nameList(), + Grantees: $7.roleSpecList(), } } -| GRANT privileges ON SCHEMA schema_name_list TO name_list WITH error +| GRANT privileges ON SCHEMA schema_name_list TO role_spec_list WITH error { return unimplemented(sqllex, "grant privileges on schema with") } -| GRANT privileges ON ALL TABLES IN SCHEMA schema_name_list TO name_list +| GRANT privileges ON ALL TABLES IN SCHEMA schema_name_list TO role_spec_list { $$.val = &tree.Grant{ Privileges: $2.privilegeList(), @@ -4327,7 +4331,7 @@ grant_stmt: Schemas: $8.objectNamePrefixList(), AllTablesInSchema: true, }, - Grantees: $10.nameList(), + Grantees: $10.roleSpecList(), } } | GRANT privileges ON SEQUENCE error @@ -4356,33 +4360,33 @@ grant_stmt: // // %SeeAlso: GRANT, WEBDOCS/revoke.html revoke_stmt: - REVOKE privileges ON targets FROM name_list + REVOKE privileges ON targets FROM role_spec_list { - $$.val = &tree.Revoke{Privileges: $2.privilegeList(), Grantees: $6.nameList(), Targets: $4.targetList()} + $$.val = &tree.Revoke{Privileges: $2.privilegeList(), Grantees: $6.roleSpecList(), Targets: $4.targetList()} } -| REVOKE privilege_list FROM name_list +| REVOKE privilege_list FROM role_spec_list { - $$.val = &tree.RevokeRole{Roles: $2.nameList(), Members: $4.nameList(), AdminOption: false } + $$.val = &tree.RevokeRole{Roles: $2.nameList(), Members: $4.roleSpecList(), AdminOption: false } } -| REVOKE ADMIN OPTION FOR privilege_list FROM name_list +| REVOKE ADMIN OPTION FOR privilege_list FROM role_spec_list { - $$.val = &tree.RevokeRole{Roles: $5.nameList(), Members: $7.nameList(), AdminOption: true } + $$.val = &tree.RevokeRole{Roles: $5.nameList(), Members: $7.roleSpecList(), AdminOption: true } } -| REVOKE privileges ON TYPE target_types FROM name_list +| REVOKE privileges ON TYPE target_types FROM role_spec_list { - $$.val = &tree.Revoke{Privileges: $2.privilegeList(), Targets: $5.targetList(), Grantees: $7.nameList()} + $$.val = &tree.Revoke{Privileges: $2.privilegeList(), Targets: $5.targetList(), Grantees: $7.roleSpecList()} } -| REVOKE privileges ON SCHEMA schema_name_list FROM name_list +| REVOKE privileges ON SCHEMA schema_name_list FROM role_spec_list { $$.val = &tree.Revoke{ Privileges: $2.privilegeList(), Targets: tree.TargetList{ Schemas: $5.objectNamePrefixList(), }, - Grantees: $7.nameList(), + Grantees: $7.roleSpecList(), } } -| REVOKE privileges ON ALL TABLES IN SCHEMA schema_name_list FROM name_list +| REVOKE privileges ON ALL TABLES IN SCHEMA schema_name_list FROM role_spec_list { $$.val = &tree.Revoke{ Privileges: $2.privilegeList(), @@ -4390,7 +4394,7 @@ revoke_stmt: Schemas: $8.objectNamePrefixList(), AllTablesInSchema: true, }, - Grantees: $10.nameList(), + Grantees: $10.roleSpecList(), } } | REVOKE privileges ON SEQUENCE error @@ -4732,7 +4736,11 @@ set_rest_more: /* SKIP DOC */ $$.val = &tree.SetSessionAuthorizationDefault{} } -| SESSION AUTHORIZATION username_or_sconst +| SESSION AUTHORIZATION IDENT + { + return unimplementedWithIssue(sqllex, 40283) + } +| SESSION AUTHORIZATION SCONST { return unimplementedWithIssue(sqllex, 40283) } @@ -5164,7 +5172,7 @@ show_databases_stmt: show_default_privileges_stmt: SHOW DEFAULT PRIVILEGES opt_for_roles { $$.val = &tree.ShowDefaultPrivileges{ - Roles: $4.nameList(), + Roles: $4.roleSpecList(), } } | SHOW DEFAULT PRIVILEGES FOR ALL ROLES { @@ -5228,9 +5236,9 @@ show_grants_stmt: { lst := $3.targetListPtr() if lst != nil && lst.ForRoles { - $$.val = &tree.ShowRoleGrants{Roles: lst.Roles, Grantees: $4.nameList()} + $$.val = &tree.ShowRoleGrants{Roles: lst.Roles, Grantees: $4.roleSpecList()} } else { - $$.val = &tree.ShowGrants{Targets: lst, Grantees: $4.nameList()} + $$.val = &tree.ShowGrants{Targets: lst, Grantees: $4.roleSpecList()} } } | SHOW GRANTS error // SHOW HELP: SHOW GRANTS @@ -6089,9 +6097,9 @@ targets: // with a name list. This cannot be included in targets directly // because some statements must not recognize this syntax. targets_roles: - ROLE name_list + ROLE role_spec_list { - $$.val = tree.TargetList{ForRoles: true, Roles: $2.nameList()} + $$.val = tree.TargetList{ForRoles: true, Roles: $2.roleSpecList()} } | SCHEMA schema_name_list { @@ -6104,13 +6112,13 @@ targets_roles: | targets for_grantee_clause: - FOR name_list + FOR role_spec_list { - $$.val = $2.nameList() + $$.val = $2.roleSpecList() } | /* EMPTY */ { - $$.val = tree.NameList(nil) + $$.val = tree.RoleSpecList(nil) } @@ -6266,7 +6274,7 @@ create_schema_stmt: { $$.val = &tree.CreateSchema{ Schema: $3.objectNamePrefix(), - AuthRole: $5.user(), + AuthRole: $5.roleSpec(), } } | CREATE SCHEMA IF NOT EXISTS opt_schema_name AUTHORIZATION role_spec @@ -6274,7 +6282,7 @@ create_schema_stmt: $$.val = &tree.CreateSchema{ Schema: $6.objectNamePrefix(), IfNotExists: true, - AuthRole: $8.user(), + AuthRole: $8.roleSpec(), } } | CREATE SCHEMA error // SHOW HELP: CREATE SCHEMA @@ -6301,7 +6309,7 @@ alter_schema_stmt: $$.val = &tree.AlterSchema{ Schema: $3.objectNamePrefix(), Cmd: &tree.AlterSchemaOwner{ - Owner: $6.user(), + Owner: $6.roleSpec(), }, } } @@ -8039,7 +8047,7 @@ alter_table_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $3.unresolvedObjectName(), - Owner: $6.user(), + Owner: $6.roleSpec(), IfExists: false, } } @@ -8047,7 +8055,7 @@ alter_table_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $5.unresolvedObjectName(), - Owner: $8.user(), + Owner: $8.roleSpec(), IfExists: true, } } @@ -8091,7 +8099,7 @@ alter_view_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $3.unresolvedObjectName(), - Owner: $6.user(), + Owner: $6.roleSpec(), IfExists: false, IsView: true, } @@ -8100,7 +8108,7 @@ alter_view_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $4.unresolvedObjectName(), - Owner: $7.user(), + Owner: $7.roleSpec(), IfExists: false, IsView: true, IsMaterialized: true, @@ -8110,7 +8118,7 @@ alter_view_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $5.unresolvedObjectName(), - Owner: $8.user(), + Owner: $8.roleSpec(), IfExists: true, IsView: true, } @@ -8119,7 +8127,7 @@ alter_view_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $6.unresolvedObjectName(), - Owner: $9.user(), + Owner: $9.roleSpec(), IfExists: true, IsView: true, IsMaterialized: true, @@ -8145,7 +8153,7 @@ alter_sequence_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $3.unresolvedObjectName(), - Owner: $6.user(), + Owner: $6.roleSpec(), IfExists: false, IsSequence: true, } @@ -8154,7 +8162,7 @@ alter_sequence_owner_stmt: { $$.val = &tree.AlterTableOwner{ Name: $5.unresolvedObjectName(), - Owner: $8.user(), + Owner: $8.roleSpec(), IfExists: true, IsSequence: true, } @@ -8232,7 +8240,7 @@ alter_default_privileges_stmt: ALTER DEFAULT PRIVILEGES opt_for_roles opt_in_schemas abbreviated_grant_stmt { $$.val = &tree.AlterDefaultPrivileges{ - Roles: $4.nameList(), + Roles: $4.roleSpecList(), Schemas: $5.objectNamePrefixList(), Grant: $6.abbreviatedGrant(), IsGrant: true, @@ -8241,7 +8249,7 @@ alter_default_privileges_stmt: | ALTER DEFAULT PRIVILEGES opt_for_roles opt_in_schemas abbreviated_revoke_stmt { $$.val = &tree.AlterDefaultPrivileges{ - Roles: $4.nameList(), + Roles: $4.roleSpecList(), Schemas: $5.objectNamePrefixList(), Revoke: $6.abbreviatedRevoke(), IsGrant: false, @@ -8268,12 +8276,12 @@ alter_default_privileges_stmt: | ALTER DEFAULT PRIVILEGES error // SHOW HELP: ALTER DEFAULT PRIVILEGES abbreviated_grant_stmt: - GRANT privileges ON alter_default_privileges_target_object TO name_list opt_with_grant_option + GRANT privileges ON alter_default_privileges_target_object TO role_spec_list opt_with_grant_option { $$.val = tree.AbbreviatedGrant{ Privileges: $2.privilegeList(), Target: $4.alterDefaultPrivilegesTargetObject(), - Grantees: $6.nameList(), + Grantees: $6.roleSpecList(), WithGrantOption: $7.bool(), } } @@ -8289,20 +8297,20 @@ opt_with_grant_option: } abbreviated_revoke_stmt: - REVOKE privileges ON alter_default_privileges_target_object FROM name_list opt_drop_behavior + REVOKE privileges ON alter_default_privileges_target_object FROM role_spec_list opt_drop_behavior { $$.val = tree.AbbreviatedRevoke{ Privileges: $2.privilegeList(), Target: $4.alterDefaultPrivilegesTargetObject(), - Grantees: $6.nameList(), + Grantees: $6.roleSpecList(), } } -| REVOKE GRANT OPTION FOR privileges ON alter_default_privileges_target_object FROM name_list opt_drop_behavior +| REVOKE GRANT OPTION FOR privileges ON alter_default_privileges_target_object FROM role_spec_list opt_drop_behavior { $$.val = tree.AbbreviatedRevoke{ Privileges: $5.privilegeList(), Target: $7.alterDefaultPrivilegesTargetObject(), - Grantees: $9.nameList(), + Grantees: $9.roleSpecList(), GrantOptionFor: true, } } @@ -8334,12 +8342,12 @@ alter_default_privileges_target_object: } opt_for_roles: - FOR role_or_group_or_user name_list + FOR role_or_group_or_user role_spec_list { - $$.val = $3.nameList() + $$.val = $3.roleSpecList() } | /* EMPTY */ { - $$.val = tree.NameList(nil) + $$.val = tree.RoleSpecList(nil) } opt_in_schemas: @@ -9034,11 +9042,11 @@ multiple_set_clause: // TO { | CURRENT_USER | SESSION_USER} // %SeeAlso: DROP OWNED BY reassign_owned_by_stmt: - REASSIGN OWNED BY name_list TO role_spec + REASSIGN OWNED BY role_spec_list TO role_spec { $$.val = &tree.ReassignOwnedBy{ - OldRoles: $4.nameList(), - NewRole: $6.user(), + OldRoles: $4.roleSpecList(), + NewRole: $6.roleSpec(), } } | REASSIGN OWNED BY error // SHOW HELP: REASSIGN OWNED BY @@ -9049,10 +9057,10 @@ reassign_owned_by_stmt: // [RESTRICT | CASCADE] // %SeeAlso: REASSIGN OWNED BY drop_owned_by_stmt: - DROP OWNED BY name_list opt_drop_behavior + DROP OWNED BY role_spec_list opt_drop_behavior { $$.val = &tree.DropOwnedBy{ - Roles: $4.nameList(), + Roles: $4.roleSpecList(), DropBehavior: $5.dropBehavior(), } } diff --git a/pkg/sql/parser/testdata/alter_type b/pkg/sql/parser/testdata/alter_type index 09892b28aef1..2129206f55d9 100644 --- a/pkg/sql/parser/testdata/alter_type +++ b/pkg/sql/parser/testdata/alter_type @@ -73,15 +73,15 @@ ALTER TYPE _ OWNER TO _ -- identifiers removed parse ALTER TYPE t OWNER TO CURRENT_USER ---- -ALTER TYPE t OWNER TO "current_user" -- normalized! -ALTER TYPE t OWNER TO "current_user" -- fully parenthesized -ALTER TYPE t OWNER TO "current_user" -- literals removed +ALTER TYPE t OWNER TO CURRENT_USER +ALTER TYPE t OWNER TO CURRENT_USER -- fully parenthesized +ALTER TYPE t OWNER TO CURRENT_USER -- literals removed ALTER TYPE _ OWNER TO _ -- identifiers removed parse ALTER TYPE t OWNER TO SESSION_USER ---- -ALTER TYPE t OWNER TO "session_user" -- normalized! -ALTER TYPE t OWNER TO "session_user" -- fully parenthesized -ALTER TYPE t OWNER TO "session_user" -- literals removed +ALTER TYPE t OWNER TO SESSION_USER +ALTER TYPE t OWNER TO SESSION_USER -- fully parenthesized +ALTER TYPE t OWNER TO SESSION_USER -- literals removed ALTER TYPE _ OWNER TO _ -- identifiers removed diff --git a/pkg/sql/randgen/BUILD.bazel b/pkg/sql/randgen/BUILD.bazel index 9bcd958ac868..6e536f70b573 100644 --- a/pkg/sql/randgen/BUILD.bazel +++ b/pkg/sql/randgen/BUILD.bazel @@ -21,7 +21,6 @@ go_library( "//pkg/geo/geopb", "//pkg/keys", "//pkg/roachpb:with-mocks", - "//pkg/security", "//pkg/sql/catalog", "//pkg/sql/catalog/colinfo", "//pkg/sql/catalog/descpb", diff --git a/pkg/sql/randgen/schema.go b/pkg/sql/randgen/schema.go index 0eaefcbbac79..6db9ad36feb6 100644 --- a/pkg/sql/randgen/schema.go +++ b/pkg/sql/randgen/schema.go @@ -18,7 +18,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/roachpb" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/catalog" "github.com/cockroachdb/cockroach/pkg/sql/catalog/colinfo" "github.com/cockroachdb/cockroach/pkg/sql/rowenc" @@ -29,9 +28,7 @@ import ( ) // MakeSchemaName creates a CreateSchema definition. -func MakeSchemaName( - ifNotExists bool, schema string, authRole security.SQLUsername, -) *tree.CreateSchema { +func MakeSchemaName(ifNotExists bool, schema string, authRole tree.RoleSpec) *tree.CreateSchema { return &tree.CreateSchema{ IfNotExists: ifNotExists, Schema: tree.ObjectNamePrefix{ diff --git a/pkg/sql/reassign_owned_by.go b/pkg/sql/reassign_owned_by.go index 5a34e947fa9e..c946d87a0506 100644 --- a/pkg/sql/reassign_owned_by.go +++ b/pkg/sql/reassign_owned_by.go @@ -43,14 +43,14 @@ func (p *planner) ReassignOwnedBy(ctx context.Context, n *tree.ReassignOwnedBy) return nil, err } - normalizedOldRole, err := n.OldRoles.ToSQLUsernames() + normalizedOldRoles, err := n.OldRoles.ToSQLUsernames(p.SessionData()) if err != nil { return nil, err } // Check all roles in old roles exist. Checks in authorization.go will confirm that current user // is a member of old roles and new roles and has CREATE privilege. // Postgres first checks if the role exists before checking privileges. - for _, oldRole := range normalizedOldRole { + for _, oldRole := range normalizedOldRoles { roleExists, err := RoleExists(ctx, p.ExecCfg(), p.Txn(), oldRole) if err != nil { return nil, err @@ -59,9 +59,13 @@ func (p *planner) ReassignOwnedBy(ctx context.Context, n *tree.ReassignOwnedBy) return nil, pgerror.Newf(pgcode.UndefinedObject, "role/user %q does not exist", oldRole) } } - roleExists, err := RoleExists(ctx, p.ExecCfg(), p.Txn(), n.NewRole) + newRole, err := n.NewRole.ToSQLUsername(p.SessionData()) + if err != nil { + return nil, err + } + roleExists, err := RoleExists(ctx, p.ExecCfg(), p.Txn(), newRole) if !roleExists { - return nil, pgerror.Newf(pgcode.UndefinedObject, "role/user %q does not exist", n.NewRole) + return nil, pgerror.Newf(pgcode.UndefinedObject, "role/user %q does not exist", newRole) } if err != nil { return nil, err @@ -80,15 +84,15 @@ func (p *planner) ReassignOwnedBy(ctx context.Context, n *tree.ReassignOwnedBy) if err != nil { return nil, err } - if p.User() != n.NewRole { - if _, ok := memberOf[n.NewRole]; !ok { + if p.User() != newRole { + if _, ok := memberOf[newRole]; !ok { return nil, errors.WithHint( pgerror.Newf(pgcode.InsufficientPrivilege, "permission denied to reassign objects"), "user must be a member of the new role") } } - for _, oldRole := range normalizedOldRole { + for _, oldRole := range normalizedOldRoles { if p.User() != oldRole { if _, ok := memberOf[oldRole]; !ok { return nil, errors.WithHint( @@ -99,7 +103,7 @@ func (p *planner) ReassignOwnedBy(ctx context.Context, n *tree.ReassignOwnedBy) } } } - return &reassignOwnedByNode{n: n, normalizedOldRoles: normalizedOldRole}, nil + return &reassignOwnedByNode{n: n, normalizedOldRoles: normalizedOldRoles}, nil } func (n *reassignOwnedByNode) startExec(params runParams) error { @@ -163,7 +167,11 @@ func (n *reassignOwnedByNode) reassignDatabaseOwner( if err != nil { return err } - if err := params.p.setNewDatabaseOwner(params.ctx, mutableDbDesc, n.n.NewRole); err != nil { + owner, err := n.n.NewRole.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } + if err := params.p.setNewDatabaseOwner(params.ctx, mutableDbDesc, owner); err != nil { return err } if err := params.p.writeNonDropDatabaseChange( @@ -184,8 +192,12 @@ func (n *reassignOwnedByNode) reassignSchemaOwner( if err != nil { return err } + owner, err := n.n.NewRole.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } if err := params.p.setNewSchemaOwner( - params.ctx, dbDesc, mutableSchemaDesc.(*schemadesc.Mutable), n.n.NewRole); err != nil { + params.ctx, dbDesc, mutableSchemaDesc.(*schemadesc.Mutable), owner); err != nil { return err } if err := params.p.writeSchemaDescChange(params.ctx, @@ -211,8 +223,12 @@ func (n *reassignOwnedByNode) reassignTableOwner( return err } + owner, err := n.n.NewRole.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } if err := params.p.setNewTableOwner( - params.ctx, mutableTbDesc.(*tabledesc.Mutable), *tableName, n.n.NewRole); err != nil { + params.ctx, mutableTbDesc.(*tabledesc.Mutable), *tableName, owner); err != nil { return err } if err := params.p.writeSchemaChange( @@ -246,9 +262,13 @@ func (n *reassignOwnedByNode) reassignTypeOwner( return err } + owner, err := n.n.NewRole.ToSQLUsername(params.p.SessionData()) + if err != nil { + return err + } if err := params.p.setNewTypeOwner( params.ctx, mutableTypDesc.(*typedesc.Mutable), arrayDesc, *typeName, - *arrayTypeName, n.n.NewRole); err != nil { + *arrayTypeName, owner); err != nil { return err } if err := params.p.writeTypeSchemaChange( diff --git a/pkg/sql/revoke_role.go b/pkg/sql/revoke_role.go index a67f76299f0f..641177ff5c36 100644 --- a/pkg/sql/revoke_role.go +++ b/pkg/sql/revoke_role.go @@ -57,21 +57,13 @@ func (p *planner) RevokeRoleNode(ctx context.Context, n *tree.RevokeRole) (*Revo return nil, err } - inputRoles := make([]security.SQLUsername, len(n.Roles)) - inputMembers := make([]security.SQLUsername, len(n.Members)) - for i, role := range n.Roles { - normalizedRole, err := security.MakeSQLUsernameFromUserInput(string(role), security.UsernameValidation) - if err != nil { - return nil, err - } - inputRoles[i] = normalizedRole + inputRoles, err := n.Roles.ToSQLUsernames() + if err != nil { + return nil, err } - for i, member := range n.Members { - normalizedMember, err := security.MakeSQLUsernameFromUserInput(string(member), security.UsernameValidation) - if err != nil { - return nil, err - } - inputMembers[i] = normalizedMember + inputMembers, err := n.Members.ToSQLUsernames(p.SessionData()) + if err != nil { + return nil, err } for _, r := range inputRoles { diff --git a/pkg/sql/sem/tree/BUILD.bazel b/pkg/sql/sem/tree/BUILD.bazel index 3faa8953380d..056951f2c05f 100644 --- a/pkg/sql/sem/tree/BUILD.bazel +++ b/pkg/sql/sem/tree/BUILD.bazel @@ -79,6 +79,7 @@ go_library( "replication_stream.go", "returning.go", "revoke.go", + "role_spec.go", "run_control.go", "schedule.go", "scrub.go", diff --git a/pkg/sql/sem/tree/alter_database.go b/pkg/sql/sem/tree/alter_database.go index 3b3a7ee849ef..9fbf376145dc 100644 --- a/pkg/sql/sem/tree/alter_database.go +++ b/pkg/sql/sem/tree/alter_database.go @@ -10,14 +10,10 @@ package tree -import "github.com/cockroachdb/cockroach/pkg/security" - // AlterDatabaseOwner represents a ALTER DATABASE OWNER TO statement. type AlterDatabaseOwner struct { - Name Name - // TODO(solon): Adjust this, see - // https://github.com/cockroachdb/cockroach/issues/54696 - Owner security.SQLUsername + Name Name + Owner RoleSpec } // Format implements the NodeFormatter interface. @@ -25,7 +21,7 @@ func (node *AlterDatabaseOwner) Format(ctx *FmtCtx) { ctx.WriteString("ALTER DATABASE ") ctx.FormatNode(&node.Name) ctx.WriteString(" OWNER TO ") - ctx.FormatUsername(node.Owner) + ctx.FormatNode(&node.Owner) } // AlterDatabaseAddRegion represents a ALTER DATABASE ADD REGION statement. diff --git a/pkg/sql/sem/tree/alter_default_privileges.go b/pkg/sql/sem/tree/alter_default_privileges.go index a3d78d748b54..a87b04eb5d00 100644 --- a/pkg/sql/sem/tree/alter_default_privileges.go +++ b/pkg/sql/sem/tree/alter_default_privileges.go @@ -17,7 +17,7 @@ import ( // AlterDefaultPrivileges represents an ALTER DEFAULT PRIVILEGES statement. type AlterDefaultPrivileges struct { - Roles NameList + Roles RoleSpecList // True if `ALTER DEFAULT PRIVILEGES FOR ALL ROLES` is executed. ForAllRoles bool // If Schema is not specified, ALTER DEFAULT PRIVILEGES is being @@ -118,7 +118,7 @@ func (t AlterDefaultPrivilegesTargetObject) String() string { type AbbreviatedGrant struct { Privileges privilege.List Target AlterDefaultPrivilegesTargetObject - Grantees NameList + Grantees RoleSpecList WithGrantOption bool } @@ -149,7 +149,7 @@ func (n *AbbreviatedGrant) Format(ctx *FmtCtx) { type AbbreviatedRevoke struct { Privileges privilege.List Target AlterDefaultPrivilegesTargetObject - Grantees NameList + Grantees RoleSpecList GrantOptionFor bool } diff --git a/pkg/sql/sem/tree/alter_schema.go b/pkg/sql/sem/tree/alter_schema.go index dc9379d431d7..fc3982e8913d 100644 --- a/pkg/sql/sem/tree/alter_schema.go +++ b/pkg/sql/sem/tree/alter_schema.go @@ -10,8 +10,6 @@ package tree -import "github.com/cockroachdb/cockroach/pkg/security" - // AlterSchema represents an ALTER SCHEMA statement. type AlterSchema struct { Schema ObjectNamePrefix @@ -50,13 +48,11 @@ func (*AlterSchemaOwner) alterSchemaCmd() {} // AlterSchemaOwner represents an ALTER SCHEMA OWNER TO command. type AlterSchemaOwner struct { - // TODO(solon): Adjust this, see - // https://github.com/cockroachdb/cockroach/issues/54696 - Owner security.SQLUsername + Owner RoleSpec } // Format implements the NodeFormatter interface. func (node *AlterSchemaOwner) Format(ctx *FmtCtx) { ctx.WriteString(" OWNER TO ") - ctx.FormatUsername(node.Owner) + ctx.FormatNode(&node.Owner) } diff --git a/pkg/sql/sem/tree/alter_table.go b/pkg/sql/sem/tree/alter_table.go index 87ab2f2aaac1..34458cbc87a1 100644 --- a/pkg/sql/sem/tree/alter_table.go +++ b/pkg/sql/sem/tree/alter_table.go @@ -13,7 +13,6 @@ package tree import ( "strings" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/server/telemetry" "github.com/cockroachdb/cockroach/pkg/sql/lex" "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" @@ -670,10 +669,8 @@ func (node *AlterTableSetSchema) TelemetryCounter() telemetry.Counter { // AlterTableOwner represents an ALTER TABLE OWNER TO command. type AlterTableOwner struct { - Name *UnresolvedObjectName - // TODO(solon): Adjust this, see - // https://github.com/cockroachdb/cockroach/issues/54696 - Owner security.SQLUsername + Name *UnresolvedObjectName + Owner RoleSpec IfExists bool IsView bool IsMaterialized bool @@ -707,7 +704,7 @@ func (node *AlterTableOwner) Format(ctx *FmtCtx) { } ctx.FormatNode(node.Name) ctx.WriteString(" OWNER TO ") - ctx.FormatUsername(node.Owner) + ctx.FormatNode(&node.Owner) } // GetTableType returns a string representing the type of table the command diff --git a/pkg/sql/sem/tree/alter_type.go b/pkg/sql/sem/tree/alter_type.go index 5cf6cea3496a..23da3897a299 100644 --- a/pkg/sql/sem/tree/alter_type.go +++ b/pkg/sql/sem/tree/alter_type.go @@ -11,7 +11,6 @@ package tree import ( - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/server/telemetry" "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" ) @@ -157,15 +156,13 @@ func (node *AlterTypeSetSchema) TelemetryCounter() telemetry.Counter { // AlterTypeOwner represents an ALTER TYPE OWNER TO command. type AlterTypeOwner struct { - // TODO(solon): Adjust this, see - // https://github.com/cockroachdb/cockroach/issues/54696 - Owner security.SQLUsername + Owner RoleSpec } // Format implements the NodeFormatter interface. func (node *AlterTypeOwner) Format(ctx *FmtCtx) { ctx.WriteString(" OWNER TO ") - ctx.FormatUsername(node.Owner) + ctx.FormatNode(&node.Owner) } // TelemetryCounter implements the AlterTypeCmd interface. diff --git a/pkg/sql/sem/tree/create.go b/pkg/sql/sem/tree/create.go index c9fc6fc90339..f2b8d32a4a3d 100644 --- a/pkg/sql/sem/tree/create.go +++ b/pkg/sql/sem/tree/create.go @@ -24,7 +24,6 @@ import ( "strconv" "strings" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/server/telemetry" "github.com/cockroachdb/cockroach/pkg/sql/lexbase" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" @@ -1573,10 +1572,8 @@ func (node *CreateTable) HoistConstraints() { // CreateSchema represents a CREATE SCHEMA statement. type CreateSchema struct { IfNotExists bool - // TODO(solon): Adjust this, see - // https://github.com/cockroachdb/cockroach/issues/54696 - AuthRole security.SQLUsername - Schema ObjectNamePrefix + AuthRole RoleSpec + Schema ObjectNamePrefix } // Format implements the NodeFormatter interface. @@ -1594,7 +1591,7 @@ func (node *CreateSchema) Format(ctx *FmtCtx) { if !node.AuthRole.Undefined() { ctx.WriteString(" AUTHORIZATION ") - ctx.FormatUsername(node.AuthRole) + ctx.FormatNode(&node.AuthRole) } } diff --git a/pkg/sql/sem/tree/drop_owned_by.go b/pkg/sql/sem/tree/drop_owned_by.go index 4fdc379918d2..4b83bf930ac4 100644 --- a/pkg/sql/sem/tree/drop_owned_by.go +++ b/pkg/sql/sem/tree/drop_owned_by.go @@ -12,7 +12,7 @@ package tree // DropOwnedBy represents a DROP OWNED BY command. type DropOwnedBy struct { - Roles NameList + Roles RoleSpecList DropBehavior DropBehavior } @@ -25,7 +25,7 @@ func (node *DropOwnedBy) Format(ctx *FmtCtx) { if i > 0 { ctx.WriteString(", ") } - ctx.FormatUsernameN(node.Roles[i]) + node.Roles[i].Format(ctx) } if node.DropBehavior != DropDefault { ctx.WriteString(" ") diff --git a/pkg/sql/sem/tree/format.go b/pkg/sql/sem/tree/format.go index fe48a96ceb1b..8f85392e0120 100644 --- a/pkg/sql/sem/tree/format.go +++ b/pkg/sql/sem/tree/format.go @@ -15,7 +15,6 @@ import ( "fmt" "sync" - "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/lexbase" "github.com/cockroachdb/cockroach/pkg/sql/sessiondatapb" "github.com/cockroachdb/cockroach/pkg/sql/types" @@ -380,16 +379,6 @@ func (ctx *FmtCtx) FormatNameP(s *string) { ctx.FormatNode((*Name)(s)) } -// FormatUsername formats a username safely. -func (ctx *FmtCtx) FormatUsername(s security.SQLUsername) { - ctx.FormatName(s.Normalized()) -} - -//FormatUsernameN formats a username that is type Name -func (ctx *FmtCtx) FormatUsernameN(s Name) { - ctx.FormatName(s.Normalize()) -} - // FormatNode recurses into a node for pretty-printing. // Flag-driven special cases can hook into this. func (ctx *FmtCtx) FormatNode(n NodeFormatter) { diff --git a/pkg/sql/sem/tree/grant.go b/pkg/sql/sem/tree/grant.go index d4549ab36bd5..88ef29dc4367 100644 --- a/pkg/sql/sem/tree/grant.go +++ b/pkg/sql/sem/tree/grant.go @@ -30,7 +30,7 @@ import ( type Grant struct { Privileges privilege.List Targets TargetList - Grantees NameList + Grantees RoleSpecList } // TargetList represents a list of targets. @@ -48,7 +48,7 @@ type TargetList struct { // in the AST. Therefore they do not participate in pretty-printing, // etc. ForRoles bool - Roles NameList + Roles RoleSpecList } // Format implements the NodeFormatter interface. @@ -91,7 +91,7 @@ func (node *Grant) Format(ctx *FmtCtx) { // GrantRole represents a GRANT statement. type GrantRole struct { Roles NameList - Members NameList + Members RoleSpecList AdminOption bool } diff --git a/pkg/sql/sem/tree/reassign_owned_by.go b/pkg/sql/sem/tree/reassign_owned_by.go index 39225ce2d42e..c2903d3b7089 100644 --- a/pkg/sql/sem/tree/reassign_owned_by.go +++ b/pkg/sql/sem/tree/reassign_owned_by.go @@ -10,12 +10,10 @@ package tree -import "github.com/cockroachdb/cockroach/pkg/security" - // ReassignOwnedBy represents a REASSIGN OWNED BY TO statement. type ReassignOwnedBy struct { - OldRoles NameList - NewRole security.SQLUsername + OldRoles RoleSpecList + NewRole RoleSpec } var _ Statement = &ReassignOwnedBy{} @@ -27,8 +25,8 @@ func (node *ReassignOwnedBy) Format(ctx *FmtCtx) { if i > 0 { ctx.WriteString(", ") } - ctx.FormatUsernameN(node.OldRoles[i]) + node.OldRoles[i].Format(ctx) } ctx.WriteString(" TO ") - ctx.FormatUsername(node.NewRole) + ctx.FormatNode(&node.NewRole) } diff --git a/pkg/sql/sem/tree/revoke.go b/pkg/sql/sem/tree/revoke.go index 813661ac5df9..bac0a86dd1c5 100644 --- a/pkg/sql/sem/tree/revoke.go +++ b/pkg/sql/sem/tree/revoke.go @@ -26,7 +26,7 @@ import "github.com/cockroachdb/cockroach/pkg/sql/privilege" type Revoke struct { Privileges privilege.List Targets TargetList - Grantees NameList + Grantees RoleSpecList } // Format implements the NodeFormatter interface. @@ -45,7 +45,7 @@ func (node *Revoke) Format(ctx *FmtCtx) { // RevokeRole represents a REVOKE statement. type RevokeRole struct { Roles NameList - Members NameList + Members RoleSpecList AdminOption bool } diff --git a/pkg/sql/sem/tree/role_spec.go b/pkg/sql/sem/tree/role_spec.go new file mode 100644 index 000000000000..b2d4946c2993 --- /dev/null +++ b/pkg/sql/sem/tree/role_spec.go @@ -0,0 +1,106 @@ +// Copyright 2021 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package tree + +import ( + "github.com/cockroachdb/cockroach/pkg/security" + "github.com/cockroachdb/cockroach/pkg/sql/lexbase" + "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" +) + +// RoleSpecType represents whether the RoleSpec is represented by +// string name or if the spec is CURRENT_USER or SESSION_USER. +type RoleSpecType int + +const ( + // RoleName represents if a RoleSpec is defined using an IDENT or + // unreserved_keyword in the grammar. + RoleName RoleSpecType = iota + // CurrentUser represents if a RoleSpec is defined using CURRENT_USER. + CurrentUser + // SessionUser represents if a RoleSpec is defined using SESSION_USER. + SessionUser +) + +// RoleSpecList is a list of RoleSpec. +type RoleSpecList []RoleSpec + +// RoleSpec represents a role. +// Name should only be populated if RoleSpecType is RoleName. +type RoleSpec struct { + RoleSpecType RoleSpecType + Name string +} + +// MakeRoleSpecWithRoleName creates a RoleSpec using a RoleName. +func MakeRoleSpecWithRoleName(name string) RoleSpec { + return RoleSpec{RoleSpecType: RoleName, Name: name} +} + +// ToSQLUsername converts a RoleSpec to a security.SQLUsername. +func (r RoleSpec) ToSQLUsername( + sessionData *sessiondata.SessionData, +) (security.SQLUsername, error) { + if r.RoleSpecType == CurrentUser { + return sessionData.User(), nil + } else if r.RoleSpecType == SessionUser { + return sessionData.SessionUser(), nil + } + return security.MakeSQLUsernameFromUserInput(r.Name, security.UsernameValidation) +} + +// ToSQLUsernames converts a RoleSpecList to a slice of security.SQLUsername. +func (l RoleSpecList) ToSQLUsernames( + sessionData *sessiondata.SessionData, +) ([]security.SQLUsername, error) { + targetRoles := make([]security.SQLUsername, len(l)) + for i, role := range l { + user, err := role.ToSQLUsername(sessionData) + if err != nil { + return nil, err + } + targetRoles[i] = user + } + return targetRoles, nil +} + +// Undefined returns if RoleSpec is undefined. +func (r RoleSpec) Undefined() bool { + return r.RoleSpecType == RoleName && len(r.Name) == 0 +} + +// Format implements the NodeFormatter interface. +func (r *RoleSpec) Format(ctx *FmtCtx) { + f := ctx.flags + if f.HasFlags(FmtAnonymize) && !isArityIndicatorString(r.Name) { + ctx.WriteByte('_') + } else { + switch r.RoleSpecType { + case RoleName: + lexbase.EncodeRestrictedSQLIdent(&ctx.Buffer, r.Name, f.EncodeFlags()) + return + case CurrentUser: + ctx.WriteString("CURRENT_USER") + case SessionUser: + ctx.WriteString("SESSION_USER") + } + } +} + +// Format implements the NodeFormatter interface. +func (l *RoleSpecList) Format(ctx *FmtCtx) { + for i := range *l { + if i > 0 { + ctx.WriteString(", ") + } + ctx.FormatNode(&(*l)[i]) + } +} diff --git a/pkg/sql/sem/tree/show.go b/pkg/sql/sem/tree/show.go index 2294d1eacd0d..0e7f5cbbac84 100644 --- a/pkg/sql/sem/tree/show.go +++ b/pkg/sql/sem/tree/show.go @@ -460,7 +460,7 @@ func (node *ShowConstraints) Format(ctx *FmtCtx) { // TargetList is defined in grant.go. type ShowGrants struct { Targets *TargetList - Grantees NameList + Grantees RoleSpecList } // Format implements the NodeFormatter interface. @@ -478,8 +478,8 @@ func (node *ShowGrants) Format(ctx *FmtCtx) { // ShowRoleGrants represents a SHOW GRANTS ON ROLE statement. type ShowRoleGrants struct { - Roles NameList - Grantees NameList + Roles RoleSpecList + Grantees RoleSpecList } // Format implements the NodeFormatter interface. @@ -855,7 +855,7 @@ func (n *ShowSchedules) Format(ctx *FmtCtx) { // ShowDefaultPrivileges represents a SHOW DEFAULT PRIVILEGES statement. type ShowDefaultPrivileges struct { - Roles NameList + Roles RoleSpecList ForAllRoles bool } diff --git a/pkg/workload/schemachange/operation_generator.go b/pkg/workload/schemachange/operation_generator.go index 60a6968c8b7c..09d0d473ef59 100644 --- a/pkg/workload/schemachange/operation_generator.go +++ b/pkg/workload/schemachange/operation_generator.go @@ -2809,7 +2809,7 @@ func (og *operationGenerator) createSchema(ctx context.Context, tx pgx.Tx) (stri } // TODO(jayshrivastava): Support authorization - stmt := randgen.MakeSchemaName(ifNotExists, schemaName, security.RootUserName()) + stmt := randgen.MakeSchemaName(ifNotExists, schemaName, tree.MakeRoleSpecWithRoleName(security.RootUserName().Normalized())) return tree.Serialize(stmt), nil }