zoukankan      html  css  js  c++  java
  • MongoDB账号管理及实践

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

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


    目前蜂巢(云计算基础服务)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 升级流程

  • 相关阅读:
    Data Base mysql备份与恢复
    java 乱码问题解决方案
    【知识强化】第二章 物理层 2.1 通信基础
    【知识强化】第二章 进程管理 2.2 处理机调度
    【知识强化】第二章 进程管理 2.1 进程与线程
    【知识强化】第一章 操作系统概述 1.3 操作系统的运行环境
    【知识强化】第一章 网络体系结构 1.1 数据结构的基本概念
    【知识强化】第一章 网络体系结构 1.2 计算机网络体系结构与参考模型
    【知识强化】第一章 网络体系结构 1.1 计算机网络概述
    【知识强化】第一章 操作系统概述 1.1 操作系统的基本概念
  • 原文地址:https://www.cnblogs.com/zyfd/p/9814787.html
Copyright © 2011-2022 走看看