云MongoDB网络安全策略和权限管理体系

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 阿里云MongoDB在市场上实际使用时,如何保障数据库安全性?又是如何防止数据库受到攻击?本文将带领你了解云数据库MongoDB云环境的网络安全策略和MongoDB自身的权限管理体系。
本次直播视频精彩回顾,戳这里!
直播涉及到的PPT,戳这里!

演讲嘉宾简介:
朱一聪(花名:一聪),2017年6月加入阿里云MongoDB组,目前主要参与阿里云MongoDB云数据库内核相关的开发。

以下内容根据演讲嘉宾视频分享以及PPT整理而成。

本次的分享主要分为以下三个部分:
一、阿里云网络安全策略
二、鉴权
三、Role-Based Access Control

回顾2017年,发生了一个比较著名的事件--MongoDB赎金事件,也暴露出MongoDB存在很大的安全问题。事件的截图如下图所示,可以看到,黑客非常嘲讽地在用户的数据库内留言并索要赎金。
2ceb0840f0350fb2fcf9d087cce0fd2cecc396e0

这个事件主要归责自然是行径恶劣的黑客,但实际上黑客攻击的手段并不高明,他们只是扫描了在互联网公网上能访问到的MongoDB,并且仅仅扫描了MongoDB默认的端口—27017,然后就直接连进了目标MongoDB。同时他们发现这并不是个例,有很多MongoDB都可以通过这种方式连上。

从客观上来说,用户和社区自己也负有一定责任:首先,把一个数据库直接开放到公网上是非常不安全的,这就相当于打开家门让大家进来;其次,还使用着默认的端口;最要命的是还没有开启鉴权。MongoDB官方默认不开启鉴权的设定确实不太合理,但它也有一些历史的原因的考虑。用户在自己使用的时候,建议是一定要开启鉴权。

一、阿里云网络安全策略
对于阿里云的MongoDB的用户来说,不存在上述的这些问题:首先,阿里云的MongoDB就是默认开启鉴权的。其次,阿里云的MongoDB本身在阿里云的网络上会带有以下安全的措施:
f61f296b94d10f655a4917aa05b0ab5d0d56dabd

1、默认公网无法访问。就算有人申请了可公网访问的ip,它也有白名单机制的保护,即它只接受你指定过的来自于ECS的访问。
2、阿里云现在大部分产品是支持VPC的,这就代表即使是在阿里云内网跟其他网络是隔离的,用户处于自己的专有虚拟网络下。 所以在网络上阿里云的MongoDB是相对比较安全的。

云MongoDB的一些安全措施主要包含四个方面:
1、鉴权[Authentication]
2、授权[Authorization]
3、审计日志
4、TLS/SSL
99b03f5a4c574c9dcf9eb62d7753f5ab5ce23124

审计日志其实是云MongoDB才提供的一个功能。对于MongoDB来说,它的社区版是不提供这个功能的,只有企业版才提供这个功能。从安全性来讲,这个功能的好处在于,万一真的有人恶意的操作了数据库,例如黑客通过一些间接手段直接把用户的用户名、密码给盗取了,那黑客的异常操作和访问是会有记录的,这就相当于他犯罪留下了证据,让用户日后也有迹可查。

TLS/SSL的是指在连接数据库的时候不是使用明文而是进行加密处理。这个能力MongoDB社区版是支持的,企业版在这个方面更强,云MongoDB由于一些原因暂时还没有开放,但未来也可能支持这个功能。

另外两块是鉴权和授权。它们的英文单词在拼写上非常接近,但实际上却是两个完全不同的意思。通俗一点来说,鉴权可以认为是识别[你的客户端]。在MongoDB中鉴权是以user为单位的,鉴权的真正含义是指鉴定这个user有没有资格、或者说认不认可这个user来连上服务器。而授权的含义是指定义这个user用户可以在服务器上做哪些动作。

二、鉴权
MongoDB的鉴权主要分为两种类型,一种是外部鉴权,就是用户以客户端访问mongodb时的鉴权。还有一种是内部鉴权,是指replSet的节点之间的相互鉴权和sharding模式下,mongos和shard节点之间鉴权。对于云MongoDB来说,它的外部鉴权和内部鉴权都是默认开启的。
53c73b5de7f2432bf9b19fd952a6ff7d0d8ca68a

鉴权方式也主要有两种。一种是在连接客户端的时候,添加一个参数用于开启鉴权,把用户名、密码代入进去。另一种是在连接上之后,调用db.auth()方法进行鉴权。

在云MongoDB上两种都支持,用法也十分简单。有一点需要注意的是鉴权这个行为是对于一个db的某个用户而言的,所以大家一定要注意db和user的匹配关系。在现实案例中,很多用户之所以无法访问数据库,往往是因为用户的用户名和用户指定的数据库不匹配导致的。比如下图中MongoDB默认给用户的超级权限用户root,其对应的数据库是admin,只有两者匹配才能成功访问,这个需要大家注意一下。
67361827c5e3c7d7f415fc68ef92f605b565745d

接下来看看MongoDB的鉴权策略,前面提到过,MongoDB是支持多种鉴权方式的,目前推荐的一种方式是SCRAM-SHA-1,并且在云MongoDB上也是采用的这种方式。以往一种可行的方式是直接把用户名、密码(无论是明文还是加密过的hash值)放在客户端进行比较,如果跟客户端保存的那个密码一致,即认为检验通过。相对于这种方法,SCRAM-SHA-1的方式更加先进。
477f7ea2e874de4da76a70543048d3b1ef1a235c

SCRAM-SHA-1是一个双向鉴定机制,不仅客户端在访问服务端的时候,服务端要鉴定客户端是否有资格进行连接,而且客户端本身也要鉴定所连接的服务端是不是正确的。相对于单单只是建立客户端的鉴权,这样的双向鉴权话就比较安全。如果不使用双向鉴权,客户端连上了一个不该连上的Server进行操作,并且Server记录了客户端的操作,会形成带有风险性的行为。

这种鉴权方式的实现比较简单。与传统的方式一样,Server端需要保留一些内容,但它不像传统的方式把密码给保存下来,而是针对密码做一次加盐哈希,即加一个salt和iteration-count做一个哈希得到password[s],然后通过password[s]得到两个key,一个是key[c],另一个是key[s],它们是password[s]直接通过HMAC和”Client Key”和”Server Key”进行哈希得到的,服务端只保存了用户名、H(key[c])、 key[s]、 salt和iteration-count,没有保存真正的password,甚至它没有保留key[c],这也是出于安全考虑。
5e8dc8792bbc094dd0eca011d080d9f197b7f03b

SCRAM-SHA-1的具体流程是这样的:
1、客户端先发送用户名和一个client-nonce(即客户端生成的随机数)。
2、然后服务端返回salt和iteration-count,并生成一个server-nonce,与client-nonce做一个异或返回给客户端。
3、客户端根据这些信息进行计算得到Auth。Auth就是根据服务端返回的结果算出来的,这时候关键操作是它需要证明自己是客户端,具体的和服务端的准备工作一样根据password计算得到key[c],然后key[c]跟Auth使用HMAC再做一次hash,最后再跟key[c]做一次异或,得到_proof[c],粗略来说就是根据password和步骤2中服务端返回的信息计算得到proof[c]。
4、客户端返回proof[c]和client-nonce|server-nonce。
5、服务端对_proof[c]是否合法进行验证,粗略来说就是通过一些计算将_proof[c]还原出key[c],然后校检H(key[c])和本地保存的值,如果它们一样,则客户端鉴权成功。
6、由于是双向鉴权,服务端也要进行鉴权,它使用步骤3的方法计算出_proof[s]并返回给客户端。
7、客户端也用和服务端校检类似的方式对_proof[s]进行验证。
92c7279b7f0ba113474568668038790fee5d9917

可以看到,整个鉴权流程还是比较冗长,而每次建立一个新的连接都要走一次这样的流程。而且在服务端鉴权的时候,需要生成随机数做一些计算,这些计算本身耗费的cpu不是太大,但MongoDB实现里面随机数是通过系统调用去取的(通过访问Linux的dev/urandom来获取随机数),系统调用的开销就不小了;此外为了使得系统调用取到的随机数不重复,这个系统调用还处在一个spinlock的保护下。这样当用户使用大量并发的短链接去连接的时候,所有链接都要做并发的鉴权,而鉴权会去进行系统调用,系统调用还加锁,性能上就会产生问题。所以在短链接的情况下,社区版MongoDB的性能并不好,而瓶颈就在于鉴权环节上。这个问题可以通过改用长连接来解决,实际上MongoDB官方也是推荐大家使用长链接的,因为长链接相对于短链接来说省去了反复链接和鉴权的开销,然而对于某些高级语言(比如PHP)来说,它没有办法只能够使用短链接,或者总有一些场景短连接更适合。而对于云MongoDB来说,短链接是可以放心食用的,因为云MongoDB的内核做了一个优化,它不再通过系统调用去获取Linux的默认的随机数,而是做了一个用户态随机数,这样就把鉴权的瓶颈给取消掉了,所以短链接的性能也非常好。这个问题在云MongoDB也就不存在了。

三、Role-Based Access Control
MongoDB的权限管理,顾名思义,是根据role这个角色来管理的。意思是说,在db下面创建了一个user(创建user需要指定一个db,实际上是通过db.createUser()这个方法创建,这个时候的user即为当前db下创建的),一个user有多个role,一个role又定义了多组权限(权限是指有权对一个resource做某个action操作),因此用户就可以通过组合多个role的方式来得到多种权限的组合,MongoDB还支持role的继承,总的来说role-based access control的是一种非常灵活、强大的方式。
1ce92d5847990fa49b77ad09bf2177b267e3079a

首先讲解一些基本概念,位于最底部的Privileges层涉及到两个概念:Resource和Action。Resource其实就是指一组资源,具体分为三种:collection resource、database resource和cluster resource。如下图中的{ db:”products”, collection:”inventory” }是指数据库products下的名为inventory集合的资源。当然resource也可以不用这么细致,也可以把一个database当成一个resource,即如下图中的{ db:”test”, collection:”” }把collection处置为空,表示对于所有的collection都有权限。还有一种cluster resource,如下图中的{ resource:{ cluster:true }  actions:{ “shut down” } }表示当前role拥有向集群发送shut down的action的权限。

Action其实也是一个封装过的概念,对于MongoDB来说,它的命令的基本单位是command,比如在shell上无论我们使用db.runCommand()的方式还是直接调用db.insert()这样的方法,最终在server端转都是赚化为command来执行。Action其实是一类相似的command的组合,比如以insert这个action为例,它其实是代表了insert和create这两个command,所以如果对一个db有insert的权限(这个insert是action),或者说一个insert权限的source是某个db,这就意味着用户拥有对数据库insert和create这两个command的权限。
8a2093d0094a32c5f1aff27931269e911854f84d

MongoDB的role是支持用户自定义的,功能非常强大。可以通过createRole()方法指定任意的role,如下图中的例子:
f80a1d2bf92fad20b18661cbe1c0592a254dec59

自定义一个role,实际上就是定义一组权限。可以看到上图中有一个字段privileges,它是一个数组,里面包含着若干自定义的权限,每个权限内又具体细分为resource和actions两部分。下方还有一个字段roles,它也是一个数组,里面包含了一个名为read的role,意思是自定义的role继承了名为read的role,这里的继承和面向对象中的继承非常类似,即表示当前名为myClusterwideAdmin的role继承了名为read的role的所有权限。

自定义的方式功能上非常强大的,用户几乎可以根据自己的喜好定义任意一种role,即对任何资源的任意操作的任意组合。但是有的时候,用户不想麻烦地自己进行定义,因此MongoDB也提供了一些内置的role。这样用户就可以通过组合这些内置的role或者直接使用这些内置的role达到自己权限管理的目的。

如下图所示,这些内置的role也分为好几类,比如Database User Roles和Database Administration Roles。大家都知道在MongoDB里面数据库分为两种,一种是Admin数据库,这个数据库是在MongoDB Server启动时就存在的,无需自己创建。还有一种是用户在使用时,自己创建的数据库。特别值得注意的是内置role中有一类Superuser Roles,它实质上就是root,即用户拥有对所有资源的所有权限,在理论上这类用户可以干任何他想干的事情。
8f53afae3737b1a041cca87819564614ab7967a4

在MongoDB中,user是在database下创建的,在鉴权的时候也需要指定当前user属于哪个database。虽然user是在database下创建的,但是它的权限可以跨越它所属的database。如下图创建user的例子:这里使用的是products这个database,但是我们在给这个user指定roles的时候,指定的两个role的权限都是作用在数据库admin下,这种写法在MongoDB里面是允许的,这样写也比较灵活。实际上可以在创建一个用户的时候给它指定任意的role,也就是说可以把对其它数据库的权限通过role赋予给它。
b9e46cc76de6f4ad776c482b82bc640394a77242

MongoDB还提供了一组管理接口,可以让用户可以很方便地管理user、管理role,之前介绍的最简单、最基础的两个db.createUser()和db.createRole()方法就在这组接口中。除此之外,如果想创建完一个用户之后更改这个用户的role,即通过更改用户的role来更改用户的权限,那么可以调用db.updateUser()的方法来进行重置;如果想进行查看的话,也可以调用db.revokeRolesFromUser()。这里就不进行一一介绍了。对于用户的一些修改操作和对权限的一些操作,它都封装了相应的方法以方便用户。
09056d042f3c759a748c71f1e9830c06c05ee9bf

我们知道在MongoDB的数据库里,数据包含三个基础概念:database、collection和document。在进行权限管理的时候,相关数据的存储其实跟普通数据的存储没有什么差别,MongoDB几乎把它所有的信息数据,包括它内部的信息、用户自定义或自己插入的一些数据,都是以document的模式放在某个db的collection里面,只不过像role、user这些信息,它是放在admin数据库下,即便role和user是创建在非admin数据库区,它们的信息也是统一集中存储在admin这个数据库下admin.system.role或admin.system.user这两个collection里面。从下图的储存实例中可以看到,system.role这个collection下存放的一个document展开项跟使用createRole()这个function时传入的document一模一样,其实在使用createRole()时,系统就是往system.role的collection里面直接插入一个document,所以才会导致它们内容一模一样。
655029ce5f229cc34494f2fd4e66819e72088e19

User信息的存储也是类似的,在使用createUser()时,系统也是往system.user的collection里面直接插入了一个document。
2e520fae6355213b24d522d848989eefb5a6d136

虽然从原理上,大家可以发现,直接对system.role和system.user两个collection进行curd操作也可以进行权限管理,但是强烈不推荐这么做,强烈推荐使用上面介绍的像createUser()这样的权限管理的接口。因为mongodb的document事物schema的,是自由的,可以是任意的格式,这是它的特色,那么好了假如system.role插入了一个奇怪的文档怎么办,如果修改某个role的document的时候字段由于失误写错了怎么办。Curd操作是不会对这些做校检的,但是调用接口就会。使用mongodb提供的接口管理权限更方便也更不容易出错。
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
15天前
|
存储 NoSQL MongoDB
掌握MongoDB索引优化策略:提升查询效率的关键
在数据库性能调优中,索引是提升查询效率的利器。本文将带你深入了解MongoDB索引的内部工作原理,探讨索引对查询性能的影响,并通过实际案例指导如何针对不同的查询模式建立有效的索引。不仅将涵盖单一字段索引,还会探讨复合索引的使用,以及如何通过分析查询模式和执行计划来优化索引,最终实现查询性能的最大化。
|
17天前
|
存储 安全 网络安全
云计算与网络安全:技术挑战与应对策略
【10月更文挑战第8天】随着云计算技术的飞速发展,越来越多的企业和个人开始将数据和应用迁移到云端。然而,这也带来了一系列网络安全问题。本文将探讨云计算环境下的网络安全挑战,并提出相应的应对策略。我们将从云服务模型、网络安全威胁、信息安全技术等方面进行分析,并通过代码示例展示如何实现安全措施。
|
2天前
|
SQL 安全 算法
网络安全漏洞与加密技术:保护信息安全的关键策略
【10月更文挑战第23天】在数字化时代,网络安全漏洞和信息安全问题日益突出。本文将探讨网络安全漏洞的概念、类型以及它们对信息系统的潜在威胁,并介绍加密技术如何成为防御这些安全威胁的有力工具。同时,强调安全意识的重要性,并提出加强网络安全教育和培训的建议。最后,通过一个代码示例,展示如何在网络应用中实现基本的加密措施,以增强读者对网络安全实践的认识。
|
5天前
|
机器学习/深度学习 计算机视觉 网络架构
【YOLO11改进 - C3k2融合】C3k2融合YOLO-MS的MSBlock : 分层特征融合策略,轻量化网络结构
【YOLO11改进 - C3k2融合】C3k2融合YOLO-MS的MSBlock : 分层特征融合策略,轻量化网络结构
|
10天前
|
供应链 安全 网络安全
云计算时代的网络安全挑战与策略
【10月更文挑战第15天】随着云计算技术的飞速发展,企业和个人用户越来越依赖云服务来存储和处理数据。然而,这种便利性也带来了新的网络安全风险。本文将探讨云计算环境中的网络安全挑战,并提出相应的防御策略,以保护数据不受威胁。
26 4
|
12天前
|
存储 监控 安全
如何实施有效的网络安全策略?
【10月更文挑战第13天】如何实施有效的网络安全策略?
46 5
|
11天前
|
运维 监控 安全
连锁药店网络优化策略:一站式融合方案提升竞争力
在数字化浪潮下,线上药店通过技术创新和线上线下融合,正重塑购药体验,提供24小时服务和医保结算便利。面对激烈竞争,连锁药店和中小药店纷纷通过优化网络架构、提升服务质量和加强合规管理来增强竞争力,实现高效、安全的数字化转型。
|
16天前
|
算法 计算机视觉 Python
YOLOv8优改系列二:YOLOv8融合ATSS标签分配策略,实现网络快速涨点
本文介绍了如何将ATSS标签分配策略融合到YOLOv8中,以提升目标检测网络的性能。通过修改损失文件、创建ATSS模块文件和调整训练代码,实现了网络的快速涨点。ATSS通过自动选择正负样本,避免了人工设定阈值,提高了模型效率。文章还提供了遇到问题的解决方案,如模块载入和环境配置问题。
54 0
YOLOv8优改系列二:YOLOv8融合ATSS标签分配策略,实现网络快速涨点
|
17天前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
31 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
12天前
|
人工智能 自然语言处理 NoSQL