2018-08-06 数据权限管理

https://blog.csdn.net/colorant/article/details/78672404

大数据平台的权限管理工作,听起来不就是用户和密码管理这点事么?找个数据库存储一下两者的映射关系,然后再找个地方记录一下每个人可以做什么事,最后在需要的时候验证一下就好了,如果不讨论各种加解密原理和算法,那这个话题有什么值得一谈的么?

实际上,如果真正接触过这方面的工作内容,你很快就会发现,不论是在技术层面还是在产品层面,大数据平台环境下的权限管理工作都是一个让人伤脑筋的烫手山芋,它不仅仅是一个技术问题,还是一个业务问题,甚至还可能是一个人际沟通和权衡利益得失的哲学问题。。。

所以,以下内容分两部分展开,先谈哲学问题,再谈技术问题。

权限管理的目标是什么?

讨论问题之前,先讨论目标,为什么要做权限管理,要做到什么程度?

如果要让你的用户来回答这个问题,他们多半会说,那还不就是没事找事,给老子添堵呗?

从技术的角度来说,用户说的也没错,权限管理过程的本质,就是通过某些技术手段来限制用户的可能行为,其结果就是用户不能为所欲为 ;)

[图片上传失败...(image-6e8339-1533567574436)]

客观逻辑上虽然如此,但主观思想上,如果你仅仅以这个为出发点来思考问题的话,我相信你早晚是要被人民群众的汪洋大海所吞没的 ;)毕竟,限制用户的行为,只是权限管理的手段而不是目的。那么目的是什么?个人以为,可以从以下三个角度来讨论:

  • 适度安全,降低人为风险

  • 隔离环境,提高工作效率

  • 权责明晰,规范业务流程

以下分别阐述一下

适度安全,降低人为风险

最直观的目的就是安全,但是,安全这个目标,如果从Security的角度来说,从来都没有终点,做到什么程度才算安全?这显然和你的业务环境有关,如果事关国家最高安全机密,比如核弹发射什么的,当然怎么做都不过分。

[图片上传失败...(image-241bb8-1533567574436)]

但多数情况下,对于多数公司的业务环境来说,现实中最大的问题可能并不是数据信息的泄漏,因为其实你并没有那么多要命的机密数据需要保护,即使有一些用户隐私,金融方面的信息需要保护,通常也只是你的所有数据中的一个小小子集。更何况,真的要防止蓄意的窃密行为,通常也不是简单的通过权限映射管理就能解决问题的。

那么除了信息安全,还有什么目的和安全这个字眼相关呢?对,那就是防止误操作!事实上,误操作的可能性和导致的伤害可能远大于信息泄漏带来的问题,好比每年死于车祸的人远大于死于谋杀,枪击,战争等恶劣事件的人。从删库到跑路问题可能才是日常工作中最有可能烦扰你的问题。

[图片上传失败...(image-5f04c9-1533567574436)]

所以,在实际工作中,从防止信息泄漏这个角度来看,你往往可能只需要做到最低限度的保障就可以了,换句话说,就是防君子不防小人。这当然不是说防小人不重要,而是说,防止蓄意的破坏,有时候代价太高,你需要评估投入产出比是否匹配。

但只防君子绝对不代表权限管理的方案就可以做得很简单。事实上,防止误操作这一目标,尽管从字面上看起来并不没有多么高大上,相比于信息泄漏这个字眼,也更容易被忽视,但实际实现起来却可能更加复杂,更加困难

因为它不仅仅是简单的授权方案方面的技术问题,实际上收紧权限和防止误操作这两者并不等同,要降低人为的安全风险,通常还涉及到系统中权限点的设计,业务流程的容错纠错能力,操作流程的规范性等等,所以通常需要结合业务知识,在权限管理体系乃至业务系统交互和流程的设计过程进行针对性的设计。

隔离环境,提高工作效率

所谓隔离,从用户的角度来说,就是将业务进行分拆,比如在数据平台整体大环境中,制造出一个只和当前用户的自身业务相关的小环境。

这么做的目的也很简单,一方面在一定程度上,能起到防止误操作的作用,你看不到别人的业务,自然也就无法操作别人的业务。此外,因为减少了误操作非相关业务的可能性,用户的胆量和自主维护的意愿也能得到提升。

另一方面,将用户的业务环境进行隔离以后,能让用户在使用平台的过程中,最大程度的减少不必要的信息干扰,降低学习成本,提高工作效率。

举个简单的例子,你可以将开发平台上的所有作业任务都展示给用户,然后提供搜索过滤功能或者层级的目录树让用户找到自己的任务。如果用户对某个任务没有权限,那么就无法打开或执行。但是,相比而言如果用户只能看到自己的作业任务,那么上述操作可能都可以省略,他所需要观察和处理的信息也会更加简洁,需要做的选择和判断也更少,工作效率自然会得到提升。

要做到这点,前提条件自然是做好业务的权限映射管理工作。你可能会说,这也很简单,就按照任务owner的关系进行隔离,大家只能看到自己开发的作业和数据不就好了么?也不竟然,在实际的业务环境中,哪些是与用户相关的作业或数据有时候很难绝对定义。

比如你作为个人,会有自己开发和负责的业务,但是你也往往希望一个团队内部的成员能共同负责部分业务,或者团队的Leader能管理团队内部所有成员的业务。又或者你作为一个业务的上下游利益相关方,你希望能够订阅相关业务的数据,作为系统管理员,你希望能够在必要的时候对任何作业或数据都能进行干预。同一个用户在不同的场景中可能承担不同的角色,或者同时拥有这些角色中的多个。总之,与用户相关的小环境,往往并不那么容易清晰的定义。

所以,要做到必要且充分的业务隔离,还要能够灵活的满足各种业务关联模型,就要求权限的映射模型足够灵活。而光有权限模型也是不够的,系统UI的交互设计也必须结合业务场景进行合理规划,但总体的原则,不外乎就是尽量遵循Need to Know原则,不要给用户过多不必要的信息,进而突出重点,提高效率,降低系统的学习和使用成本。

权责明晰,规范业务流程

权限管理,从一个角度看是禁止用户做不该做的事,但从另一个角度看是授予用户能做某件事的权利。如果你认为这是一个权力,那么伴随着权力的授予,我们当然希望同时做到责任的明晰。平台的权限管理如果只能靠系统管理员来承担,当规模小,业务环境简单的时候问题不大,当系统和业务都变得复杂的时候,就很难维系了。

所以,权限管理的理想的模式是,能够将权力和责任同时下放到相关的责任团队中去,实现业务的自治管理。一方面是为了降低平台的日常管理代价,另一方面,更重要的是通过授权,明确责任人,让每个任务,每个数据都有明确的业务和团队归属。

反过来说,也只有责任明晰了,才能敦促每个相关负责同学,认真的思考和对待手中的权力,充分发挥自身的主观能动性,合理规划业务的归属关系,权限的管理也才有可能做到能收能放,而不至流于形式或者成为妨害工作效率的拦路虎。

小结

权限管理的目标,绝对不是简单的在技术层面建立起用户,密码和权限点的映射关系这么简单的事,更重要的是要从流程合理性,业务隔离,实施代价,可执行性等方面进行考虑。单方面强调安全,结果往往并不理想。

[图片上传失败...(image-c8935a-1533567574436)]

重要的通过适度的安全管理手段,降低业务误操作的风险,结合业务流程和系统交互设计,实现业务的合理分隔,提高工作效率,同时将权限管理工作分级授权下放到业务负责人和团队,实现业务自治管理,明晰责任归属,让权限管理充分发挥其促进业务健康安全发展的作用,而不是相反。

所以在实现过程中,要争取在可接受的安全范围内,保持相对较低的开发,管理和维护代价,做到真正有效的实施,否则再完美的系统也会因为人的因素而大打折扣。举个例子,比如美国的核弹发射密码箱,一天24小时由将军以上级别的专人随身携带看管,安全措施可谓严格了吧,但据坊间谣言传闻,由于害怕复杂的密码总统记不住,核弹发射安全箱的密码一度是8个0...

安全与便利的矛盾,有解么?

谈完目标谈问题,如果你不幸做过相关工作,你应该会有体会,在权限管控方案的实施过程中,最棘手的问题绝对不是单纯的技术问题,而是在当前技术条件水平下,安全与便利,代价与风险,平台与用户,全体与个体,乃至诉求不同的个体相互之间的利益平衡问题。

天生矛盾

通常来说既然是安全管控,那么显然得依靠一定的约束条件和规范来实现,那么客观上必然给用户带来某种不便利性。虽然在实现的过程中,可能可以通过各种方式去自动化或者智能化,但毫无疑问,在同等技术条件水平下,越安全通常也就意味着越不方便,安全与便利,两者天生就是矛盾的。

而风险,在落到自己身上之前,通常很少有人会真的给予足够的重视,好比明知道得肺癌的概率很高,也很难下定决心戒烟一样,更何况有时候得到便利和承受风险的对象还有可能是不同的人群。好比丢个香蕉皮,放倒的是过马路的老奶奶,排放污水,遭殃的是下游吃瓜群众。。。

因此,不用怀疑,绝大多数情况下,你的用户一定不会赞美你在权限管控方面所做的工作。因为客观上,用户的唯一感受就是,你在没事找事,给他添麻烦了。万一你还需要他们配合完成改造,那简直就是作死,如果他们没有过来PK你,只是冷嘲热讽几句,就已经是万幸了,想要用户真心积极配合?没有的事。

再退一步说,你的用户也有可能是一个理智的用户,他可能认同安全的重要性,但是在代价方面的看法上,也往往可能会与你相左。用户很可能希望又安全,又便利,对他还没有代价,如果有,最好是由实施方来承担代价,简单来说,就是安全我认同,但别给我来事。

这其实也是人之常情,但在评估具体的方案和代价收益的时候,就必然影响各方的认知和判断。

那这种苦差事,该怎么办???说实话,我也没有太好的实践,不论如何换位思考,大家的关注点天生就不一致,所以,矛盾一定会有,只是因时因事,程度轻重不同而已。我要说,横眉冷对千夫指,俯首甘为孺子牛,你会不会很绝望 ;)

好吧,虽然如此,还是要想想变通的办法的,以下姑且让我畅想一下可能的做法

改变角度,转移目标

既然天生矛盾,那么,能否转移矛盾?有时候,瞒天过海或许是一个可行的方案。怎么解释呢?如前所说,开发平台安全管控目标的达成,各种权限的约束和限制固然是必要的,但同时,流程的规范,产品交互设计的改进和业务的合理规划在达成这个目标的过程中其实也是同等重要的,而这些工作,不光有助于提升安全性,往往也有助于改进和提升用户在平台上的产品体验和工作效率。

所以,如果有可能,就不要让用户在安全性和便利性这两者之间进行PK,而是尽可能在提升安全的同时,为用户创造一些他们更加关心的附加收益,让用户在这些他们关心的收益和安全手段带来的麻烦之间进行PK。如果这些收益大于便利性上的损失,那么相信你的工作也就能推进得更加顺利一些。说直白一点就是,如果有可能,换个角度驱动这件事的开展。

[图片上传失败...(image-70c3cd-1533567574436)]

举个简单的例子,如果你要加强数据的权限管控,要求用户必须遵守特定的用户名规范,登记IP地址并且申请对应的表权限才能读写数据,那么或许你可以通过为他提供配置化的建表工具,查询工具,并提供相关数据的负载,血缘,流量监控等服务。将对用户的安全约束条件转变成,为了能够使用对应的服务,用户所必须提供的基础信息,这样依赖,大概用户配合的意愿度就会有很大的提升。

把握尺度

多数情况下,你和用户的矛盾不是安全管控这件事要不要做,而是做到什么程度,也就是尺度的把握。但尺度的把握是个哲学问题,什么样的尺度才是合理的,现实中,你很难找到一个可以绝对客观衡量的标准。

如果是大是大非的问题,各方只要理智一些,就不难达成一致,但难就难在有些场景下,大家角色不同,诉求和感受都不一致,可以说评估用的尺子都不是同一把,那么又以谁的尺子为准来衡量呢?

有没有办法做到尽量客观?

[图片上传失败...(image-bf5d6c-1533567574436)]

尽管没有绝对客观的衡量标准,但我们还是可以从权限管控方案可预见的执行效果(或者不执行的风险)方面进行一定的评估。大是大非的情况就不讨论了,模糊的情况下,或许可以从以下几个方面来考虑相关权限管控方案的制定是否合理,是否必要,是否可以改进。

1\. 相关权限管控与否,是否对他人的工作有影响,是否会让用户之间可能存在潜在的冲突?

这一条是通常是在资源共享或者系统,平台,服务共享的场景下要考虑的基础判定标准。有权力就要承担责任,自己方便的同时,要考虑是否对它人可能造成影响。如果权限不加管控,有很大的可能出现上述问题或者一旦出现风险很高,那就需要考虑进行约束,当然,如前所述,更理想的方式是通过隔离手段,在产品形态上就能规避这类风险问题,但这并不是所有的场景都能做到的。

2\. 加上相关权限管控后,大部分同学是不申请权限了(并且似乎也没有多少人抱怨),还是依然会申请权限(且抱怨)?

这条是用来判断相关的权限管控带来的不便利性,到底是在管控不必要的伪需求,还是仅仅是给刚需带来了附加的成本。

3\. 是否几乎全部的权限申请最终都会通过?

如果相关权限申请一百次99次全都通过的,那么基本有三种可能:一是审批者无法判断相关申请是否合理,二是相关申请其实在审批者看来无关痛痒(通常意味着即使错误的漏过了也没多大危害),最后也有可能大家的申请真的都是合理的

那么怎么判断是否第三种情况呢?我觉得,可以从申请的数量上来判断,如果是很罕见的申请,比如十天半个月才有人申请一次的,那么的确有可能是第三种情况。如果是一天发生十几次几十次的申请,那么很有可能是前两种情况。

4\. 相关权限管控措施,是否只是有利于安全?

这条怎么说呢,就是权限管控的收益,除了实施者心中认为的安全因素以外,是否还有其它收益。如果没有,而安全这部分收益大家又不见得意见一致,那么它的权重可能是要打点折扣的。

大致可以上述几个方面来判断当前方案合理性。如果上面4条都不满足,那么很大几率不是安全的尺度把得过严,应该放宽;就是实际实施的方案姿势有问题,应该变革。如果只是其中一两条不太理想,那么可能我们整体做得还可以,但在具体的实施手段或者规则制度,流程优化,规范宣导方面还存在改进的空间。

可能的变通措施

客观,嘴上说容易,实际操作起来,却很难。不是因为你不想客观,而是因为事情是复杂的,正反面因素往往同时都有,你可能坚持其中一面,而忽视另外一面。

那怎么办?虽说世上无难事,只要肯坚持,但一条路走到黑,相互PK到底,有时也并不是最聪明的做法。毕竟我们最终关心的只是风险能否控制,而非采用何种方式控制风险。或许换个方式,大家更容易达成一致。

事前审批 V.S. 事后审计

所谓的事前审批,就是你不申请权限我就不让你通过,做任何事情都必须走流程。而所谓的事后审计,就是你先做,我之后加以检查你的使用是否合理合规。

你可能会说,权限管理和审计是两码事了,后者的前提是你已经有权限了,然后再审查权限是否使用恰当。把事情简单化的确如此,但实际具体系统实施过程中,你是主要依托审计还是主要依托审批,可能会将影响到你的权限模型的规划和最终方案的实现。

比如,如果你的某个服务,相关权限在业务流程中具备分级授权管理的可能,那么你就可以考虑将部分操作权限下放给业务组负责人,如果是业务负责人在业务组范围内进行的权限相关改动,就可以考虑不走审批流程直接生效,那么,整个系统的权限点的设计和业务流程都有可能因此而采用不同的方案。

这么做的风险,是有时候业务和权限的从属关系并没有那么明晰(还没做到或者压更就做不到),如果跳过审批流程,就需要对应的业务负责人能够正确评估自己的行为,因此就可能存在少部分业务组负责人不负责任瞎授权,或者授权范围大于实际负责范围的情况。

但如果你的业务场景并不是生死悠关,需要万无一失,那么这些风险在短期内或小范围内,或许也是可以接受的。要保证这一风险控制的前提条件,就要求你能够在事后进行审计,及时的修正错误的行为。换句话说,就是舍弃绝对的安全,用审计来保障可控的风险,换取便利性和工作效率的提升

最后,事情如果可以做到如此理想,为什么有时候我们不这么做?

一来,因为有时候事前审批的系统实现起来往往更加简单,因为不需要分场景考虑实现方案了嘛,一刀切就好,技术成本比较低。

二来,是因为这么做的前提条件是你需要合理规划业务和权限模型,并为每个业务找到负责人/代理人,确认有人能对最终的结果负起责任,否则放出去的权限就收不回来了。但有时候,你很可能做不到这点,或者要做到这点需要投入巨大的精力

如何尽量少给用户大爷们添堵

如果没法变通,那只好低调做人,少惹麻烦。

排除权限管控方案改造过程中需要上下游业务方配合改造的工作不说,存粹从最终系统完成后,用户使用的角度来说,常见的用户问题包括:

  • 不知道有什么权限可申请?在哪申请?找谁申请?

  • 权限审批流程,响应慢,没人管,不知道进度

  • 总感觉流程复杂,没必要,影响开发效率

上述问题,本质上不太可能完全彻底解决,因为就算方案本身没有问题,这里面还涉及到许多人的因素,而人的因素其实你很难完全掌控。不论是立场问题,角度问题,还是信息不对称问题,很多时候都是要多方共同努力来改进的。

但是,从平台方案设计实施的角度来说,做好一些工作还是有希望能减少用户在上述问题方面的抱怨的,下面就来讨论一下。

我是谁?我在哪?我该怎么办?让用户知道何去何从

[图片上传失败...(image-740501-1533567574436)]

各种后台服务的权限管控方案中,很常见的一类产品设计问题,就是对新用户不够友好,没有任何引导性的内容,如果没有权限,相关功能对用户就完全不可见了,新用户上来面对的是一个完全空白的系统,连有哪些权限可以申请都不知道,更别提找谁申请了。遗憾的是,这类系统的设计者往往还对自己能管的严特别自豪。。。

举个简单的例子,比如一个报表系统,你显然应该通过权限管控,让用户无法看到敏感报表的数据。但是我经常看到在一些类似系统的设计中,用户上来连报表列表都没法查看,给用户哪些报表权限,完全由管理员来配置,用户在这个过程中,能做什么?只能完全靠问啊,有什么报表靠问,报表内容是什么靠问,找谁开通权限靠问,什么时候开通权限靠问。。。

这种管控方案未必完全不可行,如果你处在一个中央集权的业务环境中,这么做天然就是正确的。但是多数情况下,这种方案的效率堪忧,不管是对用户还是对管理员。而且即使以安全为理由,这种简单的有和没有的一刀切方案,本质上也是技术和产品方面懒惰的表现。

更合理的做法,或许应该是通过构建报表的元数据信息管理,将这些非敏感信息透明化,区别对待。即使没有权限,用户也应该能获取到相关报表的基本信息。比如能够查询到完整的报表列表,能够查看报表的业务描述,字段信息,负责人,变更记录,订阅情况,业务归属关系等等,并且能够直接在系统上对相关报表主动发起权限申请。

总之,就是在各种服务产品的设计过程中,要尽可能让用户能够获取足够的信息,去驱动下一步的动作,不光考虑有权限可以做什么事,更要考虑没有权限可以做什么事。而当用户因为权限问题遇到障碍时,也要引导和提示他下一步去哪里申请,而不是简单的阻断操作了事。

相比一刀切的方案,这么做无疑要花费更大的开发代价,产品形态上各种权限的划分也需要考虑得更加细致,但从改善用户体验,降低沟通成本,减少维护代价的角度来说,通常都是值得的。

能否降低权限申请烦躁指数?

对于申请了权限,急着用,但是没人批,不知道进度如何了等等问题。从过程的角度来说,我们可以采用各种方式来改善过程的体验,比如通过各种方式提醒审批人(消息,短信,工单等等),设置代理人,反馈审批进度,诸如此类。

那么这些工作的实际收益如何呢? 从审批人的角度来看,各种提醒,代理能一定程度上加快响应速度,但也有个限度,过度提醒对审批人的工作效率也会造成影响。从申请人的角度来看,反馈审批进度,知道当前流程走到哪一步了,能够在一定程度上缓解申请人的焦虑感(也便于催促审批人)。

[图片上传失败...(image-83bd2f-1533567574436)]

但本质上,只要最后依然需要人为审批,上述措施所能起到的成效终归是有限的,申请和审批之间总会有个系统无法控制的人为响应的时间差。

因此,有时候我们会发现,在一些系统中开发了相应的功能以后,用户依然有很多的抱怨。所以难道是用户都这么不耐烦?真的有那么多的事情火急火燎,需要立刻完成,一刻都耽搁不了?

能否减少需要申请的权限数量?

我觉得,通常这种情况下,加快审批流程运转的效率可能已经不是问题所在了。问题在于你的用户哪来的那么权限需要立刻审批通过?

我们回头来思考一下什么样的权限申请需要审批?通常是说你不确定这个用户是否可以做某项工作,所以由相关的利益相关人或负责人来判断是否放行。

那么,相比提高审批流转效率,更有效的手段或许是减少需要审批的内容的数量。所以,这就意味着我们牺牲安全性,有一些权限我们就不审批了么?

是,也不是。事实上即使在不明显降低安全性的情况下,减少需要审批的内容,往往也是可行的

举个简单的例子,比如RBAC模型很重要的思想,就是解偶权限点和具体的人的映射关系。这一方面固然是为了简化权限模型(网状变星型),但另一方面,如果你侧重审批的内容是用户的业务角色身份,而不是具体的权限点,那么一旦用户角色确定,很多角色覆盖范围内同类的权限,事实上也就无需审批了。

上述例子,RBAC模型只是一个应用,很多问题可以合理的套上RBAC模型去简化,但也不是说RBAC模型就是相关问题的唯一解。我们要知道,在保证同等安全性的同时,降低申请和审批工作量之所以可行,关键是把一些大同小异的重复过程,通过抽象,变成一次性的过程。而一个用户,他的工作职责和范围在短期内往往是相对固定的,所以这件事通常是可行的。

但这件事的难点在于你怎么挖掘和识别出这个可以抽象的模式,最后在业务流程和权限管控方案的设计中落地体现出来。所以,具体要实现,往往涉及到对业务流程和产品形态规划的深入思考。比如前面我们说的权限下放业务组,组内工作去审批化也是一种方式,我们审批的是你做一类事情的权力,而不是在每件事情上进行审批。

避免火烧眉毛

用户抱怨影响工作效率的场景,流程的绝对响应时间有时往往可能不一定是问题,更多时候,是因为一个开发流程被打断,或者一件事情事到临头了才来处理,这时候,流程上的等待,可能影响心情,可能影响效率,也可能导致问题无法及时解决。总之,抱怨的源头不在于等待流程本身,问题在于在不能等,不想等的时候,却需要等。

所以,有时候在系统方案设计过程中,也应该思考一下,能否通过合理的产品和流程设计,减少或避免火烧眉毛的问题出现?

一方面可以通过前面说的角色和业务规划,权限下放等方式,减少权限申请的必要性,来降低遇到问题的概率。另一方面我们也可以在一些场景下,考虑将权限申请和审批的过程尽量提前来降低这件事的紧急程度。

比如说,你可以将任务运行阶段的权限检测工作,提前到任务开发阶段来进行,不要在半夜任务运行时再报权限错误,而是在白天任务脚本修改保存时就先行检测和验证所需权限。

再比如,你可以通过事先规范权限应用规则的方式,让业务在开发相关工作前,就先申请好与自己相关的权限通道。将权限的申请提前到业务准入阶段,而不是业务开发阶段,避免在开发过程中实际要测试任务的时候再来补权限。

总之,能提前搞定的,就不要临场解决,这一方面,依靠用户自身的规划意识,另一方面,也可以通过产品和流程的设计来贯彻和强化这种意识。

自动化,智能化

自动化和智能化很容易理解,就是能不需要人手工做的,就应该让系统来帮你完成。

比如你创建的表,自然就应该给你赋予对应的权限。说起来很容易,但实际情况下,很多问题并没有那么简单。

比如你创建了一个脚本任务,这个任务的脚本的读写权限自然应该是属于你的。但是,我们可能还要考虑下列问题:

  • 和你同一个业务组的同学是否需要自动授权,需要授予什么权限?如果不想自动授权,流程上又该如何区别?如果你参与了多个业务组,如何判断该脚本的归属关系?

  • 这个脚本创建的表,写出的数据,产生的内容,该如何授权,要不要授权?这并不简单,因为任务权限的管理和数据权限的管理,可能是由不同的系统负责的,需要跨系统创建授权关系,而各系统的权限管理体系,业务分组等等也可能并不一致。

  • 如果相关数据被同步或复制到其它系统中,又该如何同步权限?同构体系的同步问题不大,比如DB主从,集群备份之类。但异构的数据汇总,采集。传输之后的权限。比如hive里面的数据导出到报表系统展示,业务模型都不一样了,那么任务,数据,报表之间的权限关系又该如何映射,能否需要同步,是否能够同步?

上诉问题只是举例说明自动化和智能化可能需要解决的问题,在你的系统中,上诉问题可能不重要,或者也并不一定适合自动授权。但总体来说,自动化和智能化的问题,难点不在于技术的实现,难点在于业务逻辑上如何确定可行的自动化和智能化的规则。

如果你的业务流程没有明确的规范,业务内容缺乏归属关系的梳理,系统之间交互关系不明晰,数据血缘关系难以梳理,那么自动化,智能化的工作就很难进行。所以,与其说这是一个权限管控智能化的工作,不如说更多的是一个数据治理的工作。

总结

权限管理工作,不是简单的安全问题,更多的时候,它是一个产品设计和业务治理的理念和目标问题。实现权限的管控往往并不难,难的是如何尽量减少人为参与权限管控的必要性。

你需要通过用户引导,方案变通,流程规划,价值转移等方式来降低实施的成本和代价,提升最终的实际收益,否则,靠“安全最大”这个尚方宝剑来推动工作是没问题,但用户的抱怨和不配合也一定也会让你的头很大,很大。。。


上篇我们讨论了权限管控方案在目标,产品形态,实施方式方面的哲学问题,接下来,讨论一下技术方面的问题。你可能会想,如果不需要防止Hack的行为,那应该也不是什么很困难的事吧?

从基本的流程来说,确实如此,所以比如早几年前,我司从内部运营系统到到外部业务系统,各种大大小小的后台,一言不合,就会自己实现一套权限认证管理的方案。说到底,不就是两张表的事么,这有何难。。。

[图片上传失败...(image-5921a8-1533567574434)]

不过,当系统越来越多,环境越来越复杂时,你就会发现这件事并没有那么简单。抛开技术问题不谈,单从用户体验的角度来说,如果要在每个系统中都单独管理自己的用户账号和密码,那肯定疯掉了。所以,最起码你需要一个统一的用户账号体系。

然后,如果各个系统的权限申请,管理,审批流程都不一样,系统开发和用户学习的成本会不会很高?于是,你又会考虑除了账号密码以外,各个后台的权限管理模型也应该统一。

而具体落到大数据平台的环境下来讨论权限管理问题,相比多数以功能操作为导向的业务系统,通常又会更加复杂一些。因为大数据开发环境的特点,除了用户个人的操作权限管理,你还需要考虑:

  • 用户协同工作时的数据共享问题

  • 各种存储,计算,查询框架之间数据互通串联的能力

  • 数据的敏感程度不同,对安全等级的区分和管控粒度的要求

  • 分布式的集群场景,海量的数据对象,对权限管控流程的性能,效率,可维护性的要求

  • 各种服务和集群多样的交互,编程和接入方式,增加了权限管控的范围和难度

  • 数据的流动性本质,对权限的动态变更能力的需求

  • 各个组件自身架构在权限管控这块的实现可能千差万别,如何统一和简化的问题

所有这些因素都会大数据平台环境下的权限管控工作变得愈发的困难和复杂。

常见开源方案

权限管理相关工作可以分为两部分内容,一是管理用户身份,也就是用户身份认证(Authentication),二是用户身份和权限的映射关系管理,也就是授权(Authorization)

前者,用户身份认证这一环节,在Hadoop生态系中常见的开源解决方案是 Kerberos+LDAP,而后者授权环节,常见的解决方案有Ranger,Sentry等,此外还有像knox这种走Gateway代理服务的方案。

下面简单介绍一下这些开源项目,目的不是为了讲解这些方案的实现原理,而是从整体架构流程的角度来看看他们的目标问题和解决思想,以及适用场景等,这样当你在选择或者开发适合自己平台的权限管理方案时,也可以做到知其然,知其所以然。

至于Hadoop生态系的各个组件比如HDFS/Hive/HBase自身的权限管理模型,针对的是单一的具体组件,也是权限管控体系中的重要组成部分,但限于篇幅原因,本文就不加以讨论了

Kerberos

Kerberos是Hadoop生态系中应用最广的集中式统一用户认证管理框架。

[图片上传失败...(image-cc8902-1533567574434)]

其工作流程,简单的来说,就是提供一个集中式的身份验证服务器,各种后台服务并不直接认证用户的身份,而是通过kerberos这个第三方服务来认证。用户的身份和秘码信息在Kerberos服务框架中统一管理。这样各种后台服务就不需要自己管理这些信息并进行认证了,用户也不需要在多个系统上登记自己的身份和密码信息。

原理流程稍微多介绍一点(不想了解细节的可以跳过)

用户的身份首先通过密码向Kerberos服务器进行验证,验证后的有效性会在用户本地保留一段时间,这样不要用户每次连接某个后台服务时都需要输入密码。

然后,用户向Kerberos申请具体服务的服务秘钥,Kerberos会把连接服务所需信息和用户自身的信息加密返回给用户,而这里面用户自身信息进一步是用对应的后台服务的秘钥进行加密的,由于这个后台服务的秘钥用户并不知晓,所以用户也就不能伪装或篡改这个信息。

然后,用户将这部分信息转发给具体的后台服务器,后台服务器接收到这个信息后,用自己的秘钥解密得到经过Kerberos服务认证过的用户信息,再和发送给他这个信息的用户进行比较,如果一致,就可以认为用户的身份是真实的,可以为其服务。

核心思想

Kerberos最核心的思想是基于秘钥的共识,有且只有中心服务器知道所有的用户和服务的秘钥信息,如果你信任中心服务器,那么你就可以信任中心服务器给出的认证结果。

此外很重要的一点,从流程上来说,Kerberos不光验证的用户真实性,实际上也验证了后台服务的真实性, 所以他的身份认证是双向认证,后台服务同样是通过用户,密码的形式登记到系统中的,避免恶意伪装的钓鱼服务骗取用户信息的可能性。

应用Kerberos的难点在哪

Kerberos从原理上来说很健全,但是实现和实施起来是很繁琐的

为什么这么说呢,首先所有的后台服务必须针对性的接入Kerberos的框架,其次所有的客户端也必须进行适配,如果具体的后台服务提供对应的客户端接入封装SDK自然OK,如果没有,客户端还需要自己改造以适配Kerberos的认证流程。

其次,用户身份的认证要真正落地,就需要实现业务全链路的完整认证和传递。如果是客户端直连单个服务,问题并不大,但是在大数据平台服务分层代理,集群多节点部署的场景下,需要做用户身份认证的链路串联就没那么简单了。

举个例子,如果用户通过开发平台提交一个Hive脚本任务,该任务首先被开发平台提交给调度系统,再由调度系统提交给Hive Server,Hive Server再提交到hadoop集群上执行。那么用户信息就可能要通过开发平台/调度系统Master节点/调度系统Worker节点/Hive Server/Hadoop 这几个环节进行传递,每个上游组件都需要向下游组件进行用户身份认证工作

就算到了具体的后台服务内部。比如在Hadoop集群上运行的一个MR任务,这个认证关系链还需要继续传递下去。首先客户端向Yarn的RM节点提交任务,客户端需要和RM节点双向验证身份,然后RM将任务分配给NM节点启动运行,RM就需要把用户身份信息传给NM(因为NM节点上启动的任务会需要以用户的身份去读取HDFS数据)在NM节点上的任务以用户的身份连接HDFS NameNode获取元数据以后,下一步还需要从HDFS Datanode节点读取数据,也就再次需要验证用户身份信息。

上述的每个环节如果要支持基于Kerberos的身份验证,要么要正确处理秘钥的传递,要么要实现用户的代理机制。而这两者,实施起来难度都不小,也会带来一些业务流程方面的约束。

雪上加霜的是,这个过程中,还要考虑身份验证的超时问题,秘钥信息的保管和保密问题等等,比如MR任务跑到一半秘钥或Token过期了该怎么办,总不能中断任务吧? 所以一套完整的链路实现起来绝非易事,这也是很多开源系统迟迟没有能够支持Kerberos的原因之一,而自己要在上层业务链路上完整的传递用户身份信息,也会遇到同样的问题。

最后是性能问题,集中式管理在某种程度上意味着单点,如果每次RPC请求都要完整的走完Kerberos用户认证的流程,响应延迟,并发和吞吐能力都会是个比较大的问题,所以比如Hadoop的实现,内部采用了各种Token和cache机制来减少对Kerberos服务的请求和依赖,并不是每一个环节步骤都通过Kerberos进行验证。

小结

总体来说,Kerberos是当前最有效最完善的统一身份认证框架,但是如果真的要全面实施,代价也很高,而从安全的角度来考虑,如果真的要防止恶意破坏的行为,在整个生产环境流程中,能被突破的环节其实也很多,光上Kerberos并不意味着就解决了问题,所以各大互联网公司用还是不用Kerberos,大家并没有一致的做法,即使All in Kerberos的公司,我敢说,除非完全不做服务化的工作,否则,整体链路方面也一定存在很多并不那么Kerberos的环节 ;)

最后,用户身份认证只是权限管理环节中很小的一部分,虽然技术难度大,但是从实际影响来看,合理的权限模型和规范的管理流程,通常才是数据安全的关键所在。所以,上不上Kerberos需要结合你的实际场景和安全需求加以考量。

Sentry和Ranger

Sentry和Ranger的目标都是统一的授权管理框架/平台,不光目标,这两个项目在思想和架构方面也大同小异,那么为什么会有两套如此类似的系统?当然是因为Cloudera和Hortonworks两家互相不鸟,必须各搞一套呗,目前看起来,Sentry借CDH用户基数大的东风,普通用户比较容易接受,但Ranger在功能完整性方面似乎略微占点上风。

相比用户身份认证,授权这件事情和具体服务的业务逻辑关联性就大多了,如果是纯SQL交互的系统,通过解析脚本等方式,从外部去管理授权行为有时是可行的,其它情况,通常都要侵入到具体服务的内部逻辑中才有可能实现权限的控制逻辑。

所以Sentry和Ranger都是通过Hook具体后台服务的流程框架,深度侵入代码,添加授权验证逻辑的方式来实现权限管控的,只不过具体的权限管理相关数据的存储,查询,管理工作实际是对接到外部独立的系统中承接实现的,进而实现各种存储计算集群权限的统一管理。

要Hook具体后台服务的流程框架,最理想的是原系统本身就提供插件式的权限管理方案可供扩展,否则就需要对原系统进行针对性的改造,另外各个系统自身既有的权限模型也未必能满足或匹配Sentry和Ranger所定义的统一权限管理模型,是否能改造本身就是个问题。

加上权限验证流程通过查询外部服务实现,因此在权限的同步,对原系统的性能影响等方面常常也需要小心处理或者针对性的优化。因此,统一的授权管理平台这一目标也是一个浩大的工程。所以至今无论Sentry还是Ranger都未能全面覆盖Hadoop生态系中常见的计算存储框架。

小结

总体来说,授权这件事,Hadoop生态系中的各个组件往往会有自己独立的解决方案,但是各自方案之间的连通性并不好。而统一的授权管理框架/平台的目标就是解决这个问题,但它们当前也不算很成熟,特别是在开放性和定制性上,往往也有一定局限性。

当然,要用一个框架彻底打通所有组件的权限管理工作,除了插件化,其它其实也没有特别好的方式,而插件化自然需要框架和具体组件的双向合作努力。只能说就当前发展阶段而言,这一整套方案尚未足够成熟,没到完美的程度,也没有事实统一的标准。所以无论是Sentry还是Ranger,当前的实现如果刚好适合你的需求自然最好,如果不适合,那还需要自己再想办法,且看他们将来的发展吧。

Knox

最后来说一下Knox项目,它的思想是通过对Hadoop生态系的组件提供GateWay的形式来加强安全管控,你可以近似的认为他就是一个Rest/HTTP的服务代理/防火墙。

所有用户对集群的Rest/HTTP请求都通过Knox代理转发,既然是代理,那么就可以在转发的过程中做一些身份认证,权限验证管理的工作,因为只针对Rest/HTTP服务,所以他并不是一个完整的权限管理框架

使用Gateway的模式有很大的局限性,比如单点,性能,流程等等,不过对于Rest/HTTP的场景倒也算是匹配。它的优势是通过收拢Hadoop相关服务的入口,可以隐藏Hadoop集群的拓扑逻辑,另外,对于自身不支持权限认证管理的服务,通过Gateway也能自行叠加一层权限管控。

开源项目中常见的权限模型概念:RBAC / ACL / POSIX / SQL Standard

如果去阅读各种开源组件的权限架构相关文档,谈到权限模型时,你往往会看到各种各样的名词称谓,比如RBAC,ACL,POSIX, SQL Standard 等等。

严格来说,这些概念的内容并不是对等的,或者说他们描述的问题有时候并不是同一个范畴的内容,不适合直接拿来对比。

但是,实际环境中,各个系统在为他们的权限模型或者思想概念起名的时候,往往也并不真的完全和这些名词的所谓学术或标准上的定义相匹配,所以我在这里讨论这些概念的时候,也不打算追求绝对的精确,只是借这些名词,泛泛的谈一下其背后的思想,目标以及在平台建设过程中值得我们关注的点。

首先来看RBAC模型,RBAC从标准规范的角度来看,绝对是一个复杂的标准,但是实际情况下,各种开源系统在讨论RBAC的时候,通常重点指的就是权限和用户之间需要通过角色的概念进行一次二次映射,目的是为了对同类权限或同类用户进行归类,减少需要维护的映射关系的数量。至于RBAC理论层面上各种层级的约束,条件,规范等等,其实谈得很少。

而在其它模型中,也或多或少有组/角色的概念,只是比如:组的涵盖范围,是否允许存在多重归属,能否交叉,能否嵌套,是否允许用户和权限直接挂钩等具体规则上有所区别。不过基本上,如果你要宣称自己是一个RBAC模型的话,那么基本上还是要重点强调角色模型和映射关系的建设。而在其它模型中,组/角色的概念相对来说可能并没有那么突出或者重要。

然后谈POSIX的权限模型,谈这个,当然是因为HDFS的文件权限模型,很长一段时间以来,只支持POSIX标准文件的权限管理模型,即一个文件对应一个OWNER和一个GROUP,对OWNER和GROUP以及其它用户配置RWAC这样的读写通过管理等权限。

POSIX模型很直白,很容易理解,实现也简单,但POSIX模型最大的问题是文件的共享很难处理。因为要将权限赋予一拨人,只能通过单一固定的组的概念,你无法针对不同的人群和不同的文件进行分组授权,所以很难做到精细化的授权管理。

为了解决权限多映射精细管理问题,HDFS又引入了ACL模型,Access Control List,故名思意,就是针对访问对象,有一个授权列表。那么对不同对象给不同用户赋予不同的权限也就不成问题了。当然,HDFS的ACL模型也不是范本,事实上各种系统中所谓的ACL模型,具体设计都不尽相同,唯一可能共通的地方就是:对访问对象赋予一个授权列表这个概念,而不是像POSIX这样固定分类的授权模式。

ACL模型理论上看起来很理想,但在HDFS集群这个具体场景中,麻烦的地方在于如果集群规模比较大,授权列表的数量可能是海量的,性能,空间和效率上都可能成为问题,而事实上,ACL对象精细化的管理也并不那么容易。当然这些也并不能算是ACL模型自身的问题,更多的是具体的实现和上层业务规划方面的问题。

最后所谓的SQL标准的权限模型,从模型的角度来说和ACL模型并没有什么本质的区别,只不过是在类SQL语法的系统中,模仿了Mysql等传统数据库中标准的授权语法来与用户进行交互。具体的实现例子,比如Hive Server2中支持的SQL标准授权模型

基于开发平台服务入口的权限管控思路

了解了相关的解决方案和思路,在我们自己的大数据平台的权限管理方案的实施过程中,不管是全面使用开源方案,还是局部混搭,又或者是完全自行构建,我们都可以从身份认证与授权管理,集中式管控与Gateway边界管理等角度来拆解,思考和分析问题,寻找适合自身业务场景的整合方案。

我司的整体思路,是尽可能通过构建产品化的大数据开发平台,将各种集群以服务的形式对外提供,换句话说,类似于上述Gateway的思想(但不是knox这种http代理),尽可能让用户通过开发平台来提交任务,管理数据,而不是直接通过API连接集群。

当所有的用户都通过开发平台来和集群进行交互时,开发平台就具备了统一的用户身份认证和权限管理的基础前提条件。当然实际情况并没有那么理想,不管是出于技术原因,实现代价原因,程序效率性能原因,还是业务流程原因,总会有些业务流程和任务无法通过开发平台来统一管控。这时候就需要结合其它方案来弥补了。

以HDFS集群的文件读写的权限认证为例,大部分涉及到HDFS文件读写的任务,比如Hive/Presto/SparkSQL等相关任务,如果我们管控了这些任务作业的提交入口,相关的集群由我们提供,那么多数权限管控工作我们都是能够在开发平台层面完成管控的。

但还有很大一部分需要读写HDFS数据的业务,自身并不运行在大数据开发平台提供的服务上。比如内网的简历系统需要存取简历,商家的证照文件需要备份,广告的算法模型,特征数据需要在各个子系统间传输等等,这些业务的程序可能是自行开发的,调用入口也并不在大数据开发平台上,所以开发平台也就很难对其进行用户身份认证。

而Hadoop的客户端,除了Kerberos方案,剩下的Simple认证方案,实际上并不真正识别用户的身份(比如你只需要通过环境变量设置宣称自己是用户A,Hadoop就允许你操作用户A的数据)。那么不上Kerberos就没法处理了么?

也不完全如此,如果用户的需求是简单的文件存储工作,那么我们可以考虑通过对象存储服务的方式来支持,用户身份的认证在对象存储服务中实现,由对象存储服务代理用户在HDFS集群上进行文件读写操作。但如果用户就是需要灵活的Posix模式的文件读写服务,那显然,就要在HDFS自身服务方面动脑筋了。是封装客户端还是改造服务端,取决于具体的安全需求程度和实现代价

基于服务端的改造通常对用户的透明性好一些,安全性也更强一些(因为别人可以不用你封装好的客户端。当然,也可以在服务端加上客户端的ID识别之类的工作来加强防范)。比如,如果我们相信业务方自己不会滥用账号,我们的目的只是防止各个业务方之间无意的互相干扰和误操作,那么在服务端进行用户身份和IP来源的绑定鉴定(即特定用户只能由特定IP的机器使用),结合Hadoop自身的Posix文件权限管理模式,基本就能达到目的。当然,服务端的管控还可以想到更多的其它方案,这就需要结合你的业务环境,运维成本和技术代价等进行判断选择了。

再比较一下底层统一权限管控平台和基于开发平台进行边界权限管控的优缺点

首先,Ranger等方案,主要依托大数据组件自身的方案,Hook进执行流程中,所以管控得比较彻底,而开发平台边界权限管控,前提是需要收拢使用入口,所以论绝对安全性,如果入口收不住,那么不如前者来得彻底。不过通常来说,为用户提供统一的服务入口,不光是安全的需要,也是开发平台提高自身服务化程度和易用性的必要条件。

其次,底层权限统一管控平台,因为依托的是大数据组件自身的方案,并不收拢用户交互入口,所以身份认证环节还是需要依托类似Kerberos这样的系统来完成。而开发平台服务方式,收拢了入口,就可以用比较简单方式自行完成身份认证,如前所述,相比涉及到三方交互的分布式身份认证机制,通常实现代价会更低一些。

再次,大数据组件自身的权限方案,权限验证环节通常发生在任务实际执行的过程中,所以流程上基本都是在没有权限的时候抛出一个异常或返回错误,因此不太可能根据业务场景做更加灵活的处理。

而开发平台服务方式,权限的验证如果可以做到在执行前阶段(比如通过语法分析获得)进行,那么流程上就可以灵活很多,可以结合业务相关信息提供更丰富的调控手段。

例如,业务开发过程中,在代码编辑或保存时就可以进行相关权限验证和提示,避免在半夜任务实际执行时才发现问题。也可以定期批量审计脚本任务,或者根据业务重要程度对缺乏权限的情况进行区别对待:提示,警告,阻断等等。简单的说,就是你想怎么做就怎么做。而Ranger等基于底层组件进行Hook的权限架构方案,一来没有相关业务信息无法做出类似决策,二来考虑通用性,很多平台环境相关业务逻辑不可能也不适合绑定进来。

当然,这两种方案并不是互斥的,如何定义你的产品,如何拆分各种需求,对你选择权限管控方案也有很大的影响。更常见的情况是,你会需要一个混合体,取长补短,弥补各自的不足之处。

小结

总体来说,在开发平台上进行边界权限管控,并不是因为这种方式更安全,而是因为它更灵活,与业务和流程的兼容适配性更好,对底层组件自身权限管控能力的依赖性也更小。甚至还可以根据业务逻辑针对性定制权限管控策略,但是因为自身通常并不深度Hook具体组件内部执行逻辑,所以部分场景可能无法有效的进行管控(比如二进制代码任务无法从外部解析其读写逻辑),就需要和底层组件权限管控方案结合起来实施。

换个角度来说,这也是在开发平台的产品化过程中,很多任务我们会希望尽可能SQL化/脚本化/配置化的推动动力之一。一方面SQL化/脚本化/配置化有助于降低用户的开发成本,可以做一些系统层面的自动优化,沉淀知识和最佳实践。另一方面,有了可供解析语义的文本,也便于根据语义进行权限管理,尽可能完善平台边界权限管控的能力和范围。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容