简介
可能有些开发者已经知道了,MongoDB 没有管理员账号这个概念。而这也会造成一些安全漏洞,比如可以直接使用默认的 mongo 用户连接到数据库,其它人也可以无限制地使用这个用户账号访问数据库。针对这个问题,本文将详细介绍如何使用角色和访问控制列表(ACL)来保障 MongoDB 的安全。
使用角色配置 ACL
什么是角色?
角色是一组权限的集合,它表示允许某个用户在某个数据库上执行的操作。例如,可以为用户配置读写权限、读权限、创建和删除集合的权限、重启主机的权限等。 MongoDB 预先定义了许多角色,其中最常用的是 "read" 、"readWrite" 以及 "dbAdmin" 等。
如何使用角色
具体来说,我们可以通过以下步骤使用角色:
- 在 admin 数据库上创建用户并赋予相应的角色:
use admin db.createUser({user:"myuser",pwd:"mypass", roles:[{role:"readWrite",db:"testdb"}]})
上面的命令可以在 admin 数据库上创建一个名为 myuser,密码为 mypass 的用户,并分配了一个名为 "readWrite" 的角色,可以在 testdb 数据库上读写。需要注意的是,如果是在当前用户存在的情况下创建新用户,需要使用特权账户。 2. 开启 MongoDB 的授权认证
mongod --auth
- 重新连接到 MongoDB,并使用新的账户访问数据库
mongo --port 27017 -u myuser -p mypass --authenticationDatabase testdb
使用访问控制列表配置 ACL
什么是访问控制列表(ACL)?
访问控制列表,简称 ACL,就是一组权限列表,表示那些用户可以访问哪些资源(如数据库,集合等)以及在哪些资源上执行哪些操作。例如,可以为 userA 分配在某个数据库上读写的权限,为 userB 分配只读权限,而 userC 根本就没有权限使用这个数据库。
如何使用 ACL
在 MongoDB 中,使用 ACL 配置的操作大致分为三步:
- 创建用户并分配对应的 ACL
-- -------------------- ---- ------- --- ------ --------------- -------------- ------------- --------- ------------ - - --------------- -- ------------- - ---------- ----- - - --展开代码
这里调用 db.createUser
创建了一个名为 myuser 的用户,这里重点需要注意的是,在创建时需要指定 roles
为空数组,因为我们将在后面通过指定 ACL 赋予用户访问权限。mechanisms
用于指定具体使用的密码验证机制。customData
可以添加一些自定义数据到用户信息中,这里可以添加用户属于哪个部门、所处情况等信息。
2. 创建具体的 ACL 集合,并添加相应记录
use admin db.createCollection("system.acl") db.system.acl.insertMany([ { "resource": { "db": "testdb", "collection": "user" }, "actions": [ "find", "update" ], "group": "dev" }, { "resource": { "db": "testdb", "collection": "user" }, "actions": [ "insert" ], "user": "myuser" }, { "resource": { "db": "testdb", "collection": "log" }, "actions": [ "find" ], "user": "ops" } ])
创建于 database 级别的 ACL 可以以 system.acl
集合的形式存储。每个记录表示一条规则,通过 resource
指定访问的资源,比如是在某个数据库中的某个集合或是整个数据库;actions
表示在资源中能够执行的操作,比如是查询、插入、删除、更新等;user
表示允许哪些用户可以访问资源,group
表示允许哪些用户组可以访问资源。
3. 开启 MongoDB 的授权认证,并执行相应的访问控制操作。这里使用 mongo
命令行客户端,以 myuser 身份连接 DB
mongod --auth mongo --port 27017 -u myuser -p mypass --authenticationDatabase testdb db.user.find() db.user.update({name:"JohnDoe"},{$set:{age:30}})
编写完整的访问控制方案
通过上面的介绍可以知道,ACL 支持更为细化的权限控制。下面编写一个完整的实例方案。
假设要建立一个 "dev" 部门专业用户的数据库访问控制方案。在这个方案中,用户 "dev-admin" 是 dev 部门的管理员,其具备最大权限;用户 "dev-a" 和 "dev-b" 分别是 dev 部门中的两个一般用户,他们需要根据自己的需要使用不同的权限;而用户 "other-a" 和 "other-b" 则属于其它部门,应该无法使用该数据库。
首先创建两个组
创建 dev, other 两个组,并分别添加用户,为后面的 ACL 权限控制方案做准备。
-- -------------------- ---- ------- -- - ----- --------- --- ----- --------------- ----- ----------------------- ----------- - - --------- - -------- ---- -- -------- - ---------- ---------------- ------------- ----------------- - - -- ------ -- -- --------------- ----- ------------ ---- ------- ------ - ------ ----------------------- --- -------- - -- --------------- ----- ------------ ---- --------------- ------ - - ----- ----------------------- --- ------- - -- ----------- - ------- ------- - -- --------------- ----- -------- ---- ----------- ------ --- ----------- - ------- ------- --- --------------- ----- -------- ---- ----------- ------ --- ----------- - ------- ------- --- --------------- ----- ---------- ---- ------------- ------ --- ----------- - ------- --------- --- --------------- ----- ---------- ---- ------------- ------ --- ----------- - ------- --------- ---展开代码
创建具体的 ACL 规则
ACL 规则相对复杂,在这里展示一个例子:
-- -------------------- ---- ------- -- - ----- ---------- --- ----- --------------------------------- -- ------------- --------- ------- -------------------------- - ----------- - ----- --------- ---- -- -- ---------- - ---------------- ------------------ -------------- --------------- -- -------- ----- -- - ----------- - ----- --------- ------------- ------ -- ---------- - ------- --------- --------- -------- -- -------- ----- -- - ----------- - ----- --------- ------------- --------- -- ---------- - ------ -- ------- ------- -- - ----------- - ----- --------- ------------- ---- -- ---------- - ------ -- ------- ------- -- - ----------- - ----- --------- ------------- ----- -- ---------- - ------- -------- -- -------- ----- - -- -- -- -------- ------- -- ------ --------- -------------------------- - ----------- - ----- --------- ---- -- -- ---------- --- ------- --------- -- - ----------- - ----- --------- ---- -- -- ---------- --- ------- --------- - -- -- ---------------- -------------------------- - ----------- - ----- --- ---- -- -- ---------- --- ------- --------------- -- - ----------- - ----- --- ---- -- -- ---------- --- ------- --------------- -- --展开代码
给用户添加对应的角色
-- -------------------- ---- ------- --- ----- --------------- ----- ----------- ----------- - - ----------- - ----- --------- ---- -- -- ---------- - ------ - - -- ------ -- -- --------------- ----- ------------ ----------- - - ----------- - ----- --------- ---- -- -- ---------- - --------- --------- -------- - - -- ------ -- --展开代码
应用和测试
现在,我们将上述应用到设置中,并在管理员和用户之间测试权限:
- 设置启用授权认证:
在启动 mongod 时添加 --auth 参数即可,如:
mongod --auth --dbpath /data/db
这将启用 MongoDB 授权认证,你需要使用用户名密码才能连接到数据库。
- 系统管理员用户登录:
使用名为 dev-admin 的用户,密码为 devadminpass,登录到 MongoDB 系统管理接口。
mongo --port 27017 -u dev-admin -p devadminpass --authenticationDatabase admin
- 修改用户访问权限:
为 dev-a 分配读取 finance 数据的权限,为 dev-b 分配读取 hr 数据的权限:
use admin db.grantRolesToUser("dev-a", [{role: "dev-read", db: "testdb"}]) db.grantRolesToUser("dev-b", [{role: "dev-read", db: "testdb"}])
- 普通用户登录:
使用名为 dev-a 的用户,密码为 devapass,登录到 MongoDB 接口。
mongo --port 27017 -u dev-a -p devapass --authenticationDatabase testdb
尝试访问资源:
db.user.find() # 无权限 db.finance.find() # 有权限访问
- 验证 ACL 规则:
我们已经制定了一些精细的规则来限制访问:
- 使用远端 IP 地址限制访问,没有权限的电脑无法连接。
- 除了组 dev-admin 以外,用户无法修改数据库结构。
- 用户 dev-admin 通过 grantedRoles 命令修改组成员的权限,即使他本质上不应该拥有这样的权利也是如此。
最后,想必读者已经了解了如何处理 MongoDB 没有管理员账号的情况,掌握了使用角色和 ACL 进行 MongoDB 服务管理的相关知识,下一步可以继续深入了解 MongoDB 授权认证的理论和实践。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c8f640e46428fe9efd3c9c