MySQL安全与审计之:`MySQL`的`Role`管理:其在`MySQL 8.0`中的权限管理新特性。

好的,下面我将以讲座的模式,详细介绍MySQL 8.0中Role的管理及其在权限管理中的新特性。

MySQL安全与审计之:MySQL的Role管理

大家好,今天我们来探讨MySQL 8.0中引入的Role管理,以及它在权限管理方面带来的新特性。在传统MySQL权限管理中,我们直接将权限授予用户,当用户数量庞大,权限类型繁多时,管理会变得非常复杂。Role的引入,有效简化了权限管理,提高了效率和安全性。

1. Role的概念与优势

Role本质上是一组权限的集合。我们可以将一组相关的权限打包成一个Role,然后将这个Role授予用户。用户拥有Role,就相当于拥有了Role中包含的所有权限。

优势:

  • 简化权限管理: 避免了重复授予相同权限给多个用户。
  • 权限变更集中化: 修改Role的权限,所有拥有该Role的用户权限也随之更新。
  • 提高安全性: 方便权限撤销和审计,降低权限泄露风险。
  • 提升可维护性: 通过Role划分职责,使权限结构更加清晰。

2. Role的创建、删除与修改

2.1 创建Role

使用CREATE ROLE语句创建Role。

CREATE ROLE 'developer'@'%';
CREATE ROLE 'dba'@'localhost';
CREATE ROLE 'readonly'@'192.168.1.%';
  • CREATE ROLE 'role_name'@'host';: role_name是Role的名称,host指定Role可以被哪个主机上的用户使用。 '%'表示所有主机,'localhost'表示本地主机,'192.168.1.%' 表示192.168.1.网段的所有主机。

2.2 删除Role

使用DROP ROLE语句删除Role。

DROP ROLE 'developer'@'%';
DROP ROLE 'dba'@'localhost';
DROP ROLE 'readonly'@'192.168.1.%';
  • DROP ROLE 'role_name'@'host';: 删除指定的Role。

2.3 修改Role (间接修改)

MySQL 目前没有直接修改 Role 名称或 Host 的语句。如果需要修改,需要先删除原 Role,然后重新创建。但是,我们可以通过修改 Role 包含的权限来间接修改 Role 的功能。

3. Role的权限授予与撤销

3.1 向Role授予权限

使用GRANT语句向Role授予权限。

GRANT SELECT, INSERT, UPDATE ON `mydb`.* TO 'developer'@'%';
GRANT ALL PRIVILEGES ON `security_db`.* TO 'dba'@'localhost';
GRANT SELECT ON `report_db`.* TO 'readonly'@'192.168.1.%';
  • GRANT privilege_list ON database.table TO 'role_name'@'host';: privilege_list是权限列表,database.table是数据库和表名,'role_name'@'host'是要授予权限的Role。

3.2 从Role撤销权限

使用REVOKE语句从Role撤销权限。

REVOKE INSERT ON `mydb`.* FROM 'developer'@'%';
REVOKE ALL PRIVILEGES ON `security_db`.* FROM 'dba'@'localhost';
REVOKE SELECT ON `report_db`.* FROM 'readonly'@'192.168.1.%';
  • REVOKE privilege_list ON database.table FROM 'role_name'@'host';: privilege_list是权限列表,database.table是数据库和表名,'role_name'@'host'是要撤销权限的Role。

4. Role的激活与禁用

4.1 将Role授予用户

使用GRANT语句将Role授予用户。

GRANT 'developer'@'%' TO 'user1'@'%';
GRANT 'dba'@'localhost' TO 'root'@'localhost';
GRANT 'readonly'@'192.168.1.%' TO 'user2'@'192.168.1.100';
  • GRANT 'role_name'@'host' TO 'user_name'@'host';: 'role_name'@'host'是要授予的Role,'user_name'@'host'是要授予Role的用户。

4.2 激活Role

用户登录后,Role默认处于未激活状态。需要使用SET ROLE语句激活Role。

SET ROLE 'developer'@'%';
SET ROLE 'dba'@'localhost';
SET ROLE 'readonly'@'192.168.1.%';

SET ROLE ALL;  -- 激活所有授予用户的Role
SET ROLE DEFAULT; -- 激活默认Role (如果设置了默认Role)
SET ROLE NONE;  -- 禁用所有Role
  • SET ROLE 'role_name'@'host';: 激活指定的Role。
  • SET ROLE ALL;: 激活所有授予用户的Role。
  • SET ROLE DEFAULT;: 激活默认Role(如果设置了默认Role)。
  • SET ROLE NONE;: 禁用所有Role,用户只拥有直接授予的权限。

4.3 设置默认Role

可以使用ALTER USER语句设置用户的默认Role。

ALTER USER 'user1'@'%' DEFAULT ROLE 'developer'@'%';
ALTER USER 'root'@'localhost' DEFAULT ROLE 'dba'@'localhost';
ALTER USER 'user2'@'192.168.1.100' DEFAULT ROLE 'readonly'@'192.168.1.%';
  • ALTER USER 'user_name'@'host' DEFAULT ROLE 'role_name'@'host';: 设置用户的默认Role。用户登录后,默认Role会自动激活。可以使用DEFAULT ROLE NONE取消默认Role。

5. Role的查看

5.1 查看已存在的Role

可以使用以下语句查询已存在的Role:

SELECT * FROM mysql.roles_mapping;

5.2 查看Role的权限

可以使用以下语句查看Role拥有的权限:

SHOW GRANTS FOR 'developer'@'%';
SHOW GRANTS FOR 'dba'@'localhost';
SHOW GRANTS FOR 'readonly'@'192.168.1.%';

5.3 查看用户拥有的Role

可以使用以下语句查看用户拥有的Role:

SELECT * FROM mysql.role_edges WHERE FROM_USER = 'user1' AND FROM_HOST = '%';
SELECT * FROM mysql.role_edges WHERE FROM_USER = 'root' AND FROM_HOST = 'localhost';
SELECT * FROM mysql.role_edges WHERE FROM_USER = 'user2' AND FROM_HOST = '192.168.1.100';

5.4 查看当前会话激活的Role

SELECT CURRENT_ROLE();

6. Role使用示例

假设我们有一个电商网站,需要创建三个Role:developeranalystadministrator

  • developer:拥有开发数据库的读写权限。
  • analyst:拥有报表数据库的只读权限。
  • administrator:拥有所有数据库的读写权限。

6.1 创建Role

CREATE ROLE 'developer'@'%';
CREATE ROLE 'analyst'@'%';
CREATE ROLE 'administrator'@'%';

6.2 向Role授予权限

GRANT SELECT, INSERT, UPDATE, DELETE ON `ecommerce_dev`.* TO 'developer'@'%';
GRANT SELECT ON `ecommerce_report`.* TO 'analyst'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'administrator'@'%';

6.3 创建用户并授予Role

CREATE USER 'dev1'@'%' IDENTIFIED BY 'password';
CREATE USER 'analyst1'@'%' IDENTIFIED BY 'password';
CREATE USER 'admin1'@'%' IDENTIFIED BY 'password';

GRANT 'developer'@'%' TO 'dev1'@'%';
GRANT 'analyst'@'%' TO 'analyst1'@'%';
GRANT 'administrator'@'%' TO 'admin1'@'%';

6.4 激活Role

用户登录后,需要激活Role才能拥有相应的权限。

-- dev1登录后
SET ROLE 'developer'@'%';

-- analyst1登录后
SET ROLE 'analyst'@'%';

-- admin1登录后
SET ROLE 'administrator'@'%';

7. Role与权限继承

MySQL 8.0 支持 Role 的嵌套,即一个 Role 可以被授予给另一个 Role,从而实现权限的继承。

7.1 创建嵌套Role

CREATE ROLE 'senior_developer'@'%';
GRANT 'developer'@'%' TO 'senior_developer'@'%'; -- 将'developer'@'%'授予给'senior_developer'@'%'
GRANT CREATE TEMPORARY TABLES ON *.* TO 'senior_developer'@'%'; -- 额外授予创建临时表的权限

7.2 将嵌套Role授予用户

CREATE USER 'dev2'@'%' IDENTIFIED BY 'password';
GRANT 'senior_developer'@'%' TO 'dev2'@'%';

用户 dev2 将会继承 senior_developerdeveloper 的所有权限。

8. Role的限制

  • 存储过程和函数中的Role: 在存储过程和函数中,Role的激活状态不会被继承。需要使用SQL SECURITY DEFINER属性来指定存储过程或函数的执行权限。
  • 触发器中的Role: 触发器中同样不会继承Role的激活状态。
  • 视图中的Role: 视图的权限取决于定义视图的用户,而不是当前用户的Role。

9. 使用 mandatory roles 强制激活角色

MySQL 8.0.22 引入了mandatory roles 的概念。这可以强制某些角色始终处于激活状态,无法使用 SET ROLE NONE 关闭。这提高了安全性,确保用户始终具有某些必要的权限。

SET PERSIST mandatory_roles = '`developer`@`%`,`analyst`@`%`';

这会设置 developeranalyst 角色为 mandatory roles。用户仍然可以激活其他的 roles,但无法禁用mandatory roles。

10. Role与SQL注入防御

Role本身并不能直接防御SQL注入,SQL注入是一种代码层面的安全漏洞。但是,通过合理使用Role,可以降低SQL注入的风险。例如,可以创建一个只读Role,用于执行查询操作,从而防止恶意用户通过SQL注入修改数据。

11. 总结:权限管理更加高效

Role是MySQL 8.0中一个非常重要的权限管理新特性,它简化了权限管理,提高了安全性,提升了可维护性。通过合理使用Role,我们可以更好地管理MySQL数据库的权限,确保数据的安全。 通过权限继承,强制激活角色,使得权限管理更加高效,安全。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注