部署密钥
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
使用部署密钥访问托管在 GitLab 中的仓库。在大多数情况下,您使用部署密钥从外部主机(如构建服务器或持续集成(CI)服务器)访问仓库。
根据您的需求,您可能希望使用部署令牌来访问仓库。
| 属性 | 部署密钥 | 部署令牌 |
|---|---|---|
| 共享 | 可在多个项目间共享,甚至不同组的项目也可共享。 | 属于某个项目或组。 |
| 来源 | 在外部主机上生成的公钥 SSH 密钥。 | 在您的 GitLab 实例上生成,仅在创建时提供给用户。 |
| 可访问资源 | 通过 SSH 访问 Git 仓库 | 通过 HTTP 访问 Git 仓库、包注册表和容器注册表。 |
如果启用了外部授权,则部署密钥不能用于 Git 操作。
范围
部署密钥在创建时具有定义的范围:
- 项目部署密钥:访问权限仅限于所选项目。
- 公共部署密钥:可以授予 GitLab 实例中任何项目的访问权限。每个项目的访问权限必须由至少具有维护者角色的用户授予。
创建部署密钥后,您无法更改其范围。
权限
部署密钥在创建时会被赋予权限级别:
- 只读:只读部署密钥只能从仓库中读取内容。
- 读写:读写部署密钥可以从仓库中读取和写入内容。
创建部署密钥后,您可以更改其权限级别。更改项目部署密钥的权限仅适用于当前项目。
如果使用部署密钥的推送触发了额外的流程,则密钥的创建者必须获得授权。例如:
- 当使用部署密钥向受保护分支推送提交时,部署密钥的创建者必须对该分支有访问权限。
- 当使用部署密钥推送提交触发 CI/CD 管道时,部署密钥的创建者必须有权访问 CI/CD 资源,包括受保护环境和秘密变量。
安全影响
部署密钥旨在促进与 GitLab 的非人交互。例如,您可以使用部署密钥授予对在您组织服务器上自动运行的脚本的权限。
您应该使用服务账户,并使用该服务账户创建部署密钥。如果您使用其他用户账户创建部署密钥,该用户将被授予持续存在的权限,直到部署密钥被撤销。
此外:
- 即使创建部署密钥的用户被从组或项目中移除,部署密钥仍然有效。
- 即使用户被降级或移除,部署密钥的创建者仍保留对组或项目的访问权限。
- 当部署密钥在受保护分支规则中被指定时,部署密钥的创建者:
- 获得对受保护分支以及部署密钥本身的访问权限。
- 如果部署密钥具有读写权限,则可以推送到受保护分支。 即使该分支对所有用户的更改都受到保护,也是如此。
- 如果部署密钥的创建者被阻止或从实例中移除,用户仍然可以从组或项目中拉取更改,但不能推送。
与所有敏感信息一样,您应确保只有需要访问该秘密的人才能读取它。 对于人工交互,请使用与用户绑定的凭据,如个人访问令牌。
为了帮助检测潜在的密钥泄露,您可以使用 审计事件功能。
查看部署密钥
要查看项目可用的部署密钥:
- 在左侧边栏,选择搜索或转到并找到您的项目。
- 选择设置 > 仓库。
- 展开部署密钥。
可用的部署密钥列出如下:
- 已启用的部署密钥:有权访问项目的部署密钥。
- 私有可访问的部署密钥:没有访问权限的项目部署密钥。
- 公共可访问的部署密钥:没有访问权限的公共部署密钥。
GitLab CLI 提供 glab deploy-key list 命令。
创建项目部署密钥
先决条件:
- 您必须至少拥有项目的维护者角色。
- 生成 SSH 密钥对。将私钥 SSH 密钥放在需要访问仓库的主机上。
- 在左侧边栏,选择搜索或转到并找到您的项目。
- 选择设置 > 仓库。
- 展开部署密钥。
- 选择添加新密钥。
- 完成字段填写。
- 可选。要授予读写权限,请选择授予此密钥写入权限复选框。
- 可选。更新过期日期。
项目部署密钥在创建时即启用。您只能修改项目部署密钥的名称和权限。如果部署密钥在多个项目中启用,您无法修改部署密钥名称。
GitLab CLI 提供 glab deploy-key add 命令。
创建公共部署密钥
- Tier: Free, Premium, Ultimate
- Offering: GitLab Self-Managed, GitLab Dedicated
先决条件:
- 您必须拥有实例的管理员访问权限。
- 您必须生成 SSH 密钥对。
- 您必须将私钥 SSH 密钥放在需要访问仓库的主机上。
要创建公共部署密钥:
- 在左侧边栏底部,选择Admin。
- 选择部署密钥。
- 选择新部署密钥。
- 完成字段填写。
- 为名称使用有意义的描述。例如,包括使用公共部署密钥的外部主机或应用程序的名称。
您只能修改公共部署密钥的名称。
向公共部署密钥授予项目访问权限
先决条件:
- 您必须至少拥有项目的维护者角色。
要向公共部署密钥授予项目访问权限:
- 在左侧边栏,选择搜索或转到并找到您的项目。
- 选择设置 > 仓库。
- 展开部署密钥。
- 选择公共可访问的部署密钥。
- 在密钥的行中,选择启用。
- 要向公共部署密钥授予读写权限:
- 在密钥的行中,选择编辑( )。
- 选择授予此密钥写入权限复选框。
编辑部署密钥的项目访问权限
先决条件:
- 您必须至少拥有项目的维护者角色。
要编辑部署密钥的项目访问权限:
- 在左侧边栏,选择搜索或转到并找到您的项目。
- 选择设置 > 仓库。
- 展开部署密钥。
- 在密钥的行中,选择编辑( )。
- 选择或清除授予此密钥写入权限复选框。
撤销部署密钥的项目访问权限
要撤销部署密钥对项目的访问权限,您可以禁用它。任何依赖部署密钥的服务在密钥被禁用后将停止工作。
先决条件:
- 您必须至少拥有项目的维护者角色。
要禁用部署密钥:
- 在左侧边栏,选择搜索或转到并找到您的项目。
- 选择设置 > 仓库。
- 展开部署密钥。
- 选择禁用( )。
禁用密钥后,部署密钥的情况取决于以下因素:
- 如果密钥是公共可访问的,它将从项目中移除,但仍可在公共可访问的部署密钥选项卡中找到。
- 如果密钥是私有可访问的且仅被此项目使用,它将被删除。
- 如果密钥是私有可访问的且也被其他项目使用,它将从项目中移除,但仍可在私有可访问的部署密钥选项卡中找到。
相关主题
- GitLab CLI 部署密钥命令
故障排除
部署密钥无法推送到受保护分支
在某些情况下,部署密钥无法推送到受保护分支。
- 与部署密钥关联的所有者没有对受保护分支项目的成员资格。
- 与部署密钥关联的所有者具有低于查看项目代码要求的项目成员权限。
- 部署密钥没有项目的读写权限。
- 部署密钥已被撤销。
- 在受保护分支的允许推送和合并部分中未选择任何人。
此问题发生是因为所有部署密钥都关联到一个账户。由于账户的权限可能会更改,这可能导致原本工作的部署密钥突然无法推送到受保护分支的情况。
要解决此问题,您可以使用部署密钥 API 为项目服务账户用户创建部署密钥,而不是为您的用户创建:
-
为该服务账户用户创建个人访问令牌。该令牌必须至少具有
api范围。 -
使用部署密钥 API为服务账户用户创建部署密钥:
curl --request POST --header "PRIVATE-TOKEN: <service_account_access_token>" \ --header "Content-Type: application/json" \ --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' \ --url "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
识别与非成员和被阻止用户关联的部署密钥
如果您需要找到属于非成员或被阻止用户的密钥, 您可以使用 Rails 控制台 通过类似以下脚本来识别无法使用的部署密钥:
ghost_user_id = Users::Internal.ghost.id
DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
project = deploy_key_mapping.project
deploy_key = deploy_key_mapping.deploy_key
user = deploy_key.user
access_checker = Gitlab::DeployKeyAccess.new(deploy_key, container: project)
# can_push_for_ref? 测试部署密钥是否可以推送到默认分支,这很可能是受保护的
can_push = access_checker.can_do_action?(:push_code)
can_push_to_default = access_checker.can_push_for_ref?(project.repository.root_ref)
next if access_checker.allowed? && can_push && can_push_to_default
if user.nil? || user.id == ghost_user_id
username = 'none'
state = '-'
else
username = user.username
user_state = user.state
end
puts "Deploy key: #{deploy_key.id}, Project: #{project.full_path}, Can push?: " + (can_push ? 'YES' : 'NO') +
", Can push to default branch #{project.repository.root_ref}?: " + (can_push_to_default ? 'YES' : 'NO') +
", User: #{username}, User state: #{user_state}"
end设置部署密钥的所有者
部署密钥属于特定用户,当用户被阻止或从实例中移除时会被停用。 为了在用户被移除时保持部署密钥正常工作,将其所有者更改为活跃用户。
如果您有部署密钥的指纹,可以使用以下命令更改与部署密钥关联的用户:
k = Key.find_by(fingerprint: '5e:51:92:11:27:90:01:b5:83:c3:87:e3:38:82:47:2e')
k.user_id = User.find_by(username: 'anactiveuser').id
k.save()