IAM项目介绍
从零构建云原生 IAM:sup-iam 的设计与实践
前言
在微服务架构日益普及的今天,身份识别与访问管理(IAM) 已经成为基础设施中不可或缺的一环。无论是内部系统之间的服务调用,还是对外提供 API 给第三方开发者,都需要一套可靠的认证与授权机制来保证安全。
市面上虽然有 AWS IAM、阿里云 RAM 等商业方案,但它们与特定云平台绑定,无法在私有化部署场景中使用。开源的 IAM 方案中,Keycloak 等功能全面但过于重量级,不适合嵌入到微服务体系中使用。
因此,我们决定从零构建 sup-iam——一个轻量级、云原生的 IAM 系统,专为微服务架构设计。
什么是 sup-iam?
sup-iam 是一个用 Go 语言编写的身份识别与访问管理系统,为第三方用户及其程序化客户端提供统一的身份认证、密钥管理和基于 ACL 的访问控制能力。
简单来说,它解决的核心问题是:谁(Who)能以什么方式(How)访问什么资源(What)。
架构设计理念
控制面与数据面分离
这是 sup-iam 最核心的架构决策。参考了 AWS IAM 和服务网格(如 Istio)的设计思想,我们将系统拆分为两个层面:
- 控制面(Control Plane):负责管理身份、密钥、策略等元数据。这些操作频率低,但对一致性要求高。
- 数据面(Data Plane):负责处理实际的鉴权请求。这些请求频率极高,必须低延迟、高吞吐、高可用。
这两个面分开部署、独立扩缩,控制面的故障不影响数据面的鉴权服务,数据面的高负载也不会拖慢管理操作。
设计原则
- 无状态鉴权:数据面不保存任何用户登录状态,可以随意水平扩展
- 最小权限:默认拒绝所有请求,仅显式授权才放行
- 可审计:每一次鉴权决策都有日志可查
- 最终一致性:缓存与数据库允许秒级不一致,换取极致的读性能
系统概览
sup-iam 由三个核心服务和三个存储组件构成:
1 | ┌──────────────────┐ |
iam-api-server — 控制面核心
iam-api-server 是管理员与 IAM 系统交互的入口,提供 RESTful API 来管理所有资源:
- User 管理:注册、登录、密码修改、JWT Token 管理
- Secret 管理:创建 AK/SK(Access Key / Secret Key),支持密钥轮换
- Policy 管理:使用 Casbin DSL 定义访问策略
- Binding 管理:将 Secret 与 Policy 进行多对多绑定
- 审计查询:查看策略变更和绑定变更的历史记录
架构上采用经典的分层设计:Model → Controller → Service → Repository,每一层职责清晰,便于测试和维护。
iam-auth-server — 数据面鉴权
这是整个系统最核心的服务,处理每一个鉴权请求。它的工作流程如下:
1 | Client → Resource Server → iam-auth-server |
签名校验使用 HMAC-SHA256 算法,客户端用 Secret Key 对请求参数生成签名,服务端重新计算并比对。同时引入时间戳校验来防止重放攻击,默认允许 ±300 秒的时钟误差。
策略评估使用 Casbin 引擎的 ACL 模型,每条策略描述 “谁(sub) 可以对什么资源(obj) 做什么操作(act)”,简单且够用。
性能优化是最值得介绍的部分。如果每次鉴权都去数据库或远程服务查询密钥和策略,延迟和吞吐都无法满足生产要求。解决方案是全量本地缓存——iam-auth-server 在启动时将所有的 Secret 和 Policy 数据加载到本地内存(使用 Dgraph 的 Ristretto 缓存库)中,鉴权时直接从内存读取,零网络开销。
当控制面数据发生变更时,iam-api-server 通过 Redis Pub/Sub 发送变更通知,iam-auth-server 收到通知后异步重新拉取全量数据,通过原子替换的方式更新缓存实例,保证读取路径不产生任何锁竞争。
最终一致性窗口控制在秒级,对于鉴权场景完全可以接受。
iam-pump — 数据采集
鉴权日志的生产和消费必须解耦。iam-auth-server 将决策日志异步写入 Redis List,iam-pump 从 Redis 消费并转存到 MongoDB。这样做的好处:
- 鉴权主流程不被日志写入阻塞
- 使用 Redis 作为缓冲层,应对日志峰值流量
- 多副本部署时通过 Redlock 分布式锁保证不重复消费
- 每条日志设置 TTL,防止消费方故障导致 Redis OOM
Pump 采用插件化架构,当前内置 MongoPump 实现,未来可以扩展写入 Elasticsearch、ClickHouse 等。
技术栈
| 类别 | 选型 | 理由 |
|---|---|---|
| 语言 | Go 1.25+ | 高性能、并发友好、编译部署简单 |
| Web 框架 | Gin | 性能好、生态成熟、社区活跃 |
| ORM | GORM + MySQL | 完善的 Go ORM,支持钩子、自动迁移 |
| 本地缓存 | Ristretto | Dgraph 出品,高并发下性能优异 |
| 远程缓存 | Redis | 缓冲、Pub/Sub、分布式锁一站式解决 |
| 策略引擎 | Casbin | 功能强大,支持多种访问控制模型 |
| 日志 | Zap | 零反射、高性能,支持 V Level |
| 序列化 | Protobuf / Msgpack | 高效的二进制传输与存储 |
| 部署 | Docker + Helm | 标准的云原生交付方式 |
数据模型
系统围绕三个核心实体展开:
1 | User ──1:N──> Secret ──M:N──> Policy |
- User:控制面的登录用户
- Secret:包含 Access Key + Secret Key,用于程序化访问
- Policy:用 Casbin DSL 描述的权限规则
- Binding:Secret 与 Policy 的多对多关联(一个 Secret 最多绑定 100 条策略)
所有敏感操作都有对应的审计表,只写不改,记录每一次变更的完整快照。
部署方式
我们选择了云原生社区最主流的部署方案:
- 基础设施:MySQL(Bitnami Chart)、Redis Cluster(Bitnami Chart)、MongoDB(Bitnami Chart)
- IAM 服务:通过自定义的 Helm Chart 部署,包含三个 Deployment 和对应的 Service
- 镜像仓库:推送到 GitHub Container Registry (ghcr.io)
- 配置管理:Kubernetes ConfigMap 管理配置文件,Secrets 管理敏感信息
一条命令部署所有基础设施和 IAM 服务:
1 | make helm-mysql-install && make helm-redis-install && make helm-mongodb-install && make helm-iam-install |
总结
sup-iam 虽然还在活跃开发中,但其架构设计已经经过了多轮推演和迭代。回顾整个设计过程,有几个关键决策值得分享:
控制面与数据面分离是用于支撑高并发鉴权的最关键架构决策,虽然增加了系统复杂度,但换来了可独立扩缩容、故障隔离、按需部署的灵活性。
全量本地缓存是对性能问题的根本解法。与其优化远程查询的延迟,不如彻底消除远程查询。
异步日志流水线保证了核心鉴权路径不被日志 I/O 拖累,同时通过插件化 Pump 架构保留了日志后端存储的灵活性。
选择 Go 语言是对运维体验的考量。单二进制部署、零依赖、低资源占用,让 IAM 可以轻松嵌入到任何规模的微服务体系中。
如果你也在构建或寻找一个轻量级的 IAM 方案,欢迎关注 sup-iam 项目,一起交流学习。