写点什么

OpenIAM 简介

  • 2019-09-20
  • 本文字数:3117 字

    阅读完需:约 10 分钟

OpenIAM 简介

我们作为链家网的基础架构团队,提供了许多服务给业务线使用。在这个过程中,我们逐渐发现,(业务)服务和(基础)服务之间,“资源隔离”是初期强需求,“权限管理”是远期强需求。

当前,我们有的系统通过客户端传递“用户名/密码”,隐式地将数据隔离在当前用户这个 namespace 下;有的系统使用 AppId 和 AppKey 的方式标明用户,在数据库中更为灵活地记录权限信息。

我们除了作为服务的提供方,还往往需要充当系统管理员的角色:我们通过代码/后台/数据库等方式配置管理权限。这类琐碎的需求隔三岔五出现,可能需要我们线下测试、线上修改,打断了原本的开发节奏;用户可能需要较长时间的等待,压低了预期。

随着提供服务的增多,每个系统都可能需要开发一套用户/资源/权限的子系统,这越来越成为一种负担,拖慢了上层业务的开发,且带来了不一致的用户体验。我们在思考,有没有一个通用服务,覆盖那部分通用性强的,业务无关的权限管理?它只需要很小的成本接入,就能够提供统一的身份识别和方便的权限管理。

实际上,SaaS 平台上早有了成熟的解决方案,它就是 Identity and Access Management 系统。在链家,我们同时使用了自建 IDC 和公有云服务 Amazon Web Service。我们期待自己的服务,也能集成类似 AWS IAM这样的系统。

介绍 AWS IAM

用户体系

在 AWS IAM 中,用户分为四类实体:


  • Account(Root User)

  • 帐号对拥有的资源,有所有权限

  • 帐号可分发权限给用户,或赋予用户权限代为管理

  • 资源隔离在帐户下,不可跨帐号使用

  • User

  • 帐号下的权限隔离

  • 推荐日常使用

  • Group

  • 用户可加入到用户组

  • 方便权限的聚合管理

  • Role

  • 方便第三方跨帐户使用

  • 用户可 AssumeRole 换取临时 AK/SK,切换到对应角色


其中,帐号和用户可以有访问凭证,分别是:


  • 用户名/密码,后台访问

  • AccessKeyId/SecrectAccessKey, 程序使用 HTTP API 访问

认证流程

对于用户请求的身份识别,通常有两种方案:


  1. 基于 Session,Session 过期后重新登录。

  2. 对每次请求加密,一次一密。

  3. AWS IAM 选用了方案二,后端无状态,请求更安全。


用户在程序请求时,使用申请好的 AccessKeyId 和 SecrectAccessKey,针对 Request 的当前时间,Header 字段, URL Query 参数,Body Digest 等元素,按照一定规则拼接字符串,生成签名。


Server 校验签名,确认当前用户,判断是否有对应权限,记录请求以供审计,完成请求返回结果。

策略文档

AWS IAM 使用了 JSON 文档的方式描述策略 Policy,并提供了策略编辑器工具帮助不熟悉的用户撰写文档。


我认为这是很棒的设计:


  • JSON 是程序员们广泛接受,能够手写的格式

  • JSON 支持 Array, Map 等复杂类型,方便聚合权限


官方示例 Policy 如下:


{  "Version": "2012-10-17",      "Statement": [    {    "Effect": "Allow",               "Action": [                      "s3:ListAllMyBuckets",                      "s3:GetBucketLocation"          ],                "Resource": "arn:aws:s3:::*"    },    {     "Effect": "Allow",                 "Action": "s3:ListBucket",                 "Resource": "arn:aws:s3:::BUCKET-NAME",                  "Condition": {"StringLike": {"s3:prefix": [                        "",                        "home/",                        "home/${aws:username}/"          ]}}    },    {      "Effect": "Allow",                 "Action": "s3:*",                 "Resource": [                       "arn:aws:s3:::BUCKET-NAME/home/${aws:username}",               "arn:aws:s3:::BUCKET-NAME/home/${aws:username}/*"      ]    }  ]}
复制代码


Policy 基于字符串的匹配,加上 Allow/Deny Effect 的组合,更通用、易理解的变量名称,和外部系统深度集成的 Condition 条件语句,灵活强大,自成体系。


最终,Policy 通过内嵌(Inline Policy)或附加(Managed Policy)的方式,挂接到帐户里的用户、用户组和/或角色,完成了权限的分发。


整个解决方案,用户使用简洁灵活,可以从策略文档,挂接方式,用户类型上管控;服务提供方只需要暴露出全局性的 Resource 和梳理提供的 Action 即可。用户通过一套机制,完成了对 AWS 所有服务的对接,在 IAM 后台完成了绝大部分权限管理的工作(比如,S3 除了支持 IAM 基于访问用户的权限,还提供了基于对象的管理)

自研

AWS IAM 是个私有服务,我们只能感知客户端 SDK 和后台 Console 的行为动作,S3/EC2 之类的服务和 IAM 之间交互是透明的,无法感知的。我们翻出了私有云的实现 - OpenStack KeyStone,看看是否不用重复造轮子。


在调研阶段,我们发现,KeyStone 只是一个 Identity 服务,只实现了身份的识别,权限信息仍保留在各自的 Service 上。并且,KeyStone 是基于 Role 的设计,即便是一个细微的权限问题,我们也要先建一个 Role 与之对应,然后绑定用户,异常笨重。由于从一开始就存在较大的阻抗匹配,我们放弃了基于 KeyStone 的二次开发方案,使用 Golang 从头开发了自己的实现:OpenIAM。


在决定自研后,我们投入了两个人力(其中一个是没有写过 Golang,帅帅的大三实习生,彬彬同学),在一个多月的时间内,完成了一期目标,完全兼容了 AWS CLI,用 Vue.js 复刻了 AWS 的 Admin Console。


我们除了提供 JSON/XML 的 HTTP 接口供用户日常管理之外,还提供了高性能的 gRPC 接口供服务提供方接入。


我们设定,服务提供方不应知道 SecrectAccessKey 和 Policy 信息。它接到业务请求,只需抽取 AccessKeyId、签名和签名所用字符串,申明签名方式(如 HMac 哈希,Base64 摘要等),再加上服务自身感知到的 Resource 和 Action,一起交由 OpenIAM 完成认证和鉴权两步操作。我们使用这种方式,打通了业务/服务/OpenIAM 三者之间的闭环。


整体的流程如下图:



OpenIAM 在授权认证时的简化活动图:



那么,在 OpenIAM 服务上线后,我们预期会带来哪些改变呢?


  • 服务提供方仅需告知 OpenIAM 创建资源的帐号;后期鉴权均由 OpenIAM 完成,对提供方透明。

  • 资源的拥有者,直接在 OpenIAM 上管理权限;服务提供方无权管理。

  • 客户端逐步统一访问方式,降低接入成本,一套 AccessKeyId/ScrectAccessKey 即可跨多服务使用。

  • OpenIAM 可整合接入服务的服务后台,提供一致的使用体验。

使用场景

我们可以看到,IAM 解决的是服务和服务间的身份认证/权限管理。


在 AWS 里面所有服务都是基础服务,均有较强的资源概念。在公司里,存在更多的业务系统,没有清晰的资源概念,OpenIAM 能够适配这种情况吗?


例如,一个 Restful 的 API 接口,提供了对业务实体的 CRUD 操作。我们可以将每一个业务实体当成一个资源,将 GET/POST/PUT/DELETE 映射成 Action;服务提供方在 Resource 定位符中,直接告知 OpenIAM 资源的拥有者,OpenIAM 即可在此帐号下完成对业务实体的权限认证。


问题二,服务有自己的用户权限体系,用户请求可能涉及到第三方服务的权限问题。用户权限跟 IAM 权限有什么关系,该如何划分边界?事实上,OpenIAM 不关注用户权限信息。业务系统可以有如下两种选择:


1.一般情况下,业务系统的 AK/SK 拥有对第三方服务所需的所有权限,普通用户的权限由业务系统自行判定。


2.业务系统可以预设几个 IAM 子用户,将应用级别的用户映射到不同的 IAM 用户,不同 IAM 用户拥护不同的第三方服务权限。用户请求时,将请求转用对应的 AK/SK 加密,由 OpenIAM 决策允许或拒绝。

总结

在微服务日益火爆的今天,服务的数量会积极膨胀。OpenIAM 希望能解决服务和服务间的资源隔离问题。我们期待能跟大家更深入地分享 OpenIAM 设计与实现,如果感兴趣请留言


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/eY9HNeF4zroaOpU3oE8fKQ


2019-09-20 17:053571

评论

发布
暂无评论
发现更多内容

环信入选2020在线教育视频云创新排行TOP10

DT极客

第五周作业 (作业二)

Geek_83908e

极客大学架构师训练营

week-5-part2 学习总结

陈龙

Consistent Hashing算法实现 - JavaScript

架构训练营 - 第5周课后作业 - 学习总结

Pudding

「架构师训练营」第 1 周作业 - 食堂就餐卡系统设计

xiaomao

第五周学习心得

熊桂平

极客大学架构师训练营

Week 5 作业02

Croesus

超越视觉支持语音新版OpenVINO发布,为更多智能边缘开发者赋能

E科讯

一文快速入门分库分表中间件 Sharding-JDBC (必修课)

程序员小富

Java 分库分表

作业-2020年10月25日

芝麻酱

SpringBoot整合原生OpenFegin的坑(非SpringCloud)

冰河

微服务 高并发 远程调用 springboot OpenFegin

5. Bean Validation声明式验证四大级别:字段、属性、容器元素、类

YourBatman

Hibernate-Validator Bean Validation 数据校验

万字长文深入理解java中的集合-附PDF下载

程序那些事

java编程 JAVA集合 java集合总结 java集合使用 java秘籍

第5周作业

paul

【架构师训练营 1 期】第五周作业

诺乐

架构师训练营 - 第 5 周课后作业(1 期)

Pudding

Go发起HTTP2.0请求流程分析(后篇)——标头压缩

Gopher指北

后端 HTTP2.0 Go 语言

极客大学 - 架构师训练营第一期 - 第五周作业

Black Eyed Peter

极客大学架构师训练营

架构师训练营第 1 期第 5 周作业

owl

极客大学架构师训练营

【架构师训练营 1 期】第五周学习总结

诺乐

非阻塞的无界线程安全队列 —— ConcurrentLinkedQueue

程序员小航

Java 源码 并发 源码阅读 JUC

架构师训练营第五周学习笔记

一马行千里

极客大学架构师训练营

一致性hash

袭望

第五周作业

熊桂平

极客大学架构师训练营

架构一期第五周作业

Airs

10月24日,“网安小酒馆”线上活动开启,有红包,更有名酒相送

Cloudaemon

作业一:食堂就餐卡系统设计

伊灵

week-5-part1 java实现一致性 hash 算法

陈龙

间隔重排序链表Reorder List,iOS架构RxSwift, VIPER,MVVM,MVP, 机器学习,SageMaker,John 易筋 ARTS 打卡 Week 23

John(易筋)

学习 ARTS 打卡计划 重新排列链表算法 iOS 架构RxSwift SageMaker

阿里云盘线下交流会

兔2🐰🍃

阿里云网盘 Teambition 线下体验

OpenIAM 简介_文化 & 方法_尹吉峰_InfoQ精选文章