搭建多仓库Git服务器:SSH密钥级仓库访问控制技术咨询
多仓库场景下SSH密钥细粒度访问控制实现方案
核心权限模型思路
别再用传统单git用户绑定所有密钥的模式了,得建立密钥-用户-仓库的三级关联关系:
- 每个SSH密钥都归属于具体的用户账号,而非直接绑定到git系统用户
- 用户账号通过角色(比如Owner、Developer、Guest)获得对应仓库的访问权限,密钥自动继承所属用户的仓库权限
- 每个仓库单独维护权限列表,明确哪些用户(及关联密钥)拥有读/写权限
GitLab这类产品的典型实现方式
1. SSH代理层做前置校验
GitLab并没有让git系统用户直接处理SSH请求,而是用自定义的gitlab-shell作为代理:
- 用户发起SSH git操作时,先由这个代理服务接住请求,解析出目标仓库路径、客户端提供的公钥
- 代理服务查询后端权限数据库:先通过公钥匹配到对应的用户,再验证该用户是否拥有目标仓库的访问权限
- 只有校验通过,才把请求转发给真正的git进程执行操作
2. 密钥与用户绑定存储
所有用户上传的SSH密钥都存在数据库中,和用户ID关联,同时记录备注、有效期等信息。当SSH请求过来时,先通过公钥找到对应的用户,再检查用户对请求仓库的权限,而非直接依赖authorized_keys文件管理。
3. 定制git-shell限制操作
就算使用git系统用户,也会通过定制git-shell的命令白名单来限制操作:
- 拦截
git-receive-pack(对应推送)、git-upload-pack(对应拉取)这些核心git命令 - 在执行命令前先做权限校验,只有用户有权限操作目标仓库时,才允许命令执行
可落地的技术实现路径
- 自定义SSH服务:用Go、Python这类语言实现一个SSH server,监听22端口(或自定义端口)。处理连接时先验证客户端公钥,解析出要操作的仓库路径,查询权限系统确认有权限后,再调用git命令完成操作。
- 数据库表结构设计:
users:存储用户基础信息ssh_keys:存储公钥内容、关联的用户ID、备注、有效期repositories:存储仓库路径、归属者等信息user_repo_permissions:存储用户与仓库的权限映射(读/写/管理员)
- 封装git命令:对
git clone、push等操作做一层封装,执行前先触发权限校验逻辑,无权限则直接拒绝。
关键注意点
- 绝对不要直接将密钥写入
~/.ssh/authorized_keys,这种方式无法实现细粒度控制,必须通过中间代理层做校验 - 权限校验要覆盖所有SSH触发的git操作,包括拉取、推送、子模块更新等场景
- 定期清理失效密钥,比如用户删除的、过期的密钥,避免出现权限泄露问题
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

