
0. 架构
1. 背景
最近公司内网的各种系统部署得越来越多,每个系统都有自己的认证方式和账号体系,这导致大家在每个地方都要去注册一个账号,并且不利于公司统一管理密码安全策略,例如密码到期策略、密码复杂度策略以及强制二次验证等。
以及对于一部分短平快的内网应用来说,我们并没有时间去为它开发一套用户体系,这个时候还是希望能有一个统一的前端反向代理来处理用户认证这个流程。
为此,我就去寻找了一些解决方案,并且为了解决开源系统并不能对接外部用户系统的问题,开发了一个 Node.JS Package(Virtual-LDAP)来提供 LDAP 能力。
2. 问题
虽然总的需求是一个很简单的功能,但是这其中还是有很多细节的问题需要考虑。
认证方式
对于有一些开源系统,它本身是支持 OAuth 来进行用户认证的,这个时候只需要去选择一个支持 OAuth 的用户管理系统就可以了,甚至基于开源库自己去开发一个也并不困难。但是对于某一些开源系统来说,它并没有提供 OAuth 认证接入的支持,只提供了 LDAP 接入。
例如最近我们引入了 Metabase 作为面向运营的快速 BI 分析工具,但是它除了可以接入 Google 账号作为认证方式,就只能接受 LDAP 作为认证方式了。这个时候就得去寻找一个认证系统,同时能支持 OAuth 以及 LDAP。
用户体系
引入用户管理系统之后,还有另外一个问题需要考虑,就是现在员工的用户体系需要去管理。对于一个小公司来说,目前并没有一个统一的工具去同时管理员工的各种信息以及状态。
但是目前公司已经引入钉钉作为公司的交流沟通工具,以及作为各种流程的审批处理系统,HR 也会在钉钉上去管理所有员工的状态,以及员工的组织架构。
因此,这个用户管理系统最好需要能支持同步钉钉中的用户体系,这样就不需要额外的人力去维护用户管理系统,以及在有员工状态变更的时候,能及时同步,避免出现授权外的访问。
数据同步
有了 OAuth,有了 LDAP,还有了钉钉这个数据源,因此就需要处理好各个 Provider 之间的数据同步问题,避免人工去维护各个系统里面的用户数据,做到以钉钉的数据为基础,用户管理系统提供能力,做到各个系统各个认证方式得到的用户数据都是一致的。
以及,对于 LDAP 来说,它是有组织架构的概念的,这个可以在对接到它的应用系统中,快速映射到应用中的用户组,实现用户的权限自动分配和管理,避免每次有新员工加入,都需要单独去配置一次各个业务系统的权限。因此,这也要求用户管理系统能够做到同步钉钉的组织架构,无需额外管理。
3. 解决方案
KeyCloak
KeyCloak 是一个开源软件产品,旨在为现代的应用程序和服务,提供包含身份管理和访问管理功能的单点登录工具。
KeyCloak 提供了丰富的功能用于公司内部单点登录上,包括:
- 内置的用户账号管理界面
- OpenID Connect 以及 OAuth 2.0 支持
- LDAP 同步支持
- 支持自定义主题
虽然之前也找到了 FreeIPA 这个开源系统,功能也同样强大,但是在部署过程中碰到了很多问题,最后还是选择了 KeyCloak。
Pomerium
对于大多数开源系统来说,可能都已经内置了对于 OAuth 或者 LDAP 的支持,对于这些系统,只需要按它的需求,去配置 OAuth 或者 LDAP 认证即可接入 KeyCloak。
但是对于一些静态页面,或者是自行开发的内部应用,可能并没有时间去额外添加用户认证支持,而这个需要就需要一个带用户认证支持的反向代理了。
Pomerium 就是这样一个反向代理应用,它作为一个 Identity-Aware Proxy,用于给内部应用增加安全访问的能力。
Pomerium 的主要功能有:
- 支持接入 OAuth 认证
- 支持配置内部应用允许哪些域,或者哪些用户可以访问
- 支持 WebSocket 转发
- 支持转发时自定义 HTTP Header
- 支持 JWT 或 HTTP Header 传递用户 Session 信息到后端内部应用
- 提供一个隐式 domain/.pomerium 路径来显示当前用户信息
- 支持使用 Wildcard SSL 证书给后端服务统一增加 SSL 支持
通过 Pomerium,就可以将内部不带用户认证的应用直接加上用户认证的能力,避免非授权访问,并且可以直接通过 JWT 传递过来的用户信息,进行额外的用户权限管理。
Virtual-LDAP
Virtual-LDAP 是我开发的一个 Node.JS 程序包,用于使用自定义数据源来提供一个 LDAP 服务,可以将非 LDAP 用户系统(目前支持钉钉)对接到只支持 LDAP 认证的系统当中。并且支持保存用户密码到数据库中,以使用与非 LDAP 用户系统不一样的密码数据。
Virtual-LDAP 主要功能有:
- 定时同步钉钉组织架构以及员工信息
- 提供基本 LDAP 功能,包括 bind、search、modify 等操作
- 通过配置文件配置管理账号
- 独立保存用户密码,以 SHA256+Salt 存储
- 支持自定义分组能力,在钉钉组织架构之外扩展用户分组
- 支持自定义用户数据 Provider,可以自行开发接入钉钉以外的用户系统
Virtual-LDAP 主要解决的问题是市面上的 LDAP 服务系统并不支持接入钉钉用户系统,钉钉也并没有提供一个 LDAP 方式的数据源供企业内部使用,因此需要额外的系统去对接钉钉的用户系统,以 LDAP 方式提供用户数据,供 KeyCloak 及其他内部系统使用。
当然,Virtual-LDAP 并不是一个全功能的 LDAP 服务器,它仅支持有限的 LDAP 操作,但是在对接到 KeyCloak 作为 User Federation 已经足够用了,以下功能都可以正常使用:
- User Synchronize
- Group Synchronize
- User 和 Group 的映射关系,以及完整的组织架构
- 在认证时,使用 LDAP bind 进行认证
- 修改密码时,使用 LDAP modify 同步保存密码
通过 Virtual-LDAP,就可以直接由 HR 去管理公司的员工以及组织架构,并且不需要额外再去另外一个系统中同步维护相关信息,Virtual-LDAP 会使用钉钉 OpenAPI 自动从钉钉获取最新的员工列表以及组织架构信息。
4. 部署
对于 KeyCloak 和 Pomerium 来说,官方均已提供 Docker 镜像,因此直接通过 Docker 即可以快速部署使用。
- KeyCloak Docker:https://hub.docker.com/r/jboss/keycloak
- Pomerium Docker:https://hub.docker.com/r/pomerium/pomerium
对于 Virtual-LDAP 来说,可以直接从源代码运行,也可以自己编写一个 Dockerfile 来使用 Docker 部署。
一个典型的 Virtual-LDAP Dockerfile 可以像下面这样:
Dockerfile
FROM node:13.7.0-alpine
WORKDIR /app
COPY package.json /app/
RUN npm install
COPY index.js /app/
COPY config.js /app/
CMD [ "node","index.js" ]
index.js
const server = require('virtual-ldap');
server.setupVirtualLDAPServer(require("./config"));
server.runVirtualLDAPServer();
package.json
{
"dependencies": {
"virtual-ldap": "^0.1.1"
}
}
当然,必需的配置文件 config.js
也是不可少的,具体如何配置可以参考 config.sample.js。
5. 小结
总的来说,如果有额外的人力去维护两份员工信息以及组织架构,只需要 KeyCloak 就可以解决以上很多问题。但是对于小公司来说,使用额外的人力总归不是很高效的方式,并且钉钉拥有更完整的用户系统管理功能,对于 HR 来说使用上可能也更为友好。
希望 Virtual-LDAP 能给同样希望在公司内部部署统一认证系统,以及使用钉钉作为企业交流沟通的朋友们有所帮助。
6. 参考
- https://github.com/ohdarling/virtual-ldap
- https://www.npmjs.com/package/virtual-ldap
- https://www.pomerium.io/
- https://www.keycloak.org/
- https://www.freeipa.org/
- https://ding-doc.dingtalk.com/doc#/bgb96b/ok9au2
- http://ldapjs.org/
- https://directory.apache.org/studio/
- https://www.openldap.org/
- https://hub.docker.com/r/jboss/keycloak
- https://hub.docker.com/r/pomerium/pomerium
—EOF—
近期评论