运行 Ruby 中的 ssh-keygen 生成 VCS 部署密钥?

Run ssh-keygen in Ruby to generate VCS deploy keys?

我运行此命令为我的私有存储库生成有效的部署密钥:

ssh-keygen -b 2048 -t rsa -C "mystring"

该命令提示我输入路径和密码(我留空),并生成到文件。

一个mykey:

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
...
-----END OPENSSH PRIVATE KEY-----

还有一个mykey.pub:

ssh-rsa AAAAB3NzaC1yc...QDBQl mystring

但是我如何 运行 纯 Ruby 这个命令并得到字符串形式的结果?

我试过:

keypair = OpenSSL::PKey::RSA.new 2048
keypair.to_pem
keypair.public_key.to_s

但是生成的文件与我用 ssh-keygen 得到的文件不一样。

有人知道怎么做吗?

P.s。我找到了 sshkey gem,但还没有尝试过,因为我宁愿避免为此使用 gems。

使用内核调用 OpenSSH 实用程序

这是我认为 不应该 直接移植到 Ruby 的事情之一。虽然 OpenSSH 二进制文件和源代码会受到例行审核,但很少使用或很少使用的 Ruby gems 或 FFI 包装器不会得到相同级别的审查。相反,您应该使用 Kernel#system or Kernel#` 调用或 %x() 子 shell 文字,具体取决于您的用例。

从内部调用外部 SSH 实用程序Ruby

例如:

    # Note that 3072 is currently the default size for RSA keys in
    # OpenSSH. Also note that you can pass `-f path/to/keyfile` or
    # `-P ""` for an empty passphrase if you don't use the `-A` flag.
    system %(ssh-keygen -A -b 2048 -t rsa -C "mystring")

没有 -f 标志,您的 RSA 密钥将被放入 ~/.ssh/id_rsa~/.ssh/id_rsa.pub。然后,如果确实需要,您可以使用标准 Ruby 方法来读取文件,尽管我还是想不出您需要这样做的很多原因。

例如,要将 public 键读入 Ruby 变量:

public_key = File.read "#{ENV['HOME']/.ssh/id_rsa.pub"

使用 SSH 代理

请注意,如果您已经在 运行 程序中,那么您最大的挑战将是使用 SSH 代理(如果您正在使用的话),因为环境变量和密钥 material 不太可能此时可用。但是,您可以根据需要启动代理并在当前会话中加载密钥文件。例如:

ssh_agent = %x(eval 'ssh-agent -s')

# assumes a passwordless key
system("ssh-add") && %x(ssh-add -l)

# Your agent's SSH_AUTH_SOCK is now exported by your current Ruby
# environment.
ENV['SSH_AUTH_SOCK']

# For some reason, SSH_AGENT_PID isn't exported properly. This may be
# user error on my part. Luckily, you can easily parse it out of the
# *ssh_agent* variable if needed.
ENV['SSH_AGENT_PID'] =
  ssh_agent.match(/SSH_AGENT_PID=\d+/).to_s.split(?=).last

安全说明

如果您 运行 在 macOS 或安装了钥匙串的 Linux 系统上,最好使用存储在登录钥匙串中的密码或在启动 ssh-agent 时提示输入的密码。无密码密钥有其用武之地,但还有更安全的选项,在大多数现代系统上同样易于管理。 YMMV 基于您的确切用例。

另请参阅

有一个net-ssh gem that also contains ssh-agent support。这是否适合您的需求或是否针对您的用例进行了充分审核取决于您。但是,其他不想自己推出或调用外部实用程序的访问者应该了解此解决方案,并且可能还有其他解决方案。同样,您的里程可能会有所不同。