Rechercher dans le manuel MySQL

6.3.4 Using Roles

A MySQL role is a named collection of privileges. Like user accounts, roles can have privileges granted to and revoked from them.

A user account can be granted roles, which grants to the account the privileges associated with each role. This enables assignment of sets of privileges to accounts and provides a convenient alternative to granting individual privileges, both for conceptualizing desired privilege assignments and implementing them.

The following list summarizes role-management capabilities provided by MySQL:

  • CREATE ROLE and DROP ROLE enable roles to be created and removed.

  • GRANT and REVOKE enable privilege assignment and revocation for user accounts and roles.

  • SHOW GRANTS displays privilege and role assignments for user accounts and roles.

  • SET DEFAULT ROLE specifies which account roles are active by default.

  • SET ROLE changes the active roles within the current session.

  • The CURRENT_ROLE() function displays the active roles within the current session.

  • The mandatory_roles and activate_all_roles_on_login system variables enable defining mandatory roles and automatic activation of granted roles when users log in to the server.

For descriptions of individual role-manipulation statements, see Section 13.7.1, “Account Management Statements”. The following discussion provides examples of role usage. Unless otherwise specified, SQL statements shown here should be executed using a MySQL account with administrative privileges, such as the root account.

Creating Roles and Granting Privileges to Them

Consider this scenario:

  • An application uses a database named app_db.

  • Associated with the application, there can be accounts for developers who create and maintain the application, and for users who interact with it.

  • Developers need full access to the database. Some users need only read access, others need read/write access.

To avoid granting privileges individually to possibly many user accounts, create roles as names for the required privilege sets. This makes it easy to grant the required privileges to user accounts, by granting the appropriate roles.

To create the roles, use CREATE ROLE:

  1. CREATE ROLE 'app_developer', 'app_read', 'app_write';

Role names are much like user account names and consist of a user part and host part in 'user_name'@'host_name' format. The host part, if omitted, defaults to '%'. The user and host parts can be unquoted unless they contain special characters such as - or %. Unlike account names, the user part of role names cannot be blank. For additional information, see Section 6.2.5, “Specifying Role Names”.

To assign privileges to the roles, execute GRANT using the same syntax as for assigning privileges to user accounts:

  1. GRANT ALL ON app_db.* TO 'app_developer';
  2. GRANT SELECT ON app_db.* TO 'app_read';
  3. GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write';

Now suppose that initially you require one developer account, two user accounts that need read-only access, and one user account that needs read/write access. Use CREATE USER to create the accounts:

  1. CREATE USER 'dev1'@'localhost' IDENTIFIED BY 'dev1pass';
  2. CREATE USER 'read_user1'@'localhost' IDENTIFIED BY 'read_user1pass';
  3. CREATE USER 'read_user2'@'localhost' IDENTIFIED BY 'read_user2pass';
  4. CREATE USER 'rw_user1'@'localhost' IDENTIFIED BY 'rw_user1pass';

To assign each user account its required privileges, you could use GRANT statements of the same form as just shown, but that requires enumerating individual privileges for each user. Instead, use an alternative GRANT syntax that permits granting roles rather than privileges:

  1. GRANT 'app_developer' TO 'dev1'@'localhost';
  2. GRANT 'app_read' TO 'read_user1'@'localhost', 'read_user2'@'localhost';
  3. GRANT 'app_read', 'app_write' TO 'rw_user1'@'localhost';

The GRANT statement for the rw_user1 account grants the read and write roles, which combine to provide the required read and write privileges.

The GRANT syntax for granting roles to an account differs from the syntax for granting privileges: There is an ON clause to assign privileges, whereas there is no ON clause to assign roles. Because the syntaxes are distinct, you cannot mix assigning privileges and roles in the same statement. (It is permitted to assign both privileges and roles to an account, but you must use separate GRANT statements, each with syntax appropriate to what is to be granted.)

Table des matières Haut

Defining Mandatory Roles

It is possible to specify roles as mandatory by naming them in the value of the mandatory_roles system variable. The server treats a mandatory role as granted to all users, so that it need not be granted explicitly to any account.

To specify mandatory roles at server startup, define mandatory_roles in your server my.cnf file:

[mysqld]
mandatory_roles='role1,role2@localhost,r3@%.example.com'

To set and persist mandatory_roles at runtime, use a statement like this:

  1. SET PERSIST mandatory_roles = 'role1,role2@localhost,r3@%.example.com';

SET PERSIST sets the value for the running MySQL instance. It also saves the value to be used for subsequent server restarts; see Section 13.7.5.1, “SET Syntax for Variable Assignment”. To change a value for the running MySQL instance without saving it for subsequent restarts, use the GLOBAL keyword rather than PERSIST.

Setting mandatory_roles requires the ROLE_ADMIN privilege, in addition to the SYSTEM_VARIABLES_ADMIN or SUPER privilege normally required to set a global system variable.

Mandatory roles, like explicitly granted roles, do not take effect until activated (see Activating Roles). At login time, role activation occurs for all granted roles if the activate_all_roles_on_login system variable is enabled, or only for roles that are set as default roles otherwise. At runtime, SET ROLE activates roles.

Roles named in the value of mandatory_roles cannot be revoked with REVOKE or dropped with DROP ROLE or DROP USER.

If a role named in mandatory_roles is not present in the mysql.user system table, the role is not granted to users. When the server attempts role activation for a user, it does not treat the nonexistent role as mandatory and writes a warning to the error log. If the role is created later and thus becomes valid, FLUSH PRIVILEGES may be necessary to cause the server to treat it as mandatory.

SHOW GRANTS displays mandatory roles according to the rules described in Section 13.7.6.21, “SHOW GRANTS Syntax”.

Table des matières Haut

Checking Role Privileges

To verify the privileges assigned to an account, use SHOW GRANTS. For example:

  1. mysql> SHOW GRANTS FOR 'dev1'@'localhost';
  2. +-------------------------------------------------+
  3. | Grants for dev1@localhost                       |
  4. +-------------------------------------------------+
  5. | GRANT USAGE ON *.* TO `dev1`@`localhost`        |
  6. | GRANT `app_developer`@`%` TO `dev1`@`localhost` |
  7. +-------------------------------------------------+

However, that shows each granted role without expanding it to the privileges the role represents. To show role privileges as well, add a USING clause naming the granted roles for which to display privileges:

  1. mysql> SHOW GRANTS FOR 'dev1'@'localhost' USING 'app_developer';
  2. +----------------------------------------------------------+
  3. | Grants for dev1@localhost                                |
  4. +----------------------------------------------------------+
  5. | GRANT USAGE ON *.* TO `dev1`@`localhost`                 |
  6. | GRANT ALL PRIVILEGES ON `app_db`.* TO `dev1`@`localhost` |
  7. | GRANT `app_developer`@`%` TO `dev1`@`localhost`          |
  8. +----------------------------------------------------------+

Verify each other type of user similarly:

  1. mysql> SHOW GRANTS FOR 'read_user1'@'localhost' USING 'app_read';
  2. +--------------------------------------------------------+
  3. | Grants for read_user1@localhost                        |
  4. +--------------------------------------------------------+
  5. | GRANT USAGE ON *.* TO `read_user1`@`localhost`         |
  6. | GRANT SELECT ON `app_db`.* TO `read_user1`@`localhost` |
  7. | GRANT `app_read`@`%` TO `read_user1`@`localhost`       |
  8. +--------------------------------------------------------+
  9. mysql> SHOW GRANTS FOR 'rw_user1'@'localhost' USING 'app_read', 'app_write';
  10. +------------------------------------------------------------------------------+
  11. | Grants for rw_user1@localhost                                                |
  12. +------------------------------------------------------------------------------+
  13. | GRANT USAGE ON *.* TO `rw_user1`@`localhost`                                 |
  14. | GRANT SELECT, INSERT, UPDATE, DELETE ON `app_db`.* TO `rw_user1`@`localhost` |
  15. | GRANT `app_read`@`%`,`app_write`@`%` TO `rw_user1`@`localhost`               |
  16. +------------------------------------------------------------------------------+

SHOW GRANTS displays mandatory roles according to the rules described in Section 13.7.6.21, “SHOW GRANTS Syntax”.

Table des matières Haut

Activating Roles

Roles granted to a user account can be active or inactive within account sessions. If a granted role is active within a session, its privileges apply; otherwise, they do not. To determine which roles are active within the current session, use the CURRENT_ROLE() function.

By default, granting a role to an account or naming it in the mandatory_roles system variable value does not automatically cause the role to become active within account sessions. For example, because thus far in the preceding discussion no rw_user1 roles have been activated, if you connect to the server as rw_user1 and invoke the CURRENT_ROLE() function, the result is NONE (no active roles):

  1. mysql> SELECT CURRENT_ROLE();
  2. +----------------+
  3. | CURRENT_ROLE() |
  4. +----------------+
  5. | NONE           |
  6. +----------------+

To specify which roles should become active each time a user connects to the server and authenticates, use SET DEFAULT ROLE. To set the default to all assigned roles for each account created earlier, use this statement:

  1.   'dev1'@'localhost',
  2.   'read_user1'@'localhost',
  3.   'read_user2'@'localhost',
  4.   'rw_user1'@'localhost';

Now if you connect as rw_user1, the initial value of CURRENT_ROLE() reflects the new default role assignments:

  1. mysql> SELECT CURRENT_ROLE();
  2. +--------------------------------+
  3. | CURRENT_ROLE()                 |
  4. +--------------------------------+
  5. | `app_read`@`%`,`app_write`@`%` |
  6. +--------------------------------+

To cause all explicitly granted and mandatory roles to be automatically activated when users connect to the server, enable the activate_all_roles_on_login system variable. By default, automatic role activation is disabled.

Within a session, a user can execute SET ROLE to change the set of active roles. For example, for rw_user1:

  1. mysql> SET ROLE NONE; SELECT CURRENT_ROLE();
  2. +----------------+
  3. | CURRENT_ROLE() |
  4. +----------------+
  5. | NONE           |
  6. +----------------+
  7. mysql> SET ROLE ALL EXCEPT 'app_write'; SELECT CURRENT_ROLE();
  8. +----------------+
  9. | CURRENT_ROLE() |
  10. +----------------+
  11. | `app_read`@`%` |
  12. +----------------+
  13. mysql> SET ROLE DEFAULT; SELECT CURRENT_ROLE();
  14. +--------------------------------+
  15. | CURRENT_ROLE()                 |
  16. +--------------------------------+
  17. | `app_read`@`%`,`app_write`@`%` |
  18. +--------------------------------+

The first SET ROLE statement deactivates all roles. The second makes rw_user1 effectively read only. The third restores the default roles.

The effective user for stored program and view objects is subject to the DEFINER and SQL SECURITY attributes, which determine whether execution occurs in invoker or definer context (see Section 24.6, “Access Control for Stored Programs and Views”):

  • Stored program and view objects that execute in invoker context execute with the active roles within the current session.

  • Stored program and view objects that execute in definer context execute with the default roles of the user named in their DEFINER attribute. If activate_all_roles_on_login is enabled, such objects execute with all roles granted to the DEFINER user, including mandatory roles. For stored programs, if execution should occur with roles different from the default, the program body should execute SET ROLE to activate the required roles.

Table des matières Haut

Revoking Roles or Role Privileges

Just as roles can be granted to an account, they can be revoked from an account:

Roles named in the mandatory_roles system variable value cannot be revoked.

REVOKE can also be applied to a role to modify the privileges granted to it. This affects not only the role itself, but any account granted that role. Suppose that you want to temporarily make all application users read only. To do this, use REVOKE to revoke the modification privileges from the app_write role:

  1. REVOKE INSERT, UPDATE, DELETE ON app_db.* FROM 'app_write';

As it happens, that leaves the role with no privileges at all, as can be seen using SHOW GRANTS (which demonstrates that this statement can be used with roles, not just users):

  1. mysql> SHOW GRANTS FOR 'app_write';
  2. +---------------------------------------+
  3. | Grants for app_write@%                |
  4. +---------------------------------------+
  5. | GRANT USAGE ON *.* TO `app_write`@`%` |
  6. +---------------------------------------+

Because revoking privileges from a role affects the privileges for any user who is assigned the modified role, rw_user1 now has no table modification privileges (INSERT, UPDATE, and DELETE are no longer present):

  1. mysql> SHOW GRANTS FOR 'rw_user1'@'localhost'
  2.        USING 'app_read', 'app_write';
  3. +----------------------------------------------------------------+
  4. | Grants for rw_user1@localhost                                  |
  5. +----------------------------------------------------------------+
  6. | GRANT USAGE ON *.* TO `rw_user1`@`localhost`                   |
  7. | GRANT SELECT ON `app_db`.* TO `rw_user1`@`localhost`           |
  8. | GRANT `app_read`@`%`,`app_write`@`%` TO `rw_user1`@`localhost` |
  9. +----------------------------------------------------------------+

In effect, the rw_user1 read/write user has become a read-only user. This also occurs for any other accounts that are granted the app_write role, illustrating how use of roles makes it unnecessary to modify privileges for individual accounts.

To restore modification privileges to the role, simply re-grant them:

  1. GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write';

Now rw_user1 again has modification privileges, as do any other accounts granted the app_write role.

Table des matières Haut

Removing Roles

To remove roles, use DROP ROLE:

  1. DROP ROLE 'app_read', 'app_write';

Dropping a role revokes it from every account to which it was granted.

Roles named in the mandatory_roles system variable value cannot be dropped.

Table des matières Haut

User and Role Interchangeability

As has been hinted at earlier for SHOW GRANTS, which displays grants for user accounts or roles, accounts and roles can be used interchangeably. You can treat a user account like a role and grant that account to another user or a role. The effect is to grant the account's privileges and roles to the other user or role.

This set of statements demonstrates that you can grant a user to a user, a role to a user, a user to a role, or a role to a role:

  1. CREATE USER 'u1';
  2. CREATE ROLE 'r1';
  3. GRANT SELECT ON db1.* TO 'u1';
  4. GRANT SELECT ON db2.* TO 'r1';
  5. CREATE USER 'u2';
  6. CREATE ROLE 'r2';
  7. GRANT 'u1', 'r1' TO 'u2';
  8. GRANT 'u1', 'r1' TO 'r2';

The result in each case is to grant to the grantee object the privileges associated with the granted object. After executing those statements, each of u2 and r2 have been granted privileges from a user (u1) and a role (r1):

  1. mysql> SHOW GRANTS FOR 'u2' USING 'u1', 'r1';
  2. +-------------------------------------+
  3. | Grants for u2@%                     |
  4. +-------------------------------------+
  5. | GRANT USAGE ON *.* TO `u2`@`%`      |
  6. | GRANT SELECT ON `db1`.* TO `u2`@`%` |
  7. | GRANT SELECT ON `db2`.* TO `u2`@`%` |
  8. | GRANT `u1`@`%`,`r1`@`%` TO `u2`@`%` |
  9. +-------------------------------------+
  10. mysql> SHOW GRANTS FOR 'r2' USING 'u1', 'r1';
  11. +-------------------------------------+
  12. | Grants for r2@%                     |
  13. +-------------------------------------+
  14. | GRANT USAGE ON *.* TO `r2`@`%`      |
  15. | GRANT SELECT ON `db1`.* TO `r2`@`%` |
  16. | GRANT SELECT ON `db2`.* TO `r2`@`%` |
  17. | GRANT `u1`@`%`,`r1`@`%` TO `r2`@`%` |
  18. +-------------------------------------+

The preceding example is illustrative only, but interchangeability of user accounts and roles has practical application, such as in the following situation: Suppose that a legacy application development project began before the advent of roles in MySQL, so all user accounts associated with the project are granted privileges directly (rather than granted privileges by virtue of being granted roles). One of these accounts is a developer account that was originally granted privileges as follows:

  1. CREATE USER 'old_app_dev'@'localhost' IDENTIFIED BY 'old_app_devpass';
  2. GRANT ALL ON old_app.* TO 'old_app_dev'@'localhost';

If this developer leaves the project, it becomes necessary to assign the privileges to another user, or perhaps multiple users if development activies have expanded. Here are some ways to deal with the issue:

  • Without using roles: Change the account password so the original developer cannot use it, and have a new developer use the account instead:

    1. ALTER USER 'old_app_dev'@'localhost' IDENTIFIED BY 'new_password';
  • Using roles: Lock the account to prevent anyone from using it to connect to the server:

    1. ALTER USER 'old_app_dev'@'localhost' ACCOUNT LOCK;

    Then treat the account as a role. For each developer new to the project, create a new account and grant to it the original developer account:

    1. CREATE USER 'new_app_dev1'@'localhost' IDENTIFIED BY 'new_password';
    2. GRANT 'old_app_dev'@'localhost' TO 'new_app_dev1'@'localhost';

    The effect is to assign the original developer account privileges to the new account.


Rechercher dans le manuel MySQL

Traduction non disponible

Le manuel MySQL n'est pas encore traduit en français sur l'infobrol. Seule la version anglaise est disponible pour l'instant.

Document créé le 26/06/2006, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/mysql-rf-roles.html

L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.

Références

  1. Consulter le document html Langue du document :en Manuel MySQL : https://dev.mysql.com/

Ces références et liens indiquent des documents consultés lors de la rédaction de cette page, ou qui peuvent apporter un complément d'information, mais les auteurs de ces sources ne peuvent être tenus responsables du contenu de cette page.
L'auteur de ce site est seul responsable de la manière dont sont présentés ici les différents concepts, et des libertés qui sont prises avec les ouvrages de référence. N'oubliez pas que vous devez croiser les informations de sources multiples afin de diminuer les risques d'erreurs.

Table des matières Haut