使用 SSH 密钥身份验证

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

可以通过 macOS、Linux 或 Windows 上的 SSH 连接到 Git 存储库,以安全地连接到 Azure DevOps。

重要

SSH URL 已更改,但旧的 SSH URL 将继续工作。 如果已设置 SSH,请将远程 URL 更新为新格式:

最新的 SSH URL 以 ssh.dev.azure.com 开头。 先前的 URL 使用 vs-ssh.visualstudio.com

  • 验证哪些远程正在使用 SSH。 在 shell 中运行 git remote -v 或者改为使用 GUI 客户端。
  • 访问 Web 上的存储库并选择“克隆”。
  • 选择 SSH 并复制新的 SSH URL。
  • 在 shell 中,针对要更新的每个存储库的远程库运行 git remote set-url <remote name> <new SSH URL>。 或者,使用 GUI 客户端更新远程 URL。

先决条件

类别 要求
权限 对克隆存储库的访问权限
策略 已启用 SSH 身份验证

SSH 密钥身份验证的工作原理

SSH 公钥身份验证使用生成的加密密钥的非对称对。 钥与 Azure DevOps 共享,用于验证初始 SSH 连接。 钥在系统上保持安全。

设置 SSH 密钥身份验证

以下步骤介绍了在以下平台上使用命令行(也称为 shell)配置 SSH 密钥身份验证:

提示

在 Windows 上,我们建议使用 Git 凭据管理器 而不是 SSH。

步骤 1:创建 SSH 密钥

注意

如果已在系统上创建了 RSA SSH 密钥,请跳过此步骤并配置 SSH 密钥。 若要验证这一点,请转到主目录并查看 .ssh 文件夹(在 Windows 上为 %UserProfile%\.ssh\,在带有 Git Bash 的 Linux、macOS 和 Windows 上为 ~/.ssh/)。 如果看到两个分别名为 id_rsaid_rsa.pub 的文件,请继续配置 SSH 密钥

若要使用基于密钥的身份验证,首先需要为客户端生成公钥/私钥对。 ssh-keygen.exe 用于生成密钥文件,可以指定 DSA、RSA、ECDSA 或 Ed25519 算法。 如果未指定算法,则使用 Ed25519。

注意

Azure DevOps 支持的唯一 SSH 密钥类型是 RSA。

若要使用 Azure DevOps 支持的 RSA 算法(RSA-SHA2-256 或 RSA-SHA2-512)生成密钥文件,请在客户端上从 PowerShell 或其他 shell(如 bash)运行以下命令之一:

ssh-keygen -t rsa-sha2-256

ssh-keygen -t rsa-sha2-512

命令的输出应显示如下内容(其中 username 表示你的用户名):

Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\username/.ssh/id_rsa):

你可以按 Enter 来接受默认值,或指定要在其中生成密钥的路径和/或文件名。 此时,系统会提示你使用密码来加密你的私钥文件。 通行短语可以为空,但不建议这样做。 将密码与密钥文件一起使用来提供双因素身份验证。

Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\username/.ssh/id_rsa.
Your public key has been saved in C:\Users\username/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:FHK6WjcUkcfQjdorarzlak1Ob/x7AmqQmmx5ryYYV+8 username@LOCAL-HOSTNAME
The key's randomart image is:
+---[RSA 3072]----+
|      . ** o     |
|       +.o= .    |
|      . o+       |
|      .+. .      |
|     .ooS  .     |
|  . .oo.=.o      |
|   =.= O.= .     |
|  . B BoE + . .  |
|   . *+*o. .o+   |
+----[SHA256]-----+

现在,在指定的位置中有一个公共/专用 RSA 密钥对。 .pub 文件是公钥,没有扩展名的文件是私钥:

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        10/11/2022   6:29 PM           2610 id_rsa
-a----        10/11/2022   6:29 PM            578 id_rsa.pub

重要

切勿共享私钥的内容。 如果私钥已泄露,攻击者可以使用它来欺骗服务器认为连接来自你。 私钥文件等效于密码,应以相同的方式进行保护。

步骤 2:将公钥添加到 Azure DevOps

将上一步中生成的公钥与用户 ID 相关联。

注意

对于你有权访问且想要对其使用 SSH 的每个组织,必须重复此操作。

  1. 浏览到 Web 门户,并选择用户界面右上角的头像旁边的图标来打开安全设置。 在显示的菜单中选择 SSH 公钥

    显示 SSH 公钥菜单项以及在 Azure DevOps 中所选用户头像的屏幕截图。

  2. 选择 + 新建密钥

    显示对 Azure DevOps 中“安全配置”进行访问的屏幕截图。

  3. 将生成的公钥(例如 id_rsa.pub)的内容复制到“公钥数据”字段中。

    重要

    不要在“密钥数据”字段中添加空格或换行符,它们可能会导致 Azure DevOps 使用无效的公钥。 粘贴密钥时,通常会在末尾添加换行符。 如果出现此换行符,请务必将其删除。

    显示在 Azure DevOps 中配置公钥的屏幕截图。

  4. 为密钥提供一个有用的说明(此说明将显示在配置文件的“SSH 公钥”页上),方便在以后记起密码。 选择保存以存储公钥。 密钥一旦保存就无法更改。 可以删除密钥,也可以为另一个密钥创建新条目。 可以添加到用户配置文件的密钥数没有限制。

    注意

    Azure DevOps 中存储的 SSH 密钥在一年后过期,除非已设置组织级别策略。 有关详细信息,请参阅 更改组织的应用程序连接 & 安全策略

  5. SSH 公钥概述页上,会显示服务器指纹。 记下首次通过 SSH 连接到 Azure DevOps 时要使用的 SHA256 指纹。

    在 Azure DevOps Services 中访问安全配置的屏幕截图。

  6. 通过运行以下命令来测试连接:

    ssh -T git@ssh.dev.azure.com
    

    如果这是第一次连接,应该会收到以下输出:

    The authenticity of host 'ssh.dev.azure.com (<IP>)' can't be established.
    RSA key fingerprint is SHA256:ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og.
    This key is not known by any other names
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    将指纹与前面提到的 SSH 公钥页上显示的 SHA256 指纹进行比较。 只在两者匹配时才继续!

  7. 输入 yes 继续。 如果正确配置了所有内容,输出应如下所示:

     Warning: Permanently added 'ssh.dev.azure.com' (RSA) to the list of known hosts.
     remote: Shell access is not supported.
     shell request failed on channel 0
    

    如果没有,请参阅有关问题和故障排除的部分。

步骤 3:通过 SSH 克隆 Git 存储库

注意

若要将 SSH 与以前通过 HTTPS 克隆的存储库配合使用,请参阅将远程库更新为 SSH

  1. 从 Web 门户复制 SSH 克隆 URL。 在此示例中,SSH 克隆 URL 用于组织中名为 fabrikam-fiber 的存储库,如 dev.azure.com 后面的 URL 第一部分所示。

    显示 Azure Repos SSH 克隆 URL 的屏幕截图。

    注意

    使用 Azure DevOps Services 时,项目 URL 的格式为 dev.azure.com/{your organization}/{your project}。 但是,引用 visualstudio.com 格式的旧格式仍然受到支持。 有关详细信息,请参阅 Azure DevOps 简介 - 将现有组织切换为使用新的域名 URL

  2. 通过命令提示符运行 git clone

    git clone git@ssh.dev.azure.com:v3/fabrikam-fiber/FabrikamFiber/FabrikamFiber
    

    如果未使用 SSH 代理,系统会提示输入通行短语:

    Cloning into 'FabrikamFiber'...
    Enter passphrase for key '/c/Users/username/.ssh/id_rsa':
    remote: Azure Repos
    remote: Found 127 objects to send. (50 ms)
    Receiving objects: 100% (127/127), 56.67 KiB | 2.58 MiB/s, done.
    Resolving deltas: 100% (15/15), done.
    

    如果系统转而提示你验证指纹,请再次阅读步骤 2:将公钥添加到 Azure DevOps。 有关其他问题,请阅读有关问题和故障排除的部分。

提示

要充分利用 SSH,常见的方法是使用 SSH 代理来管理 SSH 密钥。 不过,设置代理不在本文讲解范围内。

问题和故障排除

问:我的 SSH 密钥已过期,我该怎么办?

A:建议的行动方案是按照上述步骤创建和上传新的SSH密钥

作为替代选项,项目集合管理员可以禁用验证 SSH 密钥到期日期的策略。 默认情况下,已启用“验证 SSH 密钥过期策略”。 有关详细信息,请参阅 SSH 密钥策略

7 天前以及密钥过期时,你会自动收到通知。 除了这些通知,还可以看到以下消息:

remote: Authentication failed: your SSH key has expired. To restore access, visit https://aka.ms/ado-ssh-public-key-expired for guidance.
remote: Public key authentication failed.
fatal:  Could not read from remote repository.

答:你可能会看到两种不同的警告信息:

ssh-rsa is about to be deprecated and your request has been throttled. Please use rsa-sha2-256 or rsa-sha2-512 instead. Your session will continue automatically. For more details see https://devblogs.microsoft.com/devops/ssh-rsa-deprecation.

You’re using ssh-rsa that is about to be deprecated and your request has been blocked intentionally. Any SSH session using ssh-rsa is subject to brown out (failure during random time periods). Please use rsa-sha2-256 or rsa-sha2-512 instead. For more details see https://devblogs.microsoft.com/devops/ssh-rsa-deprecation.

如果修改了 SSH 配置,通过将以下内容添加到 ~/.ssh/config(在 Windows 中为 %UserProfile%\.ssh\config)文件,以降级 Azure DevOps 的安全设置:

Host ssh.dev.azure.com vs-ssh.visualstudio.com
  HostkeyAlgorithms +ssh-rsa

请立即删除这些行,并确保允许 rsa-sha2-256 和/或 rsa-sha2-512

有关详细信息,请参阅博客文章

问:SSH 无法建立连接。 我该怎么办?

答:你可能会遇到多种不同的问题:

  • 使用不受支持的 ssh-rsa

    You’re using ssh-rsa that is unsupported. Please use rsa-sha2-256 or rsa-sha2-512 instead. For more details see https://devblogs.microsoft.com/devops/ssh-rsa-deprecation.
    

    如果修改了 SSH 配置,通过将以下内容添加到 ~/.ssh/config(在 Windows 中为 %UserProfile%\.ssh\config)文件,以降级 Azure DevOps 的安全设置:

    Host ssh.dev.azure.com vs-ssh.visualstudio.com
       HostkeyAlgorithms +ssh-rsa
    

    请立即删除这些行,并确保允许 rsa-sha2-256 和/或 rsa-sha2-512

    有关详细信息,请参阅博客文章

  • 没有匹配的主机密钥

    博客文章所述,这种问题既不会发生在 Azure DevOps 服务上,也不会发生在最新的 Azure DevOps Server 版本上。

    Unable to negotiate with <IP> port 22: no matching host key type found. Their offer: ssh-rsa
    

    将以下内容添加到 ~/.ssh/config 文件(在 Windows 中为 %UserProfile%\.ssh\config 文件)以修改 SSH 配置,从而降低 Azure DevOps 的安全级别设置。

    Host ssh.dev.azure.com vs-ssh.visualstudio.com
       HostkeyAlgorithms +ssh-rsa
    

    重要

    OpenSSH 在ssh-rsa 中弃用了 公钥签名算法,并在版本 8.8 中默认禁用了该算法。

  • 没有匹配的 MAC

    Unable to negotiate with <IP> port 22: no matching MAC found. Their offer: hmac-sha2-256,hmac-sha2-512
    

    将以下内容添加到 ~/.ssh/config 文件(在 Windows 中为 %UserProfile%\.ssh\config 文件)以修改 SSH 配置,从而降低 Azure DevOps 的安全级别设置。

    Host ssh.dev.azure.com vs-ssh.visualstudio.com
       MACs +hmac-sha2-512,+hmac-sha2-256
    
  • 没有匹配的密钥交换方法

    Unable to negotiate with <IP> 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256
    

    将以下内容添加到 ~/.ssh/config 文件(在 Windows 中为 %UserProfile%\.ssh\config 文件)以修改 SSH 配置,从而降低 Azure DevOps 的安全级别设置。

    Host ssh.dev.azure.com vs-ssh.visualstudio.com
       KexAlgorithms +diffie-hellman-group-exchange-sha256,+diffie-hellman-group14-sha1,+diffie-hellman-group1-sha1
    

    重要

    在 OpenSSH diffie-hellman-group1-sha1版本 8.2 中,密钥交换算法 diffie-hellman-group14-sha1 默认被禁用。

提示

对于 Azure DevOps Server 和 TFS 的自承载实例,请使用 Host 行中的相应主机名,而不是 ssh.dev.azure.com vs-ssh.visualstudio.com

问:如何让 Git 记住我的密钥的密码?

答:可以使用 SSH 代理。 Linux、macOS 和 Windows(从 Windows 10 [内部版本 1809] 开始或通过将 Git for Windows 与 Git Bash 配合使用)均随 SSH 代理一起提供。 SSH 代理可用于缓存 SSH 密钥以供重复使用。 若要详细了解它的使用方式,请参阅 SSH 供应商的手册。

问:我使用 PuTTY 作为 SSH 客户端,并使用 PuTTYgen 生成了密钥。 是否可以将这些密钥用于 Azure DevOps Services?

答: 是的。 使用 PuTTYgen 加载私钥,转到转换菜单,然后选择导出 OpenSSH 密钥。 保存私钥文件,然后按照步骤 设置非默认密钥。 直接从 PuTTYgen 窗口复制公钥,并粘贴到安全设置中的密钥数据字段中。

问:如何验证我上传的公钥是否与我的本地密钥相同?

答:可以使用命令行对公钥运行以下 ssh-keygen 命令来验证上传的公钥的指纹是否与配置文件中显示的指纹匹配。 如果不使用默认值,需要更改路径和公钥文件名。

注意

截至 2024 年 8 月/9 月,我们将从 MD5 迁移到 SHA-256 哈希。 可能需要在转换期间选择正确的函数。

ssh-keygen -l -E md5 -f <path_to_your_public_key> -- use this for MD5 fingerprints
ssh-keygen -l -E sha256 -f <path_to_your_public_key> -- use this for SHA-256 fingerprints

然后,可以将签名与个人资料中的签名进行比较。 此检查非常适合以下情况:将密钥添加到 Azure DevOps 时遇到连接问题或担心将公钥错误地粘贴到“密钥数据”字段中。

问:如何在当前使用 HTTPS 的存储库中开始使用 SSH?

答:需要更新 Git 中的 origin 远程 URL,以便从 HTTPS 切换到 SSH URL。 获得 SSH 克隆 URL 后,运行以下命令:

git remote set-url origin <SSH URL to your repository>

访问名为 origin 的远程库的 Git 命令现在使用 SSH。

问:我在将 Git LFS 与 Azure DevOps Services 一起使用,并拉取 Git LFS 跟踪的文件时遇到错误。

答:Azure DevOps Services 目前不支持通过 SSH 使用 LFS。 使用 HTTPS 连接到包含 Git LFS 跟踪文件的存储库。

问:如何使用非默认密钥位置,即不是 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub 的位置?

答:若要使用并非存储在默认位置的密钥,请执行以下两个任务:

  1. 密钥必须位于只有你可以读取或编辑的文件夹中。 如果文件夹的权限范围更广,SSH 不会使用这些密钥。

  2. 必须让 SSH 知道密钥的位置,例如,在 SSH 配置中将其指定为“标识”:

    Host ssh.dev.azure.com
      IdentityFile ~/.ssh/id_rsa_azure
      IdentitiesOnly yes
    

IdentitiesOnly yes 设置可确保 SSH 不会使用任何其他可用标识进行身份验证。 如果有多个标识可用,则此设置尤其重要。

问:我有多个 SSH 密钥。 如何为 Azure DevOps 使用正确的 SSH 密钥?

答:通常,为 SSH 客户端配置多个密钥时,客户端会按顺序尝试对每个密钥进行身份验证,直到 SSH 服务器接受一个密钥。

但是,由于与 SSH 协议和 Git SSH URL 结构相关的技术限制,这种方法不适用于 Azure DevOps。 Azure DevOps 将接受客户端在身份验证期间提供的第一个密钥。 如果该密钥对所请求的代码库无效,请求将失败,并且不会尝试其他可用的密钥,而导致以下错误:

remote: Public key authentication failed.
fatal: Could not read from remote repository.

对于 Azure DevOps,需要将 SSH 配置为显式使用特定密钥文件。 此过程与使用存储在非默认位置中的密钥时相同。 指示 SSH 为 Azure DevOps 主机使用正确的 SSH 密钥。

问:如何对 Azure DevOps 上的不同组织使用不同的 SSH 密钥?

答:Azure DevOps 将盲目接受客户端在身份验证期间提供的第一个密钥。 如果该密钥对于请求的存储库来说无效,请求将失败并出现以下错误:

remote: Public key authentication failed.
fatal: Could not read from remote repository.

此失败是因为所有 Azure DevOps URL 共享相同的主机名 (ssh.dev.azure.com),使得 SSH 在默认情况下无法区分它们。 但是,可以通过为每个组织提供不同的密钥来修改 SSH 配置,以区分不同的组织。 使用主机别名在 SSH 配置文件中创建单独的 Host 部分。

# The settings in each Host section are applied to any Git SSH remote URL with a
# matching hostname.
# Generally:
# * SSH uses the first matching line for each parameter name, e.g. if there's
#   multiple values for a parameter across multiple matching Host sections
# * "IdentitiesOnly yes" prevents keys cached in ssh-agent from being tried before
#   the IdentityFile values we explicitly set.
# * On Windows, ~/.ssh/your_private_key maps to %USERPROFILE%\.ssh\your_private_key,
#   e.g. C:\Users\<username>\.ssh\your_private_key.

# Imagine that we have the following two SSH URLs:
# * git@ssh.dev.azure.com:v3/Fabrikam/Project1/fab_repo
#   * For this, we want to use `fabrikamkey`, so we'll create `devops_fabrikam` as
#     a Host alias and tell SSH to use `fabrikamkey`.
# * git@ssh.dev.azure.com:v3/Contoso/Project2/con_repo
#   * For this, we want to use `contosokey`, so we'll create `devops_contoso` as
#     a Host alias and tell SSH to use `contosokey`.
#
# To set explicit keys for the two host aliases and to tell SSH to use the correct
# actual hostname, add the next two Host sections:
Host devops_fabrikam
  HostName ssh.dev.azure.com
  IdentityFile ~/.ssh/private_key_for_fabrikam
  IdentitiesOnly yes

Host devops_contoso
  HostName ssh.dev.azure.com
  IdentityFile ~/.ssh/private_key_for_contoso
  IdentitiesOnly yes

之后,不要使用实际 URL,而是通过分别将现有远程库中的主机名替换为 devops_fabrikamdevops_contoso,指示 Git 要将每个存储库的这些 URL 用作远程库。 例如,git@ssh.dev.azure.com:v3/Fabrikam/Project1/fab_repo 将变为 git@devops_fabrikam:v3/Fabrikam/Project1/fab_repo

问:我可能会收到关于 SSH 密钥的哪些通知?

A: 您可能会收到一些关于您的 SSH 密钥的通知。

  • 已将新的 SSH 密钥添加到组织

  • 与帐户关联的 SSH 密钥将在 7 天内过期,并且对身份验证无效。

  • 与帐户关联的 SSH 密钥已过期,并且不再对身份验证有效。

    示例通知

    显示 SSH 密钥电子邮件通知的屏幕截图。

问:如果认为其他人正在我的帐户上添加 SSH 密钥,我该怎么办?

答:如果收到未启动的 SSH 密钥注册通知,那么凭据可能会遭到泄露。

下一步是调查密码是否已泄露。 更改密码始终是抵御这一攻击方式的一个好的第一步。 如果你是 Microsoft Entra 用户,请与管理员联系,检查帐户是否从未知源/位置使用。

问:如果系统仍提示输入密码,并且 GIT_SSH_COMMAND="ssh -v" git fetch 显示 no mutual signature algorithmcorresponding algo not in PubkeyAcceptedAlgorithms,我该怎么办?

答:某些 Linux 发行版(例如 Fedora Linux)的加密策略需要比 Azure DevOps 支持的更强大的 SSH 签名算法(截至 2021 年 1 月)。 有一个开放功能请求可用于添加此支持。

可通过将以下代码添加到 SSH 配置 (~/.ssh/config) 来解决此问题:

Host ssh.dev.azure.com vs-ssh.visualstudio.com
  PubkeyAcceptedKeyTypes +ssh-rsa

提示

对于 Azure DevOps Server 和 TFS 的自承载实例,请使用 Host 行中的相应主机名,而不是 ssh.dev.azure.com vs-ssh.visualstudio.com