使用 SSH 密钥身份验证

Azure DevOps 服务 |Azure DevOps Server |Azure DevOps Server 2022

在 macOS、Linux 或 Windows 上使用 SSH,安全地向 Azure DevOps 中的 Azure Repos Git 存储库进行身份验证。

本文介绍如何创建 RSA 密钥对、将公钥添加到配置文件,以及使用 SSH 克隆存储库。

重要

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。
  • 在命令行中,针对要更新的每个存储库的远程,分别运行 git remote set-url <remote name> <new SSH URL>。 或者,使用 GUI 客户端更新远程 URL。

先决条件

类别 要求
权限 对克隆存储库的访问权限
策略 已启用 SSH 身份验证
本地工具 可从终端或 shell 获取的 Git 和 OpenSSH 客户端
Windows环境 如果您使用 Windows,可以使用 Git for Windows 或其他提供 gitsshssh-keygen 的环境
本地访问 访问本地 .ssh 文件夹和创建密钥文件的权限

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

SSH 公钥身份验证使用生成的加密密钥的非对称对。 与Azure DevOps共享公钥,以验证初始 SSH 连接。 请妥善保管系统中的 私有密钥,确保其安全。

设置 SSH 密钥身份验证

若要将 SSH 与 Azure Repos 配合使用,请生成 RSA 密钥对,将公钥添加到Azure DevOps配置文件,验证服务器指纹,然后克隆或更新存储库以使用 SSH URL。

如果只需要最快的路径,请按顺序完成步骤 1、步骤 2 和步骤 3,然后仅在命令失败时使用 SSH 身份验证疑难解答

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

提示

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

步骤 1:创建 SSH 密钥

注意

如果已在系统上创建了 RSA SSH 密钥,请跳过此步骤并转到步骤 2。 若要验证这一点,请转到主目录并查看.ssh文件夹(%UserProfile%\.ssh\在 Windows 或 ~/.ssh/ Linux、macOS 上,以及使用 Git Bash Windows)。 如果您看到两个名为 id_rsaid_rsa.pub 的文件,请继续执行第 2 步。

若要使用基于密钥的身份验证,首先需要为客户端生成公钥/私钥对。 OpenSSH 可以生成多种密钥类型,但Azure DevOps支持用于 SSH 身份验证的 RSA 密钥。

注意

Azure DevOps支持 RSA 密钥,并在身份验证期间使用 RSA-SHA2 签名算法。 生成 RSA 密钥,并在连接时让 SSH 客户端协商支持的 RSA-SHA2 签名。

若要为Azure DevOps生成 RSA 密钥对,请从 PowerShell 或其他 shell(如bash客户端)运行以下命令:

ssh-keygen -t rsa -b 3072

命令的输出应显示如下内容(其中 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 中配置公钥。

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

    注意

    组织策略可以强制实施 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 克隆的存储库配合使用,请参阅 如何在当前正在使用 HTTPS 的存储库中使用 SSH?

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

    Azure Repos SSH 克隆 URL 的截图。

    注意

    使用 Azure DevOps 服务时,项目 URL 的格式为 dev.azure.com/{your organization}/{your project}。 但是,引用 visualstudio.com 格式的旧格式仍然受到支持。 有关详细信息,请参阅 Introducing 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.
    

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

提示

若要充分利用 SSH,请使用 SSH 代理管理 SSH 密钥。 设置代理超出了本文的范围。

使用 AI 处理 SSH 身份验证的存储库

如果将 Git 存储库与 GitHub Copilot 或 Azure DevOps MCP 服务器配合使用,则可以使用自然语言提示来验证 SSH 设置并诊断身份验证问题。

Task 示例提示
检查存储库使用的远程 Check whether this repository uses SSH or HTTPS for origin, and show me how to switch it to SSH if needed.
验证 SSH 设置 Review my Git remote configuration and explain whether it matches the Azure Repos SSH format.
诊断身份验证失败 Help me troubleshoot this Azure Repos SSH error: remote: Public key authentication failed.
检查 SSH 使用的是哪个密钥 Explain how to tell which SSH key my client is offering to ssh.dev.azure.com and what to change if it is the wrong one.

提示

在Visual Studio Code中,代理模式可用于检查远程、查看 SSH 配置,以及建议终端输出中的后续故障排除步骤。

故障排除和常见问题

使用以下部分查找与 SSH 设置问题匹配的问题。

密钥已过期或无效

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

答: 按照前面的步骤 创建并上传新的 SSH 密钥

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

七天前以及密钥过期时,你会自动收到通知。 除了这些通知外,你还会看到以下提示信息:

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-256rsa-sha2-512

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

此修复是解决已弃用的ssh-rsa警告和不受支持的ssh-rsa错误的标准方法。 在上述场景中,请将其作为第一步。

问: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-rsa 警告所述的相同修复措施:删除任何 HostkeyAlgorithms +ssh-rsa 覆盖设置,并使用 rsa-sha2-256 和/或 rsa-sha2-512

  • 没有匹配的主机密钥

    此问题不应发生在 Azure DevOps 服务或较新的Azure DevOps Server版本中,如 blog post 中所述。

    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
    

    仅将此解决方法用于旧版兼容性方案,通常适用于旧的自承载Azure DevOps Server配置。 对于 Azure DevOps Services,请保留安全的默认设置,并避免持久的 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-sha1diffie-hellman-group14-sha1 中禁用密钥交换算法

提示

对于 Azure DevOps Server 的自行托管实例,请在 Host 行中使用相应的主机名,而不是 ssh.dev.azure.comvs-ssh.visualstudio.com

SSH 代理和通行短语问题

问:SSH 代理未运行,或者我的密钥未加载。 我该怎么办?

答: 如果密钥存在,但每次 SSH 仍会提示输入通行短语,或者如果成功创建密钥后克隆失败,请检查 SSH 代理是否正在运行,以及密钥是否已加载。

使用以下命令查看代理当前已加载的标识:

ssh-add -l

如果输出显示代理没有标识,请将私钥添加到代理:

ssh-add ~/.ssh/id_rsa

在Windows,如果将 PowerShell 与内置的 OpenSSH 代理一起使用,请确保ssh-agent服务在添加密钥之前正在运行。 如果使用 Git Bash 或其他 SSH 客户端,请参阅该客户端的文档,以启动其代理和加载密钥。

如果不想使用代理,SSH 仍可以正常工作,但经常会提示输入密钥通行短语。

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

答: 使用 SSH 代理。 Linux、macOS 和 Windows(从 Windows 10(版本 1809) 开始,或通过使用带有 Git Bash 的 Git for Windows)均附带 SSH 代理。 SSH 代理可以缓存 SSH 密钥以供重复使用。 若要详细了解它的使用方式,请参阅 SSH 供应商的手册。

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

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

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

答: 将您上传的公钥指纹与个人资料中显示的指纹进行比对,以验证该公钥指纹。 ssh-keygen使用命令行针对公钥运行以下命令。 如果不使用默认值,需要更改路径和公钥文件名。

注意

首选 SHA-256 指纹。 仅当需要与旧指纹格式进行比较时,才使用 MD5。

ssh-keygen -l -E md5 -f <path_to_your_public_key>
ssh-keygen -l -E sha256 -f <path_to_your_public_key>

然后将该签名与你个人资料中的签名进行比较。 如果在将密钥添加到Azure DevOps时遇到连接问题或担心将公钥错误粘贴到密钥数据字段中,则此检查非常有用。

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

A:更新 Git 中的 origin 远程,将其从 HTTPS URL 更改为 SSH URL。 获取 SSH 克隆 URL 后,运行以下命令:

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

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

管理多个密钥和组织

问:我在Azure DevOps服务中使用 Git LFS,在拉取 Git LFS 跟踪的文件时遇到错误。

A: Azure DevOps服务当前不支持通过 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 密钥。 如何将正确的 SSH 密钥用于Azure DevOps?

答:通常,为 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 密钥的通知?

答: 可能会收到一些有关 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 配置更强 SSH 签名算法的加密策略。

若要解决此问题,请将以下代码添加到 SSH 配置(~/.ssh/config):

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

如果 OpenSSH 版本仅支持较旧的设置名称,请改用 PubkeyAcceptedKeyTypes

将此代码用作临时兼容性解决方法。 如果可能,请升级 SSH 客户端或服务器配置,并在测试后删除此替代。

一般问题

问:是否可以将 SSH 与Azure DevOps Server配合使用?

答: 是的。 对于自托管的 Azure DevOps Server 实例,请在 SSH 配置和远程 URL 中使用你的服务器主机名,而不要使用 ssh.dev.azure.com。 本文中凡是显示 ssh.dev.azure.comvs-ssh.visualstudio.com 的地方,请将其替换为你的服务器的主机名。

问:为什么我的Azure DevOps服务 SSH 密钥停止工作?

答:SSH 密钥身份验证要求使用完整的身份验证流(Web)定期登录到 Azure DevOps 服务。 每 30 天登录一次就足以满足许多用户的需求,但可能需要根据Microsoft Entra配置更频繁地登录。 如果 SSH 密钥停止工作,请先尝试登录到组织并完成完整的身份验证提示。 如果 SSH 密钥仍然不起作用,请检查它是否已过期。

提示

对于 Azure DevOps Server 的自行托管实例,请在 Host 行中使用相应的主机名,而不是 ssh.dev.azure.comvs-ssh.visualstudio.com