@@ -12,6 +12,7 @@ import (
12
12
13
13
"github.com/cockroachdb/cockroach/pkg/security/username"
14
14
"github.com/cockroachdb/cockroach/pkg/settings"
15
+ "github.com/cockroachdb/cockroach/pkg/sql/catalog"
15
16
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
16
17
"github.com/cockroachdb/cockroach/pkg/sql/decodeusername"
17
18
"github.com/cockroachdb/cockroach/pkg/sql/paramparse"
@@ -288,8 +289,23 @@ func (*alterRoleNode) Values() tree.Datums { return tree.Datums{} }
288
289
func (* alterRoleNode ) Close (context.Context ) {}
289
290
290
291
// AlterRoleSet represents a `ALTER ROLE ... SET` statement.
291
- // Privileges: CREATEROLE, MODIFYCLUSTERSETTING, MODIFYSQLCLUSTERSETTING privilege; or admin-only if `ALTER ROLE ALL`.
292
+ //
293
+ // Privileges:
294
+ //
295
+ // - CREATEROLE, MODIFYCLUSTERSETTING, MODIFYSQLCLUSTERSETTING privilege;
296
+ // - admin-only if `ALTER ROLE ALL`;
297
+ // - database owner or admin if `ALTER ROLE ALL IN DATABASE SET ...`
292
298
func (p * planner ) AlterRoleSet (ctx context.Context , n * tree.AlterRoleSet ) (planNode , error ) {
299
+ dbDescID := descpb .ID (0 )
300
+ var dbDesc catalog.DatabaseDescriptor
301
+ if n .DatabaseName != "" {
302
+ var err error
303
+ dbDesc , err = p .Descriptors ().ByNameWithLeased (p .txn ).Get ().Database (ctx , string (n .DatabaseName ))
304
+ if err != nil {
305
+ return nil , err
306
+ }
307
+ dbDescID = dbDesc .GetID ()
308
+ }
293
309
// Note that for Postgres, only superuser can ALTER another superuser.
294
310
// CockroachDB does not support the superuser role option right now.
295
311
// However we make it so members of the ADMIN role can only be edited
@@ -298,11 +314,25 @@ func (p *planner) AlterRoleSet(ctx context.Context, n *tree.AlterRoleSet) (planN
298
314
// modifying their own defaults unless they have CREATEROLE. This is analogous
299
315
// to our restriction that prevents a user from modifying their own password.
300
316
if n .AllRoles {
301
- if hasAdmin , err := p .HasAdminRole (ctx ); err != nil {
317
+ hasAdmin , err := p .HasAdminRole (ctx )
318
+ if err != nil {
302
319
return nil , err
303
- } else if ! hasAdmin {
304
- return nil , pgerror .Newf (pgcode .InsufficientPrivilege ,
305
- "only users with the admin role are allowed to ALTER ROLE ALL ... SET" )
320
+ }
321
+ if ! hasAdmin {
322
+ if dbDesc == nil {
323
+ return nil , pgerror .Newf (pgcode .InsufficientPrivilege ,
324
+ "only users with the admin role are allowed to ALTER ROLE ALL ... SET" )
325
+ }
326
+ // If the user is not an admin, they must be the owner of the database if
327
+ // ALL IN DATABASE ... is used
328
+ isDBOwner , err := p .HasOwnership (ctx , dbDesc )
329
+ if err != nil {
330
+ return nil , err
331
+ }
332
+ if ! isDBOwner {
333
+ return nil , pgerror .Newf (pgcode .InsufficientPrivilege ,
334
+ "only users with the admin role or the owner of the database is allowed to ALTER ROLE ALL IN DATABASE SET ..." )
335
+ }
306
336
}
307
337
} else {
308
338
canAlterRoleSet , err := p .HasGlobalPrivilegeOrRoleOption (ctx , privilege .CREATEROLE )
@@ -337,15 +367,6 @@ func (p *planner) AlterRoleSet(ctx context.Context, n *tree.AlterRoleSet) (planN
337
367
}
338
368
}
339
369
340
- dbDescID := descpb .ID (0 )
341
- if n .DatabaseName != "" {
342
- dbDesc , err := p .Descriptors ().ByNameWithLeased (p .txn ).Get ().Database (ctx , string (n .DatabaseName ))
343
- if err != nil {
344
- return nil , err
345
- }
346
- dbDescID = dbDesc .GetID ()
347
- }
348
-
349
370
setVarKind , varName , sVar , typedValues , err := p .processSetOrResetClause (ctx , n .SetOrReset )
350
371
if err != nil {
351
372
return nil , err
0 commit comments