如何根据 URL 路径或 SSH 参数(对于 github 部署密钥)匹配 SSH 配置?

coo*_*101 8 ssh

我正在尝试为 github 使用多个部署密钥,这意味着我需要根据存储库名称匹配我的 SSH 配置。我无法根据主机名、端口或用户进行匹配,因为它们都是相同的。只有回购名称和部署密钥不同。

我知道以前有人问过这个问题,但我找不到满意的答案,因为我对在我的 github ssh URL 中添加子域或用户不感兴趣。此问题专门针对如何匹配 URL PATH 或 SSH 参数或其他不涉及修改默认 github ssh URL 的解决方法。

默认的 ssh github url 是 git@github.com:githubusername/githubreponame.git

通常的 SSH 配置是:

# repo 1
# MATCH or HOST xxxxxxxxxxx
    HostName github.com
    User git
    IdentityFile ~/.ssh/myrepo1name_rsa

# repo 2
# MATCH or HOST xxxxxxxxxxx
    HostName github.com
    User git
    IdentityFile ~/.ssh/myrepo2name_rsa
Run Code Online (Sandbox Code Playgroud)

根据 ssh 配置手册http://man7.org/linux/man-pages/man5/ssh_config.5.html,您可以使用 2 个参数来匹配配置,HOST 或 MATCH。

我们已经知道 HOST 做不到。所以 MATCH 是唯一的方法:

MATCH 的可用条件关键字有:canonical、final、exec、host、originalhost、user 和 localuser。

从这些 MATCH 条件关键字来看,似乎没有人可以访问 repo 名称或 SSH 参数或任何有用的东西。

MATCHexec标准关键字似乎很有希望:

exec 关键字在用户的shell 下执行指定的命令。如果该命令返回零退出状态,则认为该条件为真。

exec可以访问以下变量http://man7.org/linux/man-pages/man5/ssh_config.5.html#TOKENS

%h    The remote hostname.
%i    The local user ID.
%L    The local hostname.
%l    The local hostname, including the domain name.
%n    The original remote hostname, as given on the command line.
%p    The remote port.
%r    The remote username.
%u    The local username.
Run Code Online (Sandbox Code Playgroud)

这些变量中没有一个对我有用。

我尝试了以下方法:

Match exec "pwd | grep myreponame1"
    HostName github.com
    User git
    IdentityFile ~/.ssh/myreponame1_rsa
Run Code Online (Sandbox Code Playgroud)

它部分成功,因为通常当我使用 git 时,我在 repo 目录中,所以pwd | grep reponame会退出 true。但它不适用于克隆或如果我使用不同的目录名称。

我正在寻找更好的替代方案,它可能也会MATCH exec以某种方式使用。

编辑:到目前为止我发现的最佳解决方案是:

Match exec "git remote get-url origin | grep reponame || echo $REPO | grep reponame"
Run Code Online (Sandbox Code Playgroud)

但是我对它不是 100% 满意,因为我需要在 git clone 之前添加一个 env 变量。

bla*_*xpy 12

您可以为特定 GitHub 用户或存储库指定 SSH 密钥。

使用url全局 git 配置中的规则更改主机名。然后Host在 SSH 代理配置中使用规则为主机名选择正确的身份。

示例

GitHub 用户名:user1.

存储库:git@github.com:user1/repo.git.

用户身份文件:~/.ssh/id_rsa_user1.

~/.gitconfig~/.config/git/config

[url "git@github.com:"]
    insteadOf = https://github.com/
[url "git@github-user1:user1"]
    insteadOf = git@github.com:user1
Run Code Online (Sandbox Code Playgroud)

~/.ssh/config

AddKeysToAgent  yes
IdentitiesOnly yes

Host github-user1
    HostName github.com
    IdentityFile ~/.ssh/id_rsa_user1

Host *.example.com
    IdentityFile ~/.ssh/id_rsa_example
Run Code Online (Sandbox Code Playgroud)

Git 将替换git@github.com:user1git@github-user1:user1. 所以新的主机名将是github-user1. 然后 SSH 代理将使用新的主机名来选择user1身份文件~/.ssh/id_rsa_user1

现在您可以使用以下命令克隆存储库:

git clone git@github.com:user1/repo.git
Run Code Online (Sandbox Code Playgroud)

注意事项

只应用一个url规则。所以这行不通:

git clone https://github.com/user1/repo.git
Run Code Online (Sandbox Code Playgroud)

SSH 配置手册:

man ssh_config
Run Code Online (Sandbox Code Playgroud)

参数含义:

  • AddKeysToAgent - 首次使用时将密钥及其密码存储在代理中。
  • IdentitiesOnly - 即使代理有更多身份,也只使用配置的身份。

默认身份是~/.ssh/id_rsa。如果您使用它,请不要通过顶级IdentityFileHost *规则设置它,否则您将遇到以下问题:

  • 默认身份设置为IdentityFile ~/.ssh/id_rsa
  • 默认身份在代理中,id_rsa_user1不在代理中。
  • github-user1尽管有Host github-user1规则,代理将使用主机的默认标识。


che*_*ner 5

最简单的做法是为每个存储库创建单独的别名。

Host repo1
  HostName github.com
  User git
  IdentityFile ~/.ssh/myrepo1name_rsa

Host repo2
  HostName github.com
  User git
  IdentityFile ~/.ssh/myrepo2name_rsa
Run Code Online (Sandbox Code Playgroud)

然后使用repo1:githubusername/githubreponame.gitrepo2:githubusername/githubreponame.git作为 Git 中的 URL。

为了减少重复,您可以使用可以匹配的模式定义别名。

Host gitrepo1
  IdentityFile ~/.ssh/myrepo1name_rsa

Host gitrepo2
  IdentityFile ~/.ssh/myrepo2name_rsa

Host git*
  HostName github.com
  User git
Run Code Online (Sandbox Code Playgroud)