github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/docs/RFCS/20171220_sql_role_based_access_control.md (about) 1 - Feature Name: SQL Role-based access control 2 - Status: in-progress 3 - Start Date: 2017-11-18 4 - Authors: Marc Berhault 5 - RFC PR: [#20149](https://github.com/cockroachdb/cockroach/pull/20149) 6 - Cockroach Issue: [#20371](https://github.com/cockroachdb/cockroach/issues/20371) 7 8 Table of Contents 9 ================= 10 11 * [Summary](#summary) 12 * [Motivation](#motivation) 13 * [Related resources](#related-resources) 14 * [Out of scope](#out-of-scope) 15 * [Guide-level explanation](#guide-level-explanation) 16 * [Terminology](#terminology) 17 * [User-level explanation](#user-level-explanation) 18 * [Role basics](#role-basics) 19 * [Creating a role](#creating-a-role) 20 * [Granting and revoking privileges for a role](#granting-and-revoking-privileges-for-a-role) 21 * [Manipulating role membership](#manipulating-role-membership) 22 * [Dropping a role](#dropping-a-role) 23 * [Listing roles](#listing-roles) 24 * [Listing role memberships](#listing-role-memberships) 25 * [Administrators](#administrators) 26 * [Non-enterprise users](#non-enterprise-users) 27 * [Contributor impact](#contributor-impact) 28 * [Reference-level explanation](#reference-level-explanation) 29 * [Detailed design](#detailed-design) 30 * [Roles system table](#roles-system-table) 31 * [New SQL statements](#new-sql-statements) 32 * [Modifying role memberships](#modifying-role-memberships) 33 * [Expanding role memberships](#expanding-role-memberships) 34 * [Checking permissions](#checking-permissions) 35 * [Admin role](#admin-role) 36 * [Migrations and backwards compatibility](#migrations-and-backwards-compatibility) 37 * [Non-enterprise functionality](#non-enterprise-functionality) 38 * [Virtual tables](#virtual-tables) 39 * [Drawbacks](#drawbacks) 40 * [Use of leases to signal role changes](#use-of-leases-to-signal-role-changes) 41 * [Code location](#code-location) 42 * [Rationale and Alternatives](#rationale-and-alternatives) 43 * [Internal representation of memberships](#internal-representation-of-memberships) 44 * [Future improvements](#future-improvements) 45 46 # Summary 47 48 Role-based access control is an enterprise feature. 49 50 We propose the addition of SQL roles to facilitate user management. 51 52 A role can be seen as a group containing any number of "entities" as members. An entity can be a user or 53 another role. 54 55 Roles can have privileges on SQL objects. Any member of the role (directly a member, 56 or indirectly by being a member-of-a-member) inherits all privileges of the role. 57 58 A new `admin` role will replace the current `root` user, with `root` being a member of `admin`. 59 Non-enterprise users will not be able to manipulate roles (create/delete/change membership), but 60 will retain all roles created using an enterprise license. 61 62 This will be implemented through the addition of a new `role_members` system table containing role-role and 63 user-role relationships. Role memberships are synchronized through descriptor versions, a new versions indicating 64 that a node should refresh role information. 65 66 # Motivation 67 68 Roles simplify the task of user management on a large database. 69 70 By granting database/table privileges to a role, users of a team can be more 71 easily added to the system and granted all necessary privileges by simply adding them as members 72 of the corresponding roles. The alternative would be granting privileges for all necessary objects, 73 making it likely to forget some. 74 75 Managing privileges on a given object becomes easier: by changing the privileges granted to the role, 76 all members of the role are updated implicitly. 77 78 # Related resources 79 80 We follow the postgresql use of roles: 81 * [PostgreSQL user management](https://www.postgresql.org/docs/current/static/user-manag.html) 82 * [PostgreSQL CREATE ROLE](https://www.postgresql.org/docs/10/static/sql-createrole.html) 83 * [PostgreSQL DROP ROLE](https://www.postgresql.org/docs/10/static/sql-droprole.html) 84 * [PostgreSQL GRANT on ROLES](https://www.postgresql.org/docs/current/static/sql-grant.html#SQL-GRANT-DESCRIPTION-ROLES) 85 * [PostgreSQL REVOKE](https://www.postgresql.org/docs/current/static/sql-revoke.html) 86 87 # Out of scope 88 89 The following are not in scope but should not be hindered by implementation of this RFC: 90 * role attributes (see [PostgreSQL CREATE ROLE](https://www.postgresql.org/docs/10/static/sql-createrole.html) for full list) 91 * `ALTER` command (modify role attributes, rename role) 92 * role auditing 93 * multiple "admin" (or superuser) roles 94 * admin UI manipulation of roles 95 * new privileges (eg: admin UI related) 96 97 See [Future improvements](#future-improvements) for discussion of some of these. 98 99 # Guide-level explanation 100 101 ## Terminology 102 103 Some terminology used in this RFC: 104 * **role**: the focus point of this RFC. Please re-read the [summary](#summary) 105 * **role admin**: a member of the role allowed to change role membership 106 * **admin**: the special role allowed superuser operations, always exists 107 * **root**: the special user existing by default as a member of the `admin` role 108 * **inherit**: the behavior that grants a role's privileges to its members 109 * **`A ∈ B`**: user or role `A` is a member of role `B` 110 * **direct member**: A is a direct member of B if `A ∈ B` 111 * **indirect member**: A is an indirect member of B if `A ∈ C ... ∈ B` where `...` is an arbitrary number of memberships 112 113 ## User-level explanation 114 115 ### Role basics 116 117 A role can be thought of as a group with any number of members belonging to the group. 118 Roles have privileges on objects in the same way that users do. All members of the role 119 inherit the privileges held by the role. This is done recursively. 120 121 For example: 122 * role `employees` has `ALL` privileges on table `mydb.employee_data` 123 * user `marc` is a member of `employees` (also written: `marc ∈ employees`) 124 * without any extra privileges, `marc` can now perform any operations on table `mydb.employee_data` 125 126 Roles and users follow a small set of rules: 127 * roles cannot login (they do not have a password and cannot use certs) 128 * roles and users use the same namespace (ie: if a user `marc` exists, we cannot create a role `marc`) 129 * users and roles can be members of roles 130 * membership loops are not allowed (direct: `A ∈ B ∈ A` or indirect: `A ∈ B ∈ C ... ∈ A`) 131 * all privileges of a role are inherited by all its members 132 * privileges on a table/database can be assigned to roles and users 133 * only the admin role can create/drop roles 134 * role admins (members with the `ADMIN OPTION`) can modify role memberships 135 * a role cannot be dropped if it still has privileges 136 * there is no limit (minimum or maximum) to the number of members of a role (except for the `admin` role) 137 138 ### Creating a role 139 140 Cockroach administrators can create a new role called `myrole` using: 141 ``` 142 CREATE ROLE myrole 143 ``` 144 145 This fails if `myrole` exists either as a role or a user. 146 147 ### Granting and revoking privileges for a role 148 149 Granting privileges to a role is the same a granting privileges to a user. This syntax has not changed. 150 151 For example, granting `SELECT` privileges to the role `myrole` on a table consists of: 152 ``` 153 GRANT SELECT ON TABLE mydb.mytable TO myrole 154 ``` 155 156 Revoking privileges is also the same as before: 157 ``` 158 REVOKE SELECT ON TABLE mydb.mytable FROM myrole 159 ``` 160 161 ### Manipulating role membership 162 163 Modification of role membership requires one of the following: 164 * cockroach administrator (`admin` role) 165 * role admin (added to the role using `WITH ADMIN OPTION`) 166 167 A user `marc` can be added to the role `myrole` without role admin permissions using: 168 ``` 169 GRANT myrole TO marc 170 ``` 171 172 `marc` is now a "regular" member of the role, inheriting all role privileges. However, `marc` 173 is not allowed to modify role membership. 174 175 To allow a user to modify role membership, we can use `WITH ADMIN OPTION`: 176 ``` 177 GRANT myrole TO marc WITH ADMIN OPTION 178 ``` 179 180 `marc` is now a member of the role **and** is allowed to modify role membership. 181 182 ### Dropping a role 183 184 Cockroach administrators can delete a role called `myrole` using: 185 ``` 186 DROP ROLE myrole 187 ``` 188 189 This fails if `myrole` does not exist. We can instead use: 190 ``` 191 DROP ROLE IF EXISTS myrole 192 ``` 193 194 Dropping a role will fail if it still has direct privileges on database objects (privileges through membership 195 in other roles does not trigger an error). 196 197 Any role relationships involving this role will be removed automatically. 198 199 This applies to dropping users as well: dropping user `A` when `A ∈ myrole` will automatically remove 200 the membership. 201 202 ### Listing roles 203 204 We can get a simple list of all roles in the cluster by running: 205 ``` 206 SHOW ROLES 207 208 +--------------+ 209 | Role | 210 +--------------+ 211 | admin | 212 | myrole | 213 | myotherrole | 214 +--------------+ 215 ``` 216 217 ### Listing role memberships 218 219 A list of members can be found using: 220 ``` 221 SHOW GRANTS ON ROLE myrole 222 223 +--------+----------- +-------+ 224 | Role | User/Role | Admin | 225 +--------+------------+-------+ 226 | myrole | marc | YES | 227 | myrole | other | NO | 228 +--------+------------+-------+ 229 ``` 230 231 We will also allow the following variants: 232 * lookup all role memberships: `SHOW GRANTS ON ROLE` 233 * show all memberships for a user: `SHOW GRANTS ON ROLE FOR marc` 234 * show all members of a role: `SHOW GRANTS ON ROLE myrole` 235 * show user membership in a role: `SHOW GRANTS ON ROLE myrole FOR marc` 236 237 ### Administrators 238 239 Before this RFC, there is a single administrative user in a cockroach cluster: the user `root`. 240 241 We propose to add a default role: `admin` with a single user: `root`. 242 `root` will have admin privileges on the `admin` role, allowing addition/removal of other users. 243 244 The `admin` role cannot be deleted, and cannot be empty. The special `root` user cannot be dropped or removed 245 from the `admin` role. 246 247 All operations that previously checked for the `root` user will now check for membership in the `admin` role. 248 249 Clusters created before the existence of roles will have a new `admin` role created automatically and privileges 250 for it added where `root` currently has privileges. `root` will keep its individual privileges to allow downgrades 251 to older versions. 252 253 ### Non-enterprise users 254 255 Manipulation of roles is an enterprise feature. 256 257 Without a valid enterprise license, the following are **not** allowed: 258 * creating a role (`CREATE ROLE ...`) 259 * dropping a role (`DROP ROLE ...`) 260 * adding a member of a role (`GRANT myrole TO ...`) 261 * removing a member from a role (`REVOKE myrole TO ...`) 262 263 The following will function without an enterprise license: 264 * listing roles 265 * listing role memberships 266 * granting privileges to a role 267 * revoking privileges from a role 268 269 This restriction leaves non-enterprise users with a fully-functioning product but without the 270 ease of management provided by roles. 271 272 ## Contributor impact 273 274 Any modifications to the SQL code must keep in mind: 275 * privileges can be applied to roles and users 276 * roles and users share the same namespace 277 278 # Reference-level explanation 279 280 A number of concepts are detailed in the [Guide-level explanation](#guide-level-explanation) and not 281 repeated in this section. 282 283 ## Detailed design 284 285 ### Roles system table 286 287 We propose the modification of the users table to store roles, and the addition of a new table to store 288 role memberships. 289 290 #### Users table 291 292 Since roles and users share the same namespace, it is simplest to alter the `system.users` table to 293 include roles. 294 295 The schema for the users table becomes: 296 ``` 297 CREATE TABLE system.users ( 298 username STRING PRIMARY KEY, 299 "hashedPassword" BYTES, 300 isRole BOOL, 301 (INDEX isRole) 302 );` 303 ``` 304 305 Depending on the complexity of migration, we may be able to rename the `username` field and even the table 306 to `rolename` and `system.roles` to reflect the fact that users are really just roles. 307 308 `isRole` denotes whether the corresponding name is a user or a role. Roles cannot log in or have passwords. 309 310 #### Role members table 311 312 The `role_members` stores the list of all role memberships. This only stores direct relationships: 313 314 ``` 315 CREATE TABLE system.role_members ( 316 role STRING, 317 member STRING, 318 isAdmin BOOL, 319 PRIMARY KEY (role, member), 320 INDEX (member) 321 ); 322 ``` 323 324 For alternate representations [Internal representation of memberships](#internal-representation-of-memberships). 325 326 ### New SQL statements 327 328 We propose some new and some modified SQL statements, all mimicking the corresponding statements 329 in PostgreSQL (see [Related resources](#related-resources)). 330 331 The new statements all operate on the `system.users` and `system.role_members` tables. 332 333 #### CREATE ROLE 334 335 ``` 336 CREATE ROLE [ IF NOT EXISTS ] rolename 337 ``` 338 339 * **Behavior**: creates a new role named `rolename`. Fails if a role or user by that name exists. 340 * **Permissions**: caller must be an administrator. 341 * **Enterprise requirement**: valid license required. 342 343 #### DROP ROLE 344 345 ``` 346 DROP ROLE [ IF EXISTS ] rolename 347 ``` 348 349 * **Behavior**: drops the role named `rolename`. Fails if it does not exist, unless `IF EXISTS` is specified. 350 * **Permissions**: caller must be an administrator. 351 * **Enterprise requirement**: valid license required. 352 353 #### Grant/revoke privileges to/from a role 354 355 The `GRANT` and `REVOKE` statements used to grant privileges to a user will accept a role. No syntax 356 changes are necessary. 357 358 An enterprise license is not required. 359 360 #### GRANT role 361 362 ``` 363 GRANT rolename TO name [ WITH ADMIN OPTION ] 364 ``` 365 366 * **Behavior**: adds `name` as a member of `rolename`. Member is a role admin if `WITH ADMIN OPTION` is specified. 367 - Fails if either `rolename` or `name` does not exist, or if this creates a membership loop. 368 - Existing memberships can have their `WITH ADMIN` option enabled, but never disabled. 369 - The `ADMIN OPTION` is inherited. eg: if `A ∈ B ∈ C` and `B` has `ADMIN OPTION` on `C`, then `A` has `ADMIN OPTION` on `C` (but not necessarily on `B`). 370 * **Permissions**: must be an administrator or role admin. 371 * **Enterprise requirement**: valid license required. 372 373 #### REVOKE role 374 375 ``` 376 REVOKE [ ADMIN OPTION FOR ] rolename FROM name 377 ``` 378 379 * **Behavior**: removes `name` as a member of `rolename`. Member admin setting is removed if `ADMIN OPTION FOR` is specified, but the membership remains. 380 Fails if either `rolename` or `name` does not exist. Succeeds if the membership does not exist. 381 * **Permissions**: must be an administrator or role admin. 382 * **Enterprise requirement**: valid license required. 383 384 #### SHOW ROLES 385 386 ``` 387 SHOW ROLES 388 ``` 389 390 * **Behavior**: lists all existing roles (role names only). 391 * **Permissions**: none required. 392 * **Enterprise requirement**: none required. 393 394 #### SHOW GRANTS ON ROLE 395 396 ``` 397 SHOW GRANTS ON ROLE [rolename] [ FOR name ] 398 ``` 399 400 Where `rolename` can be one or more role and `name` can be one of more user or role. An unspecified `rolename` 401 or `name` returns all roles or members. 402 403 * **Behavior**: lists role memberships for matching roles/names. 404 * **Permissions**: none required. 405 * **Enterprise requirement**: none required. 406 407 **TODO(mberhault)**: should we have an option to pick whether to show direct/indirect/all memberships? 408 409 ### Modifying role memberships 410 411 Modifying role memberships is done through normal operations on the system tables. 412 413 However, we set `UpVersion` on the `role_members` table to trigger a descriptor version upgrade, 414 notifying lease holders that a refresh is needed. 415 416 ### Expanding role memberships 417 418 Expanding role memberships is necessary to perform permission checks. Given how frequently these need to be 419 done, we propose a per-node cache of role memberships with refreshes triggered by increases of the 420 `role_members` table descriptor version. 421 422 The process for a permission check is: 423 * if the user's expanded roles is not cached, expand roles using the `role_members` table. 424 * reads of the `role_members` table is performed at the table descriptor's `ModificationTime` 425 * the cache holds a lease on the `role_members` table 426 * when the `role_members` table descriptor version changes (indicating a change to role memberships), refresh the roles from the table 427 428 This insures that we can keep role membership information reasonably current with refreshes being forced 429 only when changes occur. 430 431 The role cache can be a simple LRU cache with a maximum size of a few MB, but this limit should be configurable. 432 Given the likely small size of the cached entries, we can expire them after some amount of inactivity rather than 433 constantly refreshing them. 434 435 Role membership expansion can be pre-computed (see [Internal representation of memberships](#internal-representation-of-memberships)) to allow for cheaper lookup at the time of permission checks. 436 437 ### Checking permissions 438 439 Permission checks currently consist of calls to one of: 440 ``` 441 func (p *planner) CheckPrivilege(descriptor sqlbase.DescriptorProto, privilege privilege.Kind) error 442 func (p *planner) CheckAnyPrivilege(descriptor sqlbase.DescriptorProto) error 443 func (p *planner) RequireAdminRole(action string) error 444 func (p *planner) HasAdminRole() (bool, error) 445 func (p *planner) MemberOfWithAdminOption(member string) (map[string]bool, error) 446 ``` 447 448 All methods operate on `p.session.User`. 449 450 These functions check a number of things for the specified user: 451 * has the required privileges in the descriptor 452 * is the `root` or `node` user 453 * has "any" privileges on the descriptor 454 455 In a world with roles, permission checks are performed against the set of names consisting of: 456 * the username 457 * the expanded list of roles the user is a member of 458 459 Checking permissions becomes checking that any of the names in the set have the required permissions. 460 For `root` checks, this is hard-coded to checking that the expanded list includes the `admin` role. 461 462 ### Admin role 463 464 The `admin` role is a special role corresponding to the current `root` user. 465 It is checked everywhere we currently check `if user == security.RootUser`. 466 467 It is created at cluster-creation time (or migration) and initialized with the `root` 468 user as a member. 469 470 The `admin` role cannot be dropped and cannot be empty (member removal of the last member 471 will fail). 472 473 ### Migrations and backwards compatibility 474 475 Migrations from older versions will perform the following tasks: 476 * add the `isRole` column to the `system.users` table 477 * add the `admin` role to the `system.users` table 478 * create the `system.role_members` table 479 * create the `root` user 480 * add `root` as a member of `admin` with `isAdmin = true` 481 * give admin the same privileges as the `root` user 482 483 Notes: 484 * we intentionally do not remove `root` privileges to allow for binary downgrade. 485 * is a user named `admin` exists, `log.Fatal` the migration and ask the user to downgrade/drop the user/try again. 486 487 ### Non-enterprise functionality 488 489 See [Non-enterprise users](#non-enterprise-users) for actions requiring an enterprise license. 490 491 All prohibited actions are in the "administrative" category of operations (role management), and not 492 in the path of data-access SQL queries. 493 494 This makes the enterprise license check relatively painless. 495 496 It is currently possible to manipulate the system tables directly, bypassing role manipulation statements. 497 Closing this loop-hole is out of scope for this document. See [tracking issue #19277](https://github.com/cockroachdb/cockroach/issues/19277). 498 499 ### Virtual tables 500 501 We must populate some virtual tables with role information. 502 503 #### pg_catalog.pg_roles 504 505 See [PostgresSQL doc](https://www.postgresql.org/docs/current/static/view-pg-roles.html) 506 507 The existing `pg_roles` table is currently populated for all users: 508 ``` 509 h.UserOid(username), // oid 510 tree.NewDName(username), // rolname 511 tree.MakeDBool(isRoot), // rolsuper 512 tree.MakeDBool(false), // rolinherit 513 tree.MakeDBool(isRoot), // rolcreaterole 514 tree.MakeDBool(isRoot), // rolcreatedb 515 tree.MakeDBool(false), // rolcatupdate 516 tree.MakeDBool(true), // rolcanlogin 517 negOneVal, // rolconnlimit 518 tree.NewDString("********"), // rolpassword 519 tree.DNull, // rolvaliduntil 520 tree.NewDString("{}"), // rolconfig 521 ``` 522 523 A similar entry must be created for each existing role with the following changes: 524 * `isRoot` is replaced with the condition `rolename == admin` 525 * `rolcanlogin` is always false 526 527 **TODO(mberhault)**: determine if members that inherit superuser roles are listed here with the inherited attributes 528 (eg: if `marc ∈ admin`, does `marc` have `rolsuper` set to true?). 529 530 #### pg_catalog.pg_auth_members 531 532 See [PostgresSQL doc](https://www.postgresql.org/docs/current/static/catalog-pg-auth-members.html) 533 534 The new virtual table `pg_auth_members` must be added. It describes role memberships: 535 ``` 536 CREATE TABLE pg_catalog.pg_auth_members ( 537 roleid OID, ; ID of the role that has a member 538 member OID, ; ID of the member 539 grantor OID, ; ID of the role that granted this membership 540 admin_options BOOL ; true if member can grant membership in roleid to others 541 ) 542 ``` 543 544 The `grantor` may or may not be a bogus value. 545 546 **TODO(mberhault)**: determine PostgreSQL logic for grantor (especially if original OID is dropped). 547 548 #### pg_catalog.pg_authid 549 550 See [PostgreSQL doc](https://www.postgresql.org/docs/current/static/catalog-pg-authid.html). 551 552 The `pg_authid` virtual table is not currently implemented in Cockroach. 553 It contains sensitive information (passwords) and PostgreSQL clearly states: 554 ``` 555 Since this catalog contains passwords, it must not be publicly readable. pg_roles is a publicly readable view on pg_authid that blanks out the password field. 556 ``` 557 558 We propose to keep in unimplemented, users should query `pg_roles` and `pg_auth_members` instead. 559 560 #### information_schema 561 562 There are multiple relevant tables in `information_schema` that must be changed or added. 563 * `administrable_role_authorizations`: roles the current user has the `ADMIN OPTION` on. 564 * `applicable_roles`: roles whose privileges the current user can use. 565 * `enabled_roles`: roles the current use is a member of (direct or indirect). 566 * `role_table_grants`: similar to the existing `table_privileges`. 567 568 **TODO(mberhault)**: determine exactly which are needed and flesh out details. 569 570 ## Drawbacks 571 572 Roles themselves follow the PostgreSQL behavior and any drawbacks there are intended for compatibility. 573 574 There are some minor drawbacks to this implementation. 575 576 ### Use of leases to signal role changes 577 578 While allowing for cheaper role expansions, the use of leases to signal role membership changes 579 subverts the original purpose. 580 581 If a more appropriate solution is found, it can replace the current mechanism at a later date. 582 583 ### Code location 584 585 The role manipulation code is very similar to user manipulation (it's just a field inside `system.users`), making 586 it preferable to reuse most of the code. We also need the role logic (expand roles, check privileges, etc..) to 587 keep working in non-enterprise mode. 588 589 These make it tricky to place all the role-related code in `pkg/ccl`. We need to figure out exactly which code 590 can be kept separate. 591 592 ## Rationale and Alternatives 593 594 ### Internal representation of memberships 595 596 The current proposal requires an iterative lookup to discover all memberships for a user. 597 This is the most naive way of representing memberships and maps well to the conceptual representation of roles. 598 599 This makes role manipulation cheap, with role lookups bearing the brunt of the cost. 600 601 Some alternatives include: 602 603 Expanding role membership into the roles table (each role contains the list of all roles its a member of): 604 * **Pros**: fast lookup of a user's memberships 605 * **Cons**: more complex manipulation of roles, needs a concept of "direct" vs "indirect" membership 606 607 Expanding role membership into database/table descriptors (descriptor contains all users with privileges): 608 * **Pros**: regular SQL operations only require the user and descriptor 609 * **Cons**: more complex manipulation of roles, increased cost for very large roles 610 611 Dual tables: one for direct role membership information, one for expanded membership information: 612 * the direct membership table would include the `ADMIN OPTION` field and would be queried for role manipulation 613 * permission checking only requires lookups in the expanded table 614 * the expanded table can use an index on the user or even an array type for the list of roles 615 * **Pros**: fast lookup of a users's memberships 616 * **Cons**: slightly more complex role manipulation 617 618 ## Future improvements 619 620 ### Move privileges to their own table 621 622 Privileges are currently stored in database/table descriptors. To properly integrate with the 623 role change control, they need to be moved to their own table. 624 625 [Existing issue](https://github.com/cockroachdb/cockroach/issues/2939). 626 627 ### Role attributes 628 629 We do not currently have attributes on users or roles. 630 631 While we do not propose to implement all of them, some of them would be useful. For instance: 632 * `SUPERUSER`: database superuser 633 * `CREATEDB`: can create databases 634 * `CREATEROLE`: can manipulate all roles (except the superuser roles) 635 * `INHERIT|NOINHERIT`: roles privileges are inherited (or not) 636 637 Implementing additional attributes is out of scope for this RFC. If added, this can be done for 638 both users and roles by adding the corresponding columns to the `system.users` table. 639 640 ### Convenience statements 641 642 Some SQL statements can be enhanced to improve usability. For example: 643 644 Adding members `firstmember` and `secondmember` when creating a new role `myrole`: 645 ``` 646 CREATE ROLE myrole ROLE firstmember, secondmember 647 ``` 648 649 Adding the new role `myrole` as a member of existing roles `existingrole1` `existingrole2: 650 ``` 651 CREATE ROLE myrole IN ROLE existingrole1, existingrole2 652 ``` 653 654 Adding members `firstadmin` and `secondadmin` to the new role `myrole` with the `ADMIN OPTION` set: 655 ``` 656 CREATE ROLE myrole ADMIN firstadmin, secondadmin 657 ``` 658 659 ### UI visibility and management 660 661 At the very least, the admin UI should show role information (privileges on objects, memberships, etc...). 662 Manipulation of roles may be a UI event. 663 664 Changing roles through the admin UI should be possible, but is currently gated on admin UI authentication. 665 666 ### Backup/restore of privileges/users/roles 667 668 Backup/restore currently does not restore privileges or users. 669 Should it start doing so, roles must be restored as well.