|
34 | 34 | #include "commands/resgroupcmds.h" |
35 | 35 | #include "miscadmin.h" |
36 | 36 | #include "nodes/pg_list.h" |
| 37 | +#include "utils/acl.h" |
37 | 38 | #include "utils/builtins.h" |
38 | 39 | #include "utils/datetime.h" |
39 | 40 | #include "utils/fmgroids.h" |
@@ -103,11 +104,15 @@ CreateResourceGroup(CreateResourceGroupStmt *stmt) |
103 | 104 | int nResGroups; |
104 | 105 | MemoryContext oldContext; |
105 | 106 |
|
106 | | - /* Permission check - only superuser can create groups. */ |
107 | | - if (!superuser()) |
| 107 | + /* |
| 108 | + * Permission check - superusers and members of the predefined role |
| 109 | + * pg_manage_resource_groups can create resource groups. |
| 110 | + */ |
| 111 | + if (!has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_RESOURCE_GROUPS)) |
108 | 112 | ereport(ERROR, |
109 | 113 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
110 | | - errmsg("must be superuser to create resource groups"))); |
| 114 | + errmsg("permission denied to create resource group"), |
| 115 | + errhint("Must be superuser or have privileges of the pg_manage_resource_groups role."))); |
111 | 116 |
|
112 | 117 | /* |
113 | 118 | * Check for an illegal name ('none' is used to signify no group in ALTER ROLE). |
@@ -269,11 +274,15 @@ DropResourceGroup(DropResourceGroupStmt *stmt) |
269 | 274 | Oid groupid; |
270 | 275 | ResourceGroupCallbackContext *callbackCtx; |
271 | 276 |
|
272 | | - /* Permission check - only superuser can drop resource groups. */ |
273 | | - if (!superuser()) |
| 277 | + /* |
| 278 | + * Permission check - superusers and members of the predefined role |
| 279 | + * pg_manage_resource_groups can drop resource groups. |
| 280 | + */ |
| 281 | + if (!has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_RESOURCE_GROUPS)) |
274 | 282 | ereport(ERROR, |
275 | 283 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
276 | | - errmsg("must be superuser to drop resource groups"))); |
| 284 | + errmsg("permission denied to drop resource group \"%s\"", stmt->name), |
| 285 | + errhint("Must be superuser or have privileges of the pg_manage_resource_groups role."))); |
277 | 286 |
|
278 | 287 | /* |
279 | 288 | * Check the pg_resgroup relation to be certain the resource group already |
@@ -375,11 +384,15 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) |
375 | 384 | ResourceGroupCallbackContext *callbackCtx; |
376 | 385 | MemoryContext oldContext; |
377 | 386 |
|
378 | | - /* Permission check - only superuser can alter resource groups. */ |
379 | | - if (!superuser()) |
| 387 | + /* |
| 388 | + * Permission check - superusers and members of the predefined role |
| 389 | + * pg_manage_resource_groups can alter resource groups. |
| 390 | + */ |
| 391 | + if (!has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_RESOURCE_GROUPS)) |
380 | 392 | ereport(ERROR, |
381 | 393 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
382 | | - errmsg("must be superuser to alter resource groups"))); |
| 394 | + errmsg("permission denied to alter resource group \"%s\"", stmt->name), |
| 395 | + errhint("Must be superuser or have privileges of the pg_manage_resource_groups role."))); |
383 | 396 |
|
384 | 397 | /* Currently we only support to ALTER one limit at one time */ |
385 | 398 | Assert(list_length(stmt->options) == 1); |
@@ -412,6 +425,18 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) |
412 | 425 | */ |
413 | 426 | groupid = get_resgroup_oid(stmt->name, false); |
414 | 427 |
|
| 428 | + /* |
| 429 | + * The built-in system resource groups may only be altered by a real |
| 430 | + * superuser, never by a member of pg_manage_resource_groups |
| 431 | + */ |
| 432 | + if (!superuser() && |
| 433 | + (groupid == ADMINRESGROUP_OID || |
| 434 | + groupid == SYSTEMRESGROUP_OID)) |
| 435 | + ereport(ERROR, |
| 436 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 437 | + errmsg("permission denied to alter resource group \"%s\"", stmt->name), |
| 438 | + errhint("Must be superuser to alter a system resource group."))); |
| 439 | + |
415 | 440 | if (limitType == RESGROUP_LIMIT_TYPE_CONCURRENCY && |
416 | 441 | value == 0 && |
417 | 442 | groupid == ADMINRESGROUP_OID) |
@@ -500,7 +525,7 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) |
500 | 525 | RESGROUP_DEFAULT_CPU_WEIGHT, ""); |
501 | 526 |
|
502 | 527 | updateResgroupCapabilityEntry(pg_resgroupcapability_rel, |
503 | | - groupid, RESGROUP_LIMIT_TYPE_CPUSET, |
| 528 | + groupid, RESGROUP_LIMIT_TYPE_CPUSET, |
504 | 529 | 0, caps.cpuset); |
505 | 530 | } |
506 | 531 | else if (limitType == RESGROUP_LIMIT_TYPE_CPU) |
@@ -1007,7 +1032,7 @@ parseStmtOptions(CreateResourceGroupStmt *stmt, ResGroupCaps *caps) |
1007 | 1032 | else |
1008 | 1033 | mask |= 1 << type; |
1009 | 1034 |
|
1010 | | - if (type == RESGROUP_LIMIT_TYPE_CPUSET) |
| 1035 | + if (type == RESGROUP_LIMIT_TYPE_CPUSET) |
1011 | 1036 | { |
1012 | 1037 | const char *cpuset = defGetString(defel); |
1013 | 1038 | strlcpy(caps->cpuset, cpuset, sizeof(caps->cpuset)); |
@@ -1611,7 +1636,7 @@ checkCpuSetByRole(const char *cpuset) |
1611 | 1636 | * ex: |
1612 | 1637 | * cpuset = "1;4" |
1613 | 1638 | * then we should assign '1' to corrdinator and '4' to segment |
1614 | | - * |
| 1639 | + * |
1615 | 1640 | * cpuset = "1" |
1616 | 1641 | * assign '1' to both coordinator and segment |
1617 | 1642 | */ |
|
0 commit comments