今天的最佳实践至少需要考虑使用堡垒主机或 VPN 类型的网络限制,以及根据您的问题的重点,中央凭证管理。我建议使用堡垒并使用基于 CA 的密钥签名。
为什么你应该(但不是必须)做堡垒
我们会喜欢它,当员工离开,即使他把他的SSH密钥的副本,他不能达到SSH端点。这是堡垒主机、VPN 和防火墙的任务。堡垒主机在基础设施方面也有很大帮助,因为如果您可以限制对堡垒的访问(例如,通过删除前雇员的 ssh 密钥),那么用户将自动被限制访问其他端点。
虽然 Bastion 主机可能会使进行密钥管理的实践变得更容易,但它在技术上并不是必需的。尽管如此,我还是强烈建议使用堡垒主机:它提高了安全性;简化基础设施;并协助审计。
管理密钥
将 pubkeys 基本复制到 authorized_keys
作为自动化任务的一部分复制公钥将起作用。Ansible、SaltStack、特定于云的部署工具、cron 等都是如何实现的示例。但是它没有下面的 Key-signing 的明显优势。如果您已经拥有适合您的自动化设备,它可以继续正常工作。有一些优点——但你已经付出了额外的工作来让它工作,而且它没有坏(对吧?)。
免费IPA
如果在所有服务器和工作站/笔记本电脑上配置 FreeIPA,您可以集中管理密钥。我发现了一些显然可以与它一起使用的工具来支持使用 CA 签名的密钥,尽管我还没有探索这个选项。
密钥签名
至少自 2010 *以来,对签名 SSH 密钥证书的内置支持显然已在 openssh 中提供,尽管我最近才知道它。SSH 密钥签名似乎优于所有其他可用的密钥管理机制。Facebook 最近(2016 年)发布了关于他们如何管理证书的帖子 - 签署 SSH 密钥是主要成分。
核心思想是您拥有自己的内部 CA 来验证您的公钥,并让您的所有 ssh 端点都信任该 CA。当您连接到端点时,ssh 会显示您的公钥和签名证书,端点会验证证书是否正确,并且您被授予访问权限。
密钥签名的优点:
- 您的“个人”密钥变得短暂 - 您不必担心备份密钥
- 实际密钥不受信任,这意味着泄露的密钥并不重要
- 证书过期,这意味着受损的密钥-证书组合有时间限制,此后它不再有权访问您的基础设施
- 服务器密钥也可以签名,这意味着当您连接到签名端点时,您不必手动批准或管理冲突的指纹(FreeIPA 也可以处理这个问题,尽管它在技术上仍然会“老式”复制公钥)
如何使用密钥签名?
不幸的是,没有专门为协调 CA 信任和密钥签名而构建的著名的交钥匙系统——但有一些工具可以让您组合起来完成这项工作。对于一个团队,您可能愿意编写自己的系统来签署密钥,尽管我目前正在研究一些工具集。其中最重要的是 HashiCorp 的 Vault,它承诺使用其Secrets Engine解决签名 SSH 证书的问题。CommerceHub 的ssh-ca-server,承诺允许您的 CA 通过 Web 界面对密钥进行签名,同时使用 LDAP 身份验证来确保仅对有效用户的密钥进行签名。如前所述,我不确定这些是否是完整的解决方案 - 但它们至少涵盖了很多领域。似乎还有很多其他的工具集——尽管我还不知道有什么似乎是“最好的”工具集。另请参阅对此答案的知情评论。
我想手动完成 - 或者我想了解它是如何完成的
以个人身份,只要您保留 CA 密钥密码,您就可以使用 CA 签名,如下所示。在小型企业环境中,我建议将密钥分开,这样用户就无法直接访问它,或者将现有工具(如上所述)放在一起为您完成繁重的工作。您还应该建立适当的备份机制——这一键控制对所有内容的访问:
示例手动用例
在我的示例中,我们将使用.ssh/.ca
测试客户端上的 ca 数据文件夹。注意当然这只是一个例子。最好的方法是通过远程服务:
tricky@testclient $ export CAPATH=~/.ssh/.ca
生成 CA 密钥对
您可以使用rsa
类型 - 我只是更喜欢ed25519
:
tricky@testclient $ ssh-keygen -C CA -f ${CAPATH}/ca -t ed25519
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/tricky/.ssh/.ca/ca.
Your public key has been saved in /home/tricky/.ssh/.ca/ca.pub.
The key fingerprint is:
SHA256:qGSZbssuQOV0TR8WrTV/gzXBSyTO4uAKUO7q+fJUDYw CA
The key's randomart image is:
+--[ED25519 256]--+
| .o. +o .oo.|
| oo.o.o .+o .= |
| +..E o oo.oo+ o|
| . .oo .+.o .o + |
|. =o..So . . .|
|. +..o . |
| . .+. . |
| o+o. |
| =Bo |
+----[SHA256]-----+
tricky@testclient $ cat ${CAPATH}/ca.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKg9nxnaBLOQKnfuxUQgb3Y1hiqIaMEtXwr8WsX5bLlv CA
分发公共部分
将文件分发ca.pub
到 ssh 守护程序可访问的位置中的远程端点,例如/etc/ssh/ca.pub
- 这只需在每台服务器上执行一次。确保它归根用户所有,非根用户不可写。其他用户也可以阅读。
配置远程端点
将以下行添加到sshd_config
远程端点上的文件中,指的是您添加ca.pub
文件的位置。同样,这只需在每台服务器上执行一次:
TrustedUserCAKeys /etc/ssh/ca.pub
测试配置文件。您可能会在配置中发现“不推荐使用的选项”警告,特别是如果您使用的是非库存生成的配置 - 但只要没有实际错误,您可以重新启动 sshd 服务:
root@testserver $ sshd -t
/etc/ssh/sshd_config line 23: Deprecated option UsePrivilegeSeparation
/etc/ssh/sshd_config line 26: Deprecated option KeyRegenerationInterval
/etc/ssh/sshd_config line 27: Deprecated option ServerKeyBits
/etc/ssh/sshd_config line 45: Deprecated option RSAAuthentication
/etc/ssh/sshd_config line 54: Deprecated option RhostsRSAAuthentication
root@testserver $ systemctl restart sshd
root@testserver $
确保您没有使用旧密钥
要进行测试,请重命名您现有的密钥,以便您不再使用显式受信任的密钥:
for type in dsa rsa ed25519 ; do
mv ~/.ssh/id_${type}{,.bak}
mv ~/.ssh/id_${type}.pub{,.bak}
done
请参阅末尾的注释**以恢复这些原始密钥(毕竟,在您的 CA 被所有端点信任之前,您将需要现有的密钥)。
作为健全性检查,如果您使用的服务(例如 keychain 或 ssh-agent)会记住您的密钥,您可能需要停止该服务,以便知道您的测试没有使用旧密钥:
tricky@testclient $ killall ssh-agent
创建一个新的用户密钥对
您可以使用rsa
类型 - 我只是更喜欢ed25519
:
tricky@testclient $ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in testkey.
Your public key has been saved in testkey.pub.
The key fingerprint is:
SHA256:0cKlJxYQrizfd5FDboyVYhn9RK7oHkpsBbarZuv+DoQ brendan@tricky-desktop.4d.eset.co.za
The key's randomart image is:
+--[ED25519 256]--+
| ooo.... |
| . . B.o. |
| + @ *o. |
| o o = & o. |
| E + . S O |
| + o + . o |
| o * + . |
| o= + o |
| ==++ . |
+----[SHA256]-----+
tricky@testclient $
签署新的用户密钥对
密钥签名使用可用于帮助审计的序列号。我不介意在示例中记录这一点。您至少会在后续签名事件中增加序列号。序列号必须是数字:
tricky@testclient $ export serial=1
身份理论上可以是任何东西 - 但客户端用户名或 user@hostname 是一个很好的起点
tricky@testclient $ export IDENTITY="${USER}@$(hostname)"
密钥需要授予特定远程用户的访问权限。使用典型的堡垒配置,您不会在这里拥有“root”:
tricky@testclient $ export users="root,${USER}"
对于有效期,我一般建议使用 4 小时(14400 秒)——但您可能需要更长的时间跨度。Facebook 的帖子建议一整天(86400 秒)。其他具有自动身份验证的人建议只需五分钟。
tricky@testclient $ export VALIDITY_PERIOD=86400
请注意,您签署了公钥,因为它是需要被端点接受的公共部分:
tricky@testclient $ ssh-keygen -s ${CAPATH}/ca -I ${IDENTITY} -n ${users} -V +${VALIDITY_PERIOD} -z ${serial} ~/.ssh/id_ed25519.pub
Enter passphrase:
Signed user key /home/tricky/.ssh/id_ed25519-cert.pub: id "tricky@testclient" serial 1 for root,tricky valid from 2018-10-09T20:06:00 to 2018-10-10T20:06:00
连接到端点:
tricky@testclient $ ssh root@testserver
Last login: Mon Oct 8 20:46:31 2018 from testclient.localdomain
root@testserver ~ #
*感谢@PatrickMevzek 提供参考信息:
TrustedUserCAKeys ... was added first in a commit on March 4 2010
openssh.com/txt/release-5.4 "Add support for certificate authentication of users and hosts using a new, minimal OpenSSH certificate format (not X.509)."
**
for type in dsa rsa ed25519 ; do
mv ~/.ssh/id_${type}{.bak,}
mv ~/.ssh/id_${type}.pub{.bak,}
done
恢复后,我建议您签署现有密钥,但也开始将它们视为临时密钥。保留原始密钥的备份,以防您认为信任它们但不支持基于 CA 的密钥签名的服务可能需要它们。