使用 SSH 密钥与极狐GitLab 通信

Git 是一个分布式版本控制系统,这意味着您可以在本地工作,然后将您的更改共享或推送到服务器。在这种情况下,服务器是极狐GitLab。

极狐GitLab 使用 SSH 协议来安全地与 Git 通信。当您使用 SSH 密钥对 GitLab 远程服务器进行身份验证时,您无需每次都提供用户名和密码。

先决条件

要使用 SSH 与极狐GitLab 通信,您需要:

  • OpenSSH 客户端,预装在 GNU/Linux、macOS 和 Windows 10 上。
  • SSH 6.5 或更高版本。早期版本使用 MD5 签名,这是不安全的。

要查看系统上安装的 SSH 版本,请运行 ssh -V

支持的 SSH 密钥类型

要与极狐GitLab 通信,您可以使用以下 SSH 密钥类型:

管理员可以限制允许使用哪些密钥及其最小长度。

ED25519 SSH 密钥

Practical Cryptography With Go 一书表明 ED25519 密钥比 RSA 密钥更安全、更高效。

OpenSSH 6.5 在 2014 年引入了 ED25519 SSH 密钥,它们应该可以在大多数操作系统上使用。

ED25519_SK SSH 密钥

引入于 14.8 版本。

要在极狐GitLab 上使用 ED25519_SK SSH 密钥,您的本地客户端和 GitLab 服务器必须安装 OpenSSH 8.2 或更高版本。

ECDSA_SK SSH 密钥

引入于 14.8 版本。

要在极狐GitLab 上使用 ECDSA_SK SSH 密钥,您的本地客户端和 GitLab 服务器必须安装 OpenSSH 8.2 或更高版本。

RSA SSH 密钥

可用文档表明 ED25519 比 RSA 更安全。

如果您使用 RSA 密钥,美国国家科学技术研究院 Publication 800-57 Part 3 (PDF) 建议密钥大小至少为 2048 位。默认密钥大小取决于您的 ssh-keygen 版本。有关详细信息,请查看已安装的 ssh-keygen 命令的手册页。

查看您是否已有 SSH 密钥对

在创建密钥对之前,请查看密钥对是否已存在。

  1. 在 Windows、Linux 或 macOS 上,转到您的主目录。
  2. 进入.ssh/ 子目录。如果 .ssh/ 子目录不存在,您可能不在主目录中,或者可能之前没有使用过 ssh。在后一种情况下,您需要生成 SSH 密钥对
  3. 查看是否存在以下格式之一的文件:

    算法 公钥 私钥
    ED25519 (首选) id_ed25519.pub id_ed25519
    ED25519_SK id_ed25519_sk.pub id_ed25519_sk
    ECDSA_SK id_ecdsa_sk.pub id_ecdsa_sk
    RSA (至少 2048 位密钥大小) id_rsa.pub id_rsa
    DSA (废弃) id_dsa.pub id_dsa
    ECDSA id_ecdsa.pub id_ecdsa

生成 SSH 密钥对

如果您没有现有的 SSH 密钥对,请生成一个新的。

  1. 打开一个终端。
  2. 输入 ssh-keygen -t,然后输入密钥类型和可选注释。此注释包含在创建的 .pub 文件中。您可能希望在注释中使用电子邮件地址。

    例如,对于 ED25519:

    ssh-keygen -t ed25519 -C "<comment>"
    

    对于 2048 位 RSA:

    ssh-keygen -t rsa -b 2048 -C "<comment>"
    
  3. Enter。将显示类似于以下内容的输出:

    Generating public/private ed25519 key pair.
    Enter file in which to save the key (/home/user/.ssh/id_ed25519):
    
  4. 接受建议的文件名和目录,除非您正在生成部署密钥,或想要保存在存储其他密钥的特定目录中。

您还可以将 SSH 密钥对专用于特定主机

  1. 指定密码

    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    
  2. 将显示确认信息,包括有关文件存储位置的信息。

生成公钥和私钥。将公共 SSH 密钥添加到您的极狐GitLab 帐户,并确保私钥安全。

配置 SSH 以指向不同的目录

如果您没有将 SSH 密钥对保存在默认目录中,请将您的 SSH 客户端配置为指向存储私钥的目录。

  1. 打开终端并运行以下命令:

    eval $(ssh-agent -s)
    ssh-add <directory to private SSH key>
    
  2. 将这些设置保存在 ~/.ssh/config 文件中。 例如:

    # GitLab.com
    Host gitlab.com
      PreferredAuthentications publickey
      IdentityFile ~/.ssh/gitlab_com_rsa
    
    # Private GitLab instance
    Host gitlab.company.com
      PreferredAuthentications publickey
      IdentityFile ~/.ssh/example_com_rsa
    

有关这些设置的更多信息,请参阅 SSH 配置手册中的 man ssh_config 页面。

公共 SSH 密钥对于极狐GitLab 必须是唯一的,因为它们绑定到您的帐户。当您使用 SSH 推送代码时,您的 SSH 密钥是您拥有的唯一标识符。它必须唯一地映射到单个用户。

更新您的 SSH 密钥密码

您可以更新 SSH 密钥的密码。

  1. 打开终端并运行以下命令:

    ssh-keygen -p -f /path/to/ssh_key
    
  2. 在出现提示时,输入密码并按 Enter

将您的 RSA 密钥对升级为更安全的格式

如果您的 OpenSSH 版本介于 6.5 和 7.8 之间,您可以以更安全的 OpenSSH 格式保存您的私有 RSA SSH 密钥。

  1. 打开终端并运行以下命令:

    ssh-keygen -o -f ~/.ssh/id_rsa
    

    或者,您可以使用以下命令生成具有更安全加密格式的新 RSA 密钥:

    ssh-keygen -o -t rsa -b 4096 -C "<comment>"
    

为 FIDO/U2F 硬件安全密钥生成 SSH 密钥对

要生成 ED25519_SK 或 ECDSA_SK SSH 密钥,您必须使用 OpenSSH 8.2 或更高版本。

  1. 将硬件安全密钥插入您的计算机。
  2. 打开终端。
  3. 键入 ssh-keygen -t 后跟密钥类型和可选注释。此注释包含在创建的 .pub 文件中。您可能希望使用电子邮件地址发表评论。

    例如,对于 ED25519_SK:

    ssh-keygen -t ed25519-sk -C "<comment>"
    

    对于 ECDSA_SK:

    ssh-keygen -t ecdsa-sk -C "<comment>"
    

    如果您的安全密钥支持 FIDO2 常驻密钥,您可以在创建 SSH 密钥时启用此功能:

    ssh-keygen -t ed25519-sk -O resident -C "<comment>"
    

    -O resident 表示密钥应该存储在 FIDO 身份验证器本身上。 常驻密钥更容易导入到新计算机,因为它可以通过 ssh-add -Kssh-keygen -K 直接从安全密钥加载。

  4. 选择 Enter。显示类似于以下的输出:

    Generating public/private ed25519-sk key pair.
    You may need to touch your authenticator to authorize key generation.
    
  5. 触摸硬件安全密钥上的按钮。

  6. 接受建议的文件名和目录:

    Enter file in which to save the key (/home/user/.ssh/id_ed25519_sk):
    
  7. 指定密码

    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    
  8. 将显示确认信息,包括有关文件存储位置的信息。

生成公钥和私钥。将公共 SSH 密钥添加到您的极狐GitLab 帐户。

将 SSH 密钥添加到您的极狐GitLab 帐户

引入于 15.4 版本,UI 中提供建议默认到期日期。

要将 SSH 与极狐GitLab 结合使用,请将您的公钥复制到您的极狐GitLab 帐户。

  1. 复制公钥文件的内容。您可以手动执行此操作或使用脚本。例如,要将 ED25519 密钥复制到剪贴板:

    macOS:

    tr -d '\n' < ~/.ssh/id_ed25519.pub | pbcopy
    

    Linux (需要 xclip 包):

    xclip -sel clip < ~/.ssh/id_ed25519.pub
    

    Git Bash on Windows:

    cat ~/.ssh/id_ed25519.pub | clip
    

    id_ed25519.pub 替换为您的文件名。例如,对 RSA 使用 id_rsa.pub

  2. 登录极狐GitLab。
  3. 在顶部栏的右上角,选择您的头像。
  4. 选择 偏好设置
  5. 在左侧边栏上,选择SSH 密钥
  6. 密钥 框中,粘贴公钥的内容。如果您手动复制密钥,请确保复制整个密钥,以ssh-rsassh-dssecdsa-sha2-nistp256ecdsa-sha2-nistp384ecdsa-sha2-nistp521ssh-ed25519sk-ecdsa-sha2-nistp256@openssh.com,或 sk-ssh-ed25519@openssh.com 开头,并可能以注释结尾。
  7. 标题 框中,输入说明,例如 “Work Laptop” 或 “Home Workstation”。
  8. 可选。更新到期日期以修改默认到期日期。

    • 对于 13.12 及更早版本,到期日期仅供参考。它不会阻止您使用密钥。管理员可以查看到期日期并在删除密钥时作为指导。
    • 每天 02:00 AM UTC 检查所有 SSH 密钥。通过电子邮件发送所有在当前日期到期的 SSH 密钥的到期通知。(引入于 13.11 版本)
    • 每天 01:00 AM UTC 检查所有 SSH 密钥。通过电子邮件发送所有计划在 7 天后到期的 SSH 密钥的到期通知。(引入于 13.11 版本)
  9. 选择 添加密钥

验证您是否可以连接

验证您的 SSH 密钥是否已正确添加。

  1. 打开终端并运行此命令,将 gitlab.example.com 替换为您的实例 URL:

    ssh -T git@gitlab.example.com
    
  2. 如果这是您第一次连接,您应该验证 GitLab 主机的真实性。如果您看到如下消息:

    The authenticity of host 'gitlab.example.com (35.231.145.151)' can't be established.
    ECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'gitlab.example.com' (ECDSA) to the list of known hosts.
    

    输入 yes,然后按 Enter

  3. 再次运行 ssh -T git@gitlab.example.com 命令。您应该会收到 Welcome to GitLab, @username! 消息。

如果没有出现欢迎消息,您可以通过在详细模式下运行 ssh 来进行故障排除:

ssh -Tvvv git@gitlab.example.com

对不同的仓库使用不同的密钥

您可以为每个仓库使用不同的密钥。

打开终端并运行以下命令:

git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-filename-for-this-repository -F /dev/null"

此命令不使用 SSH 代理,需要 Git 2.10 或更高版本。有关 ssh 命令选项的更多信息,请参阅 sshssh_configman 页。

在单个实例上使用不同的帐户

您可以使用多个帐户连接到 GitLab 的单个实例。 您可以使用前一节中的命令来执行此操作。但是,即使您将 IdentitiesOnly 设置为 yes,如果 IdentityFile 存在于 Host 块之外,您也无法登录。

相反,您可以在 ~/.ssh/config 文件中为主机分配别名。

  • 对于 Host,使用像 user_1.jihulab.comuser_2.jihulab.com 这样的别名。高级配置更难维护,当使用像 git remote这样的工具时,这些字符串更容易理解。
  • 对于 IdentityFile,使用私钥的路径。
# User1 Account Identity
Host <user_1.jihulab.com>
  Hostname jihulab.com
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/<example_ssh_key1>

# User2 Account Identity
Host <user_2.jihulab.com>
  Hostname jihulab.com
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/<example_ssh_key2>

现在,要为 user_1 克隆仓库,请在 git clone 命令中使用 user_1.jihulab.com

git clone git@<user_1.jihulab.com>:gitlab-cn/gitlab.git

要更新别名为 origin 的先前克隆的存储库:

git remote set-url origin git@<user_1.gitlab.com>:gitlab-org/gitlab.git
note私钥和公钥包含敏感数据。 确保文件的权限使您可以读取但其他人无法访问。

配置双重认证(2FA)

您可以为 Git over SSH 设置双因素身份验证 (2FA)。我们建议使用 ED25519_SKECDSA_SK SSH 密钥。

在 Eclipse 上使用 EGit

如果您使用 EGit,您可以将您的 SSH 密钥添加到 Eclipse

在 Microsoft Windows 上使用 SSH

如果您运行的是 Windows 10,则可以将 Windows Subsystem for Linux (WSL) 与预装了 gitsshWSL 2 一起使用 ,或者安装 Git for Windows,通过 Powershell 使用 SSH。

WSL 中生成的 SSH 密钥不能直接用于 Windows 版 Git,反之亦然,因为两者都有不同的主目录:

  • WSL: /home/<user>
  • Git for Windows: C:\Users\<user>

您可以复制 .ssh/ 目录以使用相同的密钥,也可以在每个环境中生成一个密钥。

如果您运行的是 Windows 11 并使用 OpenSSH for Windows,请确保 HOME 环境变量设置正确。否则,可能找不到您的私有 SSH 密钥。

替代工具包括:

覆盖 GitLab 服务器上的 SSH 设置

极狐GitLab 与系统安装的 SSH 守护进程集成,并指定一个用户(通常名为“git”),通过该用户处理所有访问请求。通过 SSH 连接到 GitLab 服务器的用户由其 SSH 密钥而不是用户名标识。

在 GitLab 服务器上执行的 SSH 客户端操作以此用户身份执行。您可以修改此 SSH 配置。例如,您可以为此用户指定用于身份验证请求的私有 SSH 密钥。但是,这种做法不受支持,强烈建议不要这样做,因为它会带来重大的安全风险。

系统会检查这种情况,例如:

$ gitlab-rake gitlab:check

Git user has default SSH configuration? ... no
  Try fixing it:
  mkdir ~/gitlab-check-backup-1504540051
  sudo mv /var/lib/git/.ssh/id_rsa ~/gitlab-check-backup-1504540051
  sudo mv /var/lib/git/.ssh/id_rsa.pub ~/gitlab-check-backup-1504540051
  For more information see:
  doc/user/ssh.md#overriding-ssh-settings-on-the-gitlab-server
  Please fix the error above and rerun the checks.

尽快删除自定义配置。这些自定义设置明确不受支持,并且可能随时停止工作。

故障排查

使用 git clone 提示密码

当您运行 git clone 时,可能会提示输入密码,比如 git@gitlab.example.com's password:。这表明您的 SSH 设置有问题。

  • 确保您正确生成了 SSH 密钥对,并将公共 SSH 密钥添加到您的 GitLab 配置文件中。
  • 尝试使用 ssh-agent 手动注册您的私有 SSH 密钥。
  • 尝试通过运行 ssh -Tv git@example.com 来调试连接。用您的 GitLab URL 替换 example.com
  • 确保您遵循在 Microsoft Windows 上使用 SSH 中的所有说明。

Could not resolve hostname 错误

验证是否可以连接时,您可能会收到以下错误:

ssh: Could not resolve hostname gitlab.example.com: nodename nor servname provided, or not known

如果您收到此错误,请重新启动终端并再次尝试该命令。

Key enrollment failed: invalid format 错误

为 FIDO/U2F 硬件安全密钥生成 SSH 密钥对时,您可能会收到以下错误:

Key enrollment failed: invalid format

您可以通过尝试以下方法来解决此问题:

  • 使用 sudo 运行 ssh-keygen 命令。
  • 验证您的 IDO/U2F 硬件安全密钥是否支持所提供的密钥类型。
  • 通过运行 ssh -v 验证 OpenSSH 的版本是 8.2 或更高版本。