共计 5245 个字符,预计需要花费 14 分钟才能阅读完成。
认识权限管理,说明主要概念及关系,与大多数数据库一样,Mongodb 同样提供了一套权限管理机制。为了体验 Mongodb 的权限管理,我们找一台已经安装好的 Mongodb,可以参照这里搭建一个单节点的 Mongodb。
直接打开 mongo shell:
./bin/mongo --port=27017
尝试执行 stats 命令以查看 appdb 数据库的状态:
MongoDB Enterprise > use appdb
MongoDB Enterprise > db.stats()
{"ok" : 0,
"errmsg" : "not authorized on nscl to execute command {dbstats: 1.0, scale: undefined}",
"code" : 13
}
此时的提示正是说明你当前的操作没有获得许可,使用 appdb 预创建的用户进行鉴权:
> db.auth('appuser','yourpassword')
1
> db.stats()
{"db" : "appdb",
"collections" : 0,
"views" : 0,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 0,
"numExtents" : 0,
"indexes" : 0,
"indexSize" : 0,
"fileSize" : 0,
"ok" : 1
}
可以发现,在通过验明身份之后,stats 操作的鉴权获得了许可。
以上例子可能让你对数据库鉴权有了点浅显认识,那么接下来开始说点概念了,大致是叫 基于角色的权限控制
[图 - 角色权限控制]
先解释下图中的几个实体:
- Resource,资源 一个资源可以是一个数据库、集合、或者一个集群.. 往大了说,任何可能被操作的事物都可以被当做资源。
- Action,动作 动作是指对资源的一个执行行为,比如读取表、读取数据库,其中读取便是一个动作。
- Privilege,权限 权限指的是对某类或某一些资源执行某些动作的允许,与 Permission 的意义一致。
- Role,角色 系统中的角色,通常是代表了一种权力等级的象征,比如论坛中的管理员、版主、游客等等,就是角色;系统定义中,角色往往代表一组权限的集合。
- User,用户 可登录系统的实体,一个用户通常可被赋予多个角色。
噢,关于图的简单解释:权限定义了对某些资源的某些操作,角色则可以拥有多个权限;用户 User 可以被赋予多个角色,从而获得这些角色所拥有的权限以操作某些资源。
对于 Mongodb 来说,只要开启鉴权,所有的 DB 访问操作都需要通过权限检查。而大致的操作流程跟下图类似
[图 -mongo 鉴权]
- Mongodb 的用户归属于某个数据库,用户需要在所属的数据库中进行鉴权;
- 一旦通过鉴权,当前的会话 (连接) 中所有操作将按照用户被赋予的角色权限执行检查。
二、鉴权方式
阐述 Mongodb 支持的几种鉴权方式 鉴权方式是指 Mongodb 如何识别接入用户,如何检查权限是否合法的一系列校验机制。
-
SCRAM-SHA-1 SCRAM-SHA-1 是默认的鉴权机制,定义于 IETF standard, RFC 5802 是一种安全性较高的 ” 挑战 - 应答 ” 鉴权机制。关于 ” 挑战 - 应答 ” 可以参考维基百科
-
MongoDB Challenge and Response (MONGODB-CR) 3.0 以前采用的机制,已经废弃
-
x.509 Certificate Authentication. 基于证书的鉴权,采用该方式可建立 SSL/TLS 加密连接
-
LDAP proxy authentication 基于 LDAP 系统的鉴权,仅企业版支持
-
Kerberos authentication 基于 Kerberos 的鉴权,仅企业版支持
SCRAM-SHA-1 是当前推荐使用的鉴权方式,既然如此,有必要上图继续解释:
步骤解读
- 客户端发起一个 SCRAM 鉴权请求;鉴权参数中带上用户名、客户端随机字符串(防止重放攻击);
- 服务端发出一个挑战响应;服务侧先检查用户名,通过后生成一个 salt 因子、迭代数、合并字符串(包含客户端随机串和服务端随机串)
- 客户端响应一个 proof(证明数据)和合并字符串;响应的 proof 数据根据服务所给的随机参数以及客户端密钥生成,是一个客户端签名与密钥异或计算后的结果;
- 服务端将存储的密钥结合随机参数,使用同样的算法生成签名并校验客户端 proof 数据;若校验通过,服务端采用类似方式发送自己的签名;
- 客户端校验服务端签名数据。
可以看到,SCRAM 鉴权时也类似 SSL/TLS 的握手过程,但相比之下简单许多,同时在性能方面也要具备优势;然后我们看看安全性的部分:
- 信息窃听,传输过程中全部采用动态签名,保证密码不会被传输;
- 重放攻击,由于使用了随机数,每次生成的数据都不一样,可避免重复数据攻击;
- 服务假冒,鉴权过程是双向的,即客户端会校验服务端身份,而服务端密钥也根据密码生成,中间人无法仿造;
- 存储安全,密码在数据库中均没有明文存储,都通过不可逆的算法加密存储。
另外 SCRAM-SHA-1 相比 MONGODB-CR 的优势 还有:
A tunable work factor (iterationCount), 可灵活调整的安全系数 Per-user random salts rather than server-wide salts 每个用户有独立的随机系数 A cryptographically stronger hash function (SHA-1 rather than MD5), 更安全的 hash 函数 Authentication of the server to the client as well as the client to the server. 支持双向认证
对 SCRAM-SHA- 1 的实现感兴趣?戳这里
三、内部鉴权
副本集、分片集群内鉴权方式
内部鉴权是指 Mongo 集群内部节点之间进行访问的鉴权方式,比如副本集内主备之间的访问、分片集群内 Mongos 与 Mongod 之间的访问。内部鉴权目前支持两种方式:
-
KeyFiles 密钥文件方式,采用SCAM-SHA-1 的鉴权机制,文件内包含了一个共享密钥,由集群内所有成员共同持有。通常,密钥的长度在 6 -1024 字符内,采用 Base64 编码。如何使用?
-
X.509 证书 证书鉴权,用于 SSL/TLS 加密连接通道。如何使用?
四、数据库角色
针对 Mongodb 数据库中的各种角色进行说明
数据库访问
角色名称 | 拥有权限 |
---|---|
read | 允许读取指定数据库的角色 |
readWrite | 允许读写指定数据库的角色 |
数据库管理
角色名称 | 拥有权限 |
---|---|
dbAdmin | 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问 system.profile |
userAdmin | 允许管理当前数据库的用户,如创建用户、为用户授权 |
dbOwner | 数据库拥有者(最高),集合了 dbAdmin/userAdmin/readWrite 角色权限 |
集群管理
角色名称 | 拥有权限 |
---|---|
clusterAdmin | 集群最高管理员,集合 clusterManager/clusterMonitor/hostManager 角色权限 |
clusterManager | 集群管理角色,允许对分片和副本集集群执行管理操作,如 addShard,resync 等 |
clusterMonitor | 集群监控角色,允许对分片和副本集集群进行监控,如查看 serverStatus |
hostManager | 节点管理角色,允许监控和管理节点,比如 killOp、shutdown 操作 |
备份恢复
角色名称 | 拥有权限 |
---|---|
backup | 备份权限,允许执行 mongodump 操作 |
restore | 恢复权限,允许执行 mongoresotre 操作 |
数据库通用角色
角色名称 | 拥有权限 |
---|---|
readAnyDatabase | 允许读取所有数据库 |
readWriteAnyDatabase | 允许读写所有数据库 |
userAdminAnyDatabase | 允许管理所有数据库的用户 |
dbAdminAnyDatabase | 允许管理所有数据库 |
特殊角色
角色名称 | 拥有权限 |
---|---|
root | 超级管理员,拥有所有权限 |
__system | 内部角色,用于集群间节点通讯 |
基本是这些,有兴趣可看看官方的内置角色 Mongodb 的用户及角色数据一般位于当前实例的 admin 数据库,system.users 存放了所有数据;存在例外的情况是分片集群,应用接入 mongos 节点,鉴权数据则存放于 config 节点。因此有时候为了方便分片集群管理,会单独为分片内部节点创建独立的管理操作用户;
五、相关操作
简单列举用户权限相关的常用操作
授权启动
./bin/mongod --auth
默认为非授权启动 也可以通过 security.authorization 配置指定
创建管理员用户
use admin
db.createUser({user:'admin',pwd:'admin@2016',roles:[{role:'clusterAdmin',db:'admin'},
{role:'userAdminAnyDatabase',db:'admin'}
]})
创建用户
use appdb
db.createUser({user:'appuser',pwd:'appuser@2016'})
授予权限
use appdb
db.grantRolesToUser("appuser", [{role:'readWrite',db:'appdb'}])
删除权限
use appdb
db.revokeRolesFromUser("appuser",[{role: "read", db: "appdb" }])
更多操作
六、常见问题
shell 操作提示错误
use appdb
MongoDB Enterprise > db.stats()
{"ok" : 0,
"errmsg" : "not authorized on appdb to execute command {dbstats: 1.0, scale: undefined}",
"code" : 13
}
原因:当前连接未鉴权或用户没有操作权限 解决:为用户分配适当权限,并执行 auth 操作,如下:
db.auth('appuser','yourpassword');
无法执行 eval 操作
db.eval() 是一个全局操作,可执行任意数据库脚本;执行该命令需要拥有 anyAction 或 anyResource 的权限,通常不建议为数据库用户赋予这样的权限。该命令存在安全风险,已不建议使用(mongodb 3.0 之后已经过期)。
七、扩展阅读
Mongodb 鉴权机制 https://docs.mongodb.com/manual/core/authentication/
Mongodb 内置角色介绍 https://docs.mongodb.com/manual/reference/built-in-roles/#database-user-roles
Mongodb 权限操作介绍 https://docs.mongodb.com/manual/reference/privilege-actions/#security-user-actions
更多 MongoDB 相关教程见以下内容:
MongoDB 文档、集合、数据库简介 http://www.linuxidc.com/Linux/2016-12/138529.htm
MongoDB 3 分片部署及故障模拟验证 http://www.linuxidc.com/Linux/2016-12/138529.htm
Linux CentOS 6.5 yum 安装 MongoDB http://www.linuxidc.com/Linux/2016-12/137790.htm
CentOS 7 yum 方式快速安装 MongoDB http://www.linuxidc.com/Linux/2016-11/137679.htm
MongoDB 的查询操作 http://www.linuxidc.com/Linux/2016-10/136581.htm
在 Azure 虚拟机上快速搭建 MongoDB 集群 http://www.linuxidc.com/Linux/2017-09/146778.htm
MongoDB 复制集原理 http://www.linuxidc.com/Linux/2017-09/146670.htm
MongoDB 3.4 远程连接认证失败 http://www.linuxidc.com/Linux/2017-06/145070.htm
Ubuntu 16.04 中安装 MongoDB3.4 数据库系统 http://www.linuxidc.com/Linux/2017-07/145526.htm
MongoDB 权威指南第 2 版 PDF 完整带书签目录 下载见 http://www.linuxidc.com/Linux/2016-12/138253.htm
MongoDB 的详细介绍:请点这里
MongoDB 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/147865.htm