此文已由作者温正湖授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

目前蜂巢(云计算基础服务)MongoDB上已经有数十个实例,其中不少是企业用户或公司内部产品用户的。用户多了,那就会反馈一些问题。其中一个就是MongoDB实例访问账号,虽能够提供创建和删除集合、索引,创建数据库等用户所需的权限,但无法删除数据库,这个问题虽然不严重,但多少会影响用户体验。那么这是为什么呢?本文以此作为入口来谈谈MongoDB的账号管理。

MongoDB作为一个成熟的数据库,像MySQL一样,也提供账号管理,但又跟MySQL不大一样,MongoDB使用基于角色的访问权限控制(Role-Based Access Control,RBAC),包括账号(Users,直译为用户,但似乎账号更好理解)、角色(Roles)和权限(Privileges)三层关系。权限指的是允许对某种资源进行的某些操作。这里所说的资源,包括数据库、集合和集群等。在进行MongoDB权限管理操作时,资源使用一个文档来表示,比如数据库mydb下的集合mycoll作为一种资源表示为{db: "mydb", collection: "mycoll"}。{db: "mydb", collection: ""}表示数据库mydb下的所有集合。对应地,{db: "", collection: "mycoll"}就是所有数据库下的mycoll集合,集群资源表示为{cluster: true},如果要将所有数据库和集群作为一种资源那么可以表示为{anyResource: true}。所说的操作包括对集合的CRUD,查看数据库下的集合列表,查看复制集或分片集群当前状态等。根据操作类型,又可以分为:读写操作,数据库管理操作,集群部署操作,复制集操作,分片集群操作,系统管理操作,诊断操作,内部操作等8大类。

MongoDB对外提供的是账号,作为访问MongoDB认证单位。内部,一个账号可以由0到多个角色组成,角色分为内建角色(Built-In Roles)和自定义角色(User-Defined Roles)。为了方便使用,MongoDB提供了多种内建角色,分为数据库用户,数据库管理员,集群管理员,备份和恢复角色,跨数据库角色,超级用户,内部用户等7大类,每个大类下面有可以分为不同权限的角色,比如数据库用户大类可细分为读read和读写readWrite两种角色,而每个角色拥有一定的权限,比如readWrite角色具有创建/删除集合、创建删除索引和集合CRUD等16种权限,跨数据库角色表示该角色不仅对某个数据库有指定的操作权限,还对实例中其他所有(用户创建的)的数据库都具备同样的权限,比如readWriteAnyDatabase,具备对所有数据库有readWrite权限。这里有个特例,就是给用户授权角色时,如果授权时指定的数据库是admin,则即使仅指定readWrite,也同样具备readWriteAnyDatabase角色,也就是说对admin具有readWrite角色,那么对其他数据库也具有,天然具有AnyDatabase光辉。

蜂巢(云计算基础服务)MongoDB提供了MongoDB复制集实例,用户可以创建readWriteAnyDatabase权限的账号来访问MongoDB,为什么要AnyDatabase呢?因为我们还未提供MongoDB的数据库和账号管理功能(接管用户所有的数据库/集合、用户创建和权限管理操作),无法限制用户创建数据库,所以也就无法为特定某个数据库授予readWrite权限。readWriteAnyDatabase权限具备了复制集场景下用户所需的绝大部分权限,包括集合、索引的创建和删除,数据库/集合等统计信息。就像文章刚开始的描述一样,其不具备删除数据库(dropDatabase)这个权限,虽然有点坑,但还不是大问题,只需在后续提供MongoDB的数据库和账号管理功能中,将dropDatabase权限纳入管理即可。但在分片集群场景下,readWriteAnyDatabase所具有的的权限已经根本无法满足用户的正常操作,比如对数据库启用分片功能(enableSharding),人工进行分片的chunk拆分(splitChunk),在我们没有数据库和账号管理功能前,这些操作都需要用户端来执行,而readWriteAnyDatabase无法满足。那么是不是有其他内建角色满足需求呢,查阅官方文档发现集群管理员下的clusterManager角色提供了我们所需的权限,但其还提供了诸如在分片集群中添加和删除分片服务器,在复制集中进行复制集重配置等重型权限,如果给用户这些权限将是非常危险的。所以,在蜂巢分片集群实例中,无法通过为用户提供拥有多个内建角色(如readWriteAnyDatabase、clusterManager两个)的账号来满足用户正常使用的需求。这个时候,自定义角色就派送用场了,在创建自定义角色时,既可以指定对资源的操作权限,还可以选择继承另一个角色所拥有的权限,比如,提供给用户的新账号继承了readWriteAnyDatabase角色的所有权限,还额外添加了dropDatabase、enableSharding和splitChunk等权限,这样一来就顺利解决了面临的问题。

关说不练假把式,结合以上的描述,演示如何为MongoDB进行账号管理操作。

1、首先在mongod配置文件中增加权限相关设置 security: {authorization: enabled, keyFile: /home/mongo/keyfile}。其中authorization表示是否启用访问权限认证,keyFile指定了MongoDB复制集或分片集群内部各组件相互间通信的认证文件;MongoDB提供了本地例外机制,避免用户在启用认证前未设置账号导致无法访问MongoDB实例的尴尬;

2、创建用户所需的数据库账号,如下:

mongos> use admin

mongos> db.createUser(
 {
   user: "myuser",
   pwd: "xxxxx",
   roles: [ { role: "readWrite", db: "admin" } ]
 }
)

指定了认证数据库为admin,角色采用内建的readWrite,由于指定的数据库是admin,那么等同于创建了readWriteAnyDatabase角色的账号。用该账号登陆:

use admin

db.auth("myuser","wzh123")

3、但该账号无法执行如下这些操作:

mongos> use mydb
mongos> db.dropDatabase()
{
"ok" : 0,
"errmsg" : "not authorized on shardtest to execute command { dropDatabase: 1.0 }",
"code" : 13,
"codeName" : "Unauthorized"
}
mongos> sh.enableSharding("wzhshard")
{
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { enableSharding: \"wzhshard\" }",
"code" : 13,
"codeName" : "Unauthorized"
}

4、所以,只能通过创建自定义角色来满足需求,先切换到root账号:

use admin

db.auth("root","wzh123") // root为已创建的具备超级用户角色的管理账号。

创建自定义角色:
db.createRole({
role: "wzhRole",
privileges: [{ resource: { db: "", collection: "" }, actions: ["enableSharding","dropDatabase" ] }],
roles: ["readWriteAnyDatabase"]
})

privileges字段指定了该角色具有的对resource字段所述资源具有actions字段所述的操作权限enableSharding和dropDatabase,同时通过roles字段继承了readWriteAnyDatabase的所有权限。

5、进一步操作myuser账号,先去掉其readWrite角色,操作如下:

db.revokeRolesFromUser(
    "myuser",
    [
      { role: "readWrite", db: "admin" }
    ]
)

确认权限已收回:

mongos> db.getUser("myuser")
{
"_id" : "admin.myuser",
"user" : "myuser",
"db" : "admin",
"roles" : [ ]
}

6、为myuser增加wzhRole角色:

db.grantRolesToUser(
    "myuser",
    [
      { role: "wzhRole", db: "admin" }
    ]
)

确认权限已经赋予:

db.getUser("myuser")
{
"_id" : "admin.myuser",
"user" : "myuser",
"db" : "admin",
"roles" : [
{
"role" : "wzhRole",
"db" : "admin"
}
]
}

7、再使用myuser登陆

use admin

db.auth("myuser","wzh123")

8、执行操作:

mongos> sh.enableSharding("wzhshard")
{ "ok" : 1 }
mongos> sh.shardCollection("wzhshard.table1",{mykey:1})
{ "collectionsharded" : "wzhshard.table1", "ok" : 1 }
mongos> use wzhshard
switched to db wzhshard
mongos> db.dropDatabase()
{ "dropped" : "wzhshard", "ok" : 1 }

一切看起来那么美好!

MongoDB在权限管理中引入了角色这一中间层,一般情况下,直接基于内建角色来创建账号即可,有特殊需求的话,可以创建自定义角色来满足需求,这样一来就无需暴露繁多的具体权限。对于新司机,更容易上手。但不足之处在于MongoDB数据库并未像MySQL一样未提供IP过滤功能(未提供Host字段用来设置账号所适用的主机IP列表)。

最后,网易数据库团队正在热火朝天地调研和开发MongoDB分片集群功能,计划上半年在蜂巢(云计算基础服务)上提供MongoDB分片集群能力,届时将带给大家更加强大的文档数据库能力。

网易云数据库RDS是一种稳定可靠、可弹性伸缩的在线关系型数据库服务,当前支持MySQL引擎,提供基础版,高可用版,金融版针对不同业务场景的高可用解决方案,同时提供多重安全防护措施,性能监控体系,专业的数据库备份、恢复及优化方案,使您能专注于应用开发和业务发展。

参考资料:

1、https://docs.mongodb.com/manual/reference/built-in-roles

2、https://docs.mongodb.com/manual/reference/privilege-actions/

3、https://docs.mongodb.com/manual/reference/resource-document/

4、https://docs.mongodb.com/manual/core/authorization/

5、https://docs.mongodb.com/manual/core/security-user-defined-roles/

6、https://docs.mongodb.com/manual/tutorial/manage-users-and-roles/

网易云免费体验馆,0成本体验20+款云产品!

更多网易技术、产品、运营经验分享请点击。

相关文章:
【推荐】 Android优化之内存优化倒计时篇
【推荐】 混合APP开发-hybrid 升级流程

MongoDB账号管理及实践的更多相关文章

  1. MongoDB基本管理命令

    MongoDB是一个NoSQL数据库系统:一个数据库可以包含多个集合(Collection),每个集合对应于关系数据库中的表:而每个集合中 可以存储一组由列标识的记录,列是可以自由定义的,非常灵活,由 ...

  2. MongoDB——权限管理

    MongoDB--权限管理 MongoDB默认是没有权限验证的,但生产环境中,没有权限控制是很不安全的. 我们先不详谈太多概念,直接动手创建两个典型的账号: 超级管理员,类似sql server的sa ...

  3. HUST高级软件工程--测试管理工具实践--Day4

    测试管理工具实践--Day4 今天完成任务情况: 小靳 今天,主要在前两天的基础上继续学习挖掘jira相关内容: 学会了如何创建项目,并且创建了issue 学会了创建一般账号,并且可以将任务分发给一般 ...

  4. HUST高级软件工程--测试管理工具实践--Day3

    测试管理工具实践--Day3 今天完成任务情况: 小靳 今天,大家参加考试,时间比较紧促.庆幸,自己的队伍比较给力,大家都没有拖后腿,深夜还在为自己的任务拼搏,很是激励人心 我今天的工作就是 学会了注 ...

  5. HUST高级软件工程--测试管理工具实践--Day1

    测试管理工具实践--Day1 今天完成任务情况: 课前组好队伍,建好微信群. 课上通过老师的介绍,初步了解各种测试工具的使用情况. 课后选取了组长,在微信群经过"广泛而激烈"的讨论 ...

  6. SNF快速开发平台2019-用户安全控制-权限管理模型实践-权限都在这里

    1.1    是否保存密码 勾选记住密码后,再次开启程序用户密码不需要再次输入,直接显示在密码输入框内,方便快捷. 图 4.1‑1 记住密码的登录页面框 1.2    是否自动登录 勾选自动登录后,再 ...

  7. MySQL基础知识:启动管理和账号管理

    整理.记录常用的MySQL基础知识:时间久了,很多就忘记了. 操作系统环境为MacOS Catalina, MySQL版本为: 8.0.13 MySQL Community Server - GPL. ...

  8. Android 6.0 权限管理最佳实践

    博客: Android 6.0 运行时权限管理最佳实践 github: https://github.com/yanzhenjie/AndPermission

  9. NoSQL学习二:MongoDB基本管理命令

    MongoDB命令学习  一.MongoDB命令帮助 在安装MongoDB后,启动服务器进程(mongod),可以通过在客户端命令mongo实现对MongoDB的管理和监控: 这是MongoDB最上层 ...

随机推荐

  1. OpenCL 图像卷积 1

    ▶ 书上的代码改进而成,从文件读入一张 256 阶灰度图,按照给定的卷积窗口计算卷积,并输出到文件中. ● 代码,使用 9 格的均值窗口,居然硬读写 .bmp 文件,算是了解一下该文件的具体格式,留作 ...

  2. spring错误处理 Build path is incomplete. Cannot find class file for org.springframework.aop.Advisor

    Build path is incomplete. Cannot find class file for org.springframework.aop.Advisor 初学spring,记录一下出现 ...

  3. WeakHashMap, NOT A CACHE

    Overview Base Map的实现 基于WeakReference的Entity实现 基于Reference和ReferenceQueue实现 它的弱引用是键,而不是值 它的key会被全自动回收 ...

  4. MyBatis 提供的内置类型别名

  5. 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

    目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...

  6. win bat命令后台运行控制台应用

    @echo off if "%1"=="h" goto begin start mshta vbscript:createobject()(window.clo ...

  7. Qt5 How to translate App UI languages

    Adding new language file name in app.pro file. TRANSLATIONS += lg_ch.ts \ lg_en.ts \ lg_new.ts Runni ...

  8. Common issue on financial information exchange (FIX) Connectivity[z]

    FIX Protocol Session Connectivity Hi guys, in this post I would like share my experience with financ ...

  9. Python爬虫利器六之PyQuery的用法

    前言 你是否觉得 XPath 的用法多少有点晦涩难记呢? 你是否觉得 BeautifulSoup 的语法多少有些悭吝难懂呢? 你是否甚至还在苦苦研究正则表达式却因为少些了一个点而抓狂呢? 你是否已经有 ...

  10. Ubuntu 17 Nginx 配置 laravel 运行环境

    1 安装 nginx #aptitude install nginx #apatitude install php7.1-fpm 2 在 /etc/nginx/sites-available 建立 s ...