1. 异构系统带来的认证鉴权问题
企业系统,可以分为以下几种类型:
- 购买的商业软件,比如 JumpServer
- 开源的软件,比如 Kibana、Grafana
- 自主研发的软件,比如应用管理平台
这里需要说明的是,认证和鉴权是两个功能:
- 认证,证明你是你
- 鉴权,你是管理员,而不是普通用户
针对上面的系统,在接入认证鉴权时,主要面临如下问题:
- 自主定制成本高,而社区支持响应慢。定制开源组件需要投入大量人力,直接对其进行定制是不合时宜的,而将需求提交到社区等待解决方案,周期太长,难解燃眉之急
- 自研系统一个一个对接认证鉴权成本很高。每一个自研系统都需要实现一套类似的逻辑,校验登录态,验证权限规则
- 老的系统接入困难。有些老的服务相关人员离职,几乎没人维护但又有人在使用,改不动
对于商业购买的软件,在采购时就可对接入成本、安全性等进行评估,常常能够满足认证鉴权的需求。而在大型企业中,不同的部门总是习惯性建设一套自己熟悉的认证鉴权系统,导致部门与部门之间的系统割裂,形成一个一个的烟囱壁垒,信息无法在内部自由流动。这给员工带来极大不便、大大降低工作效率,削弱企业在市场上的竞争力。统一的认证鉴权体系是有必要的。公共的功能,通过服务化的形式提供给大家使用,不仅可以避免重复开发,还可以享受更优质的职能化服务。
2. 服务的域名策略
在进行登录态验证时,通常会需要获取 HTTP 请求的 Cookie。而 Cookie 的作用范围是和域名直接相关的。因此在聊统一认证鉴权之前,先了解一下服务的域名策略。
2.1 多域名多服务
为了服务之间彻底隔离,减小每次变更的影响范围,会采用多域名策略。示例如下:
harbor.oa.com
c.domain.com
www.chenshaowen.com
一个服务一个域名,减小了故障的爆炸半径,但也在管理上增加了很大成本,比如证书、DNS 配置等。如果没有统一的管理平面,这些复杂度的增加必然会增加人为失误、犯错的概率。控制复杂度是每个优秀的工程师必须掌握的技能。统一的域名有利于树立良好的品牌形象。混乱的域名使用,会导致用户品牌识别度降低,误将李鬼当李逵,让黑产有机可乘。同时,多域名也不利于 SEO,分散服务在搜索引擎上的打分,降低排名。因此,域名不要太多,在启用新域名之前,多思考能不能不用,采用尽可能少的原则使用。在多域名策略下,我们只能以第三方登录的形态接入统一登录系统。每个系统申请一套接入凭证,然后各自进行对接。
2.2 单一域名多 Location
采用同一个域名,不同 Location 对应不同服务,是我推荐的一种做法。
domain.com/grafana/
domain.com/oa/
domain.com/c/
domain.com/c-test/
用户好记,研发也不用再苦恼于配置 Hosts,采用多域名时,每个服务配置一个 Hosts,甚是麻烦。入口统一易于维护。多入口、多管理平面都是架构、运维能力弱的表现。谁都不会拒绝简单,直观、简洁、所见即所得是我们在设计系统时不断追求的目标。由于采用单域名,这些系统之间的 Cookie 是共享的。因此只需要在该域名下写下登陆态 Cookie,用户使用其他系统时,也将处于登录状态。其他系统无需完成登录逻辑,只需要后台校验登陆态,再进行鉴权即可。
3. 通过七层 forward-auth 接入认证鉴权
如上图,无论是对于商业、自研、开源的软件,我们都可以通过七层网关统一认证鉴权。下面是访问流程:
值得高兴的是,有些网关已经提供了这样的功能,比如 Apisix 的 forward-auth 插件,Traefik 的 forward-auth 中间件等,我们直接使用即可。下面是 forward-auth 需要实现的功能:当有流量经过网关时,forward-auth 需要向指定的鉴权接口,发送一个请求,如果请求返回的是 200,那么放行流量;如果请求返回的是非 200,那么将进行重定向,将流量引导至认证页面。下面是在 Apisix 中给 forward-auth 的一段配置,以供大家参考:Apisix 中 forward-auth 插件是 lua 编写,可以根据需要进行修改。比如,需要增加鉴权逻辑,只需要将 UID 和资源定位符 URI 传给统一的鉴权中心即可。
4. 通过 sidecar 接入认证鉴权
上面这种方式,我们是将认证放在了接入层,对业务系统没有任何改造。但是这种方式存在一个风险,如果绕过网关,就可以绕过认证。在网关上实现的 forward-auth 认证的是南北向流量,即用户直接访问业务系统的流量。但这却无法控制东西向流量,其他服务依然可以对受控服务进行访问。另一种方式是,采用 Sidecar 进行认证鉴权,如下图:我们需要开发一个 Sidecar,下沉网关层的 forward-auth,代理全部访问流量,进行统一认证鉴权之后再转发至受控业务。这样就需要在每个受控系统上,部署一个 Sidecar。此时,用户请求的流量应该转发给 Sidecar 而不是业务本身。
5. 总结
本文主要思考的是在异构的系统下,如何快速接入统一的认证鉴权体系。认证是证明你是你,而鉴权是证明你有权限这样做。在已有一套统一的认证鉴权系统的前提下,这里提供了两种快速接入的思路:第一种是,采用网关层的 forward-auth,对业务无任何入侵,在接入层完成认证鉴权。通过后端 Middleware 二次验证,能够提供进一步的安全验证。第二种是,采用 Sidecar 拦截受控业务的流量,进行认证鉴权之后,再转发流量。这种方式具有一定的开发量,但 Sidecar 可以复用,对业务代码没有入侵。其实,很多 Middleware 实现的功能都可以使用 Sidecar 实现,将开发成本转移到运维部署层面,当基础设施是 Kubernetes 时,我们又可以借助于 kube-apiserver 的准入控制 Webhook 实现自动注入,达到一次开发永久零成本使用的效果。
6. 参考
- https://apisix.apache.org/zh/docs/apisix/plugins/forward-auth/