防患于未然,应对“删库跑路”的一种解决思路

2020 年 11 月 24 日

防患于未然,应对“删库跑路”的一种解决思路

本文最初发布于 paepper.com 网站,经原作者授权由 InfoQ 中文站翻译并分享。


开发人员经常需要访问某些服务器,做一些检查应用程序日志之类的工作。


一般来说,访问过程是使用公私钥加密来控制的,每位开发人员都会生成自己的公私钥对。并且,每个开发人员的公钥都会添加到他们有权访问的每台服务器上的 authorized_keys 文件中。



痛苦的手动更改


到目前为止,这还没什么问题。但是,当一名开发人员离职时又会发生什么事情呢?


在这种情况下,应该从所有服务器上删除这位开发人员的公钥。根据他们有权访问的服务器数量,这可能会涉及很多工作。


更糟糕的是,如果这个环节都是手动操作的,那么操作员很有可能会忘了删除某些服务器上的公钥。也就是说,离职员工的访问权限仍然保持启用状态。


替代解决方案


有一些商业和开源解决方案可以帮助我们解决这一问题。这里的基本思想是,你在这类服务上添加并维护一个密钥和访问权限列表,需要删除某个密钥时,该密钥将从所有服务器中删除。


这听起来不错,但这种方案有一个很大的缺陷:它是潜在的单一故障源。如果某人获取了对该服务的访问权限,那就意味着他可以访问你的所有服务器。而且,如果你无法访问这个服务,在最坏的情况下,甚至会无法访问所有服务器。


解决方案:签名密钥


当我遇到了这个问题时,我去HackerNews上问了问其他人是如何解决它的。


社区提供了一些很棒的建议和见解,而这个问题的最佳解决方案似乎是对密钥进行签名,本文会详细给大家介绍一下。


基本思想


这个方法的基本思想是:你还是要为每位开发人员生成一个公钥-私钥对。但是,不要把公钥上载到服务器上。


而是使用之前生成的,所谓的证书颁发机构(CA)密钥对公共密钥进行签名。这个签名就是生成了第三个证书文件,你将它还给开发人员,然后让他们放在.ssh/文件夹中,和私钥、公钥放在一起。


在服务器上,你只需告诉服务器你的 CA 的公钥,服务器就可以检测用户是否具有正确签名的证书,并且仅允许拥有这种签名证书的开发人员访问自己。


优点


签署证书时,可以定义这次签署有效的时间。因此,如果你签署的有效期为 3 个月,随后开发人员离开了公司,那么 3 个月后,他们肯定将无法访问任何服务器。


现在你会说:好吧,但我不想每 3 个月就对每个人的密钥签一次名,这个抱怨很合理。


一种办法是让这个流程自动化,例如,你可以构建服务,让用户在使用公司的电子邮件和密码授权时可以自动获得签名证书,但这不在本文的讨论范围之内。


另一种简单的替代方法是,你可以颁发有效期更长的证书。然后,如果有人离开公司,就可以撤消这个证书,也就是使其失效。你可以在服务器上放置一个无效证书列表,它们将不再接受用户访问。例如,可以通过 AWS S3 或其他存储来存放这个列表,并在每台服务器上定期创建一个 cronjob 来完成这一操作。

该怎么做?


了解了原理后,实际上做起来非常简单。


首先,你要生成一个证书颁发机构的公钥-私钥对,你应该把这个私钥放在非常安全的地方:


umask 77                        # you want it to be privatemkdir ~/my-ca && cd ~/my-cassh-keygen -C CA -f ca -b 4096  # be sure to use a passphrase and store it securely
复制代码

然后在你的服务器上,设置为允许由你的 CA 签名的所有用户访问该服务器:


  1. 将CA的公钥上传到服务器上,例如放在/etc/ssh/ca.pub

  2. /etc/ssh/sshd_config中添加一行,指示服务器允许访问由该证书签名的用户:


TrustedUserCAKeys /etc/ssh/ca.pub # Trust all with a certificate signed by ca.pub
复制代码


为了使更改生效,你应该重新加载 ssh 服务:sudo service ssh reload。现在,如果一位开发人员生成了他的公钥-私钥对(例如ssh-keygen -t ecdsa -b 521),他们只需向你发送他们的公钥(请注意,你永远不需要发送任何私钥!)。然后,你只需签署他们的公钥就能生成他们的证书:

# Inside your ~/my-ca folder, sign their public key (here: id_ecdsa.pub)ssh-keygen -s ca -I USER_ID -V +12w -z 1 id_ecdsa.pub
复制代码

各个部分的简要说明:


  • -s ca:你要使用CA进行签名

  • -I USER_ID:你的用户ID/用户名

  • -V +12w:证书过期前的有效时间,这里有效期为12周

  • -z 1:此证书的序列号,以后可用它来让这个证书无效,序列号应唯一

  • id_ecdsa.pub:你要签名的开发人员的公钥


它将生成证书id_ecdsa-cert.pub,你可以将其发送给开发人员,然后将其放在〜/.ssh文件夹中的公钥/私钥对旁边。


改进一下


听起来不错,但是你还可以做得更好!


你的组织里可能有很多拥有不同经验水平、身处不同团队、承担不同职责的开发人员,并不是每个人都会访问相同的服务器。


这样的话,让我们在签名流程中添加角色吧。


这样,你可以在服务器上设置允许哪些角色访问服务器,并且在签名过程中可以指定要签名的开发人员的角色。


然后,这位开发人员就能访问与其角色匹配的所有服务器。


当你添加新的开发人员时,只需生成一个证书即可让他们获得授权,访问所有相关服务器,而无需在这些服务器上添加任何内容。


大致上是这样的:



带有角色的 ssh 证书签名


下面是在服务器上配置角色的方式:


首先,创建用于配置访问权限的文件夹:sudo mkdir /etc/ssh/auth_principals。在该文件夹中,你可以用允许登录服务器的用户名创建文件。例如,要对某些角色授予 root 访问权限,请添加文件/etc/ssh/auth_principals/root


/etc/ssh/auth_principals/root内部,你只需列出所有可以用 root 身份登录的角色,每行一个角色:

adminsenior-developer
复制代码

最后,再在/etc/ssh/sshd_config中添加一行,在服务器上配置为使用角色:


AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
复制代码

为了使更改生效,你应该重新加载 ssh 服务:sudo service ssh reload


下面是使用角色签署密钥的方式(它们已添加到证书中):


ssh-keygen -s ca -I USER_ID -n ROLE1,ROLE2 -V +12w -z 2 id_ecdsa.pub
复制代码


这里和之前是一样的,但带有-n ROLE1,ROLE2标志。重要提示:不同角色的逗号之间不能有空格!现在,这位开发人员可以登录 auth_principals 文件中有ROLE1ROLE2的任何服务器,以获取他们尝试登录时使用的用户名。

注销密钥


最后,如果要使证书无效,可以通过用户名或证书的序列号(-z标志)来实现。建议你在 Excel 电子表格中列出生成的证书列表,或者根据你的具体情况来建立数据库。


ssh-keygen -k -f revoked-keys -u -s ca list-to-revoke
复制代码


当你已经有一个revoked-keys列表并想要更新它时(-u标志)就这样做。对于初始生成,请拿掉更新标志。list-to-revoke需要包含用户名(id)或序列号(生成期间为-z标志),如下所示:

serial: 1id: test.user
复制代码

这将撤消对序列号为 1 的证书以及 ID 为test.user的所有证书的访问权限。


为了让服务器知晓已注销的密钥,你需要将生成的/更新的revoked keys文件添加到/etc/ssh/revoked-keys,并在/etc/ssh/sshd_config中再次配置:


警告:确保revoked-keys文件可访问且可读,否则你可能无法访问服务器


<span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">RevokedKeys /etc/ssh/revoked-keys</span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">
复制代码


小结:ssh 密钥管理的好方


我认为这种解决方案是最好用的。你可以选择通过 ssh 基于角色管理对服务器的访问权限。你只需配置一次服务器(允许哪些角色访问服务器)即可。对于新加入的开发人员,你只需要生成一个签名证书,他们就能立即访问与他们的角色/经验相匹配的所有相关机器。当他们离开公司时,你也可以通过一种简单的方式撤销他们的访问权限。


即使发生不幸事故,并且开发人员在未取消访问权限的情况下离开,他们的证书也会在一段时间后过期,因此他们也将自动失去访问权限。


对小型团队来说,你可以手动执行这些步骤,因为这些工作做起来非常快;然后随着你的成长,可以使用基于公司身份验证详细信息的登录服务来自动进行证书签名。


祝你 ssh 快乐!


原文链接:


https://www.paepper.com/blog/posts/how-to-properly-manage-ssh-keys-for-server-access/


2020 年 11 月 24 日 14:261161
用户头像

发布了 489 篇内容, 共 175.3 次阅读, 收获喜欢 1010 次。

关注

评论 2 条评论

发布
用户头像
跳板机它不香吗
2020 年 11 月 25 日 14:59
回复
用户头像
类似 FreeIPA 的方案还是简单多了,可以加一些高可用的方案。
2020 年 11 月 25 日 00:32
回复
没有更多评论了
发现更多内容

Hello!GitHub 好用好玩值得收藏的开源项目集合~

Kerwin

开源

SharePoint 部署架构

JackWangGeek

架构 BI SharePoint

week6 总结

不在调上

日记一则

progyoung

当我们在谈架构时,我们谈的是什么?

Winfield

架构 企业架构 系统架构

第六周作业

赵龙

ARTS - Week 5

Khirye

ARTS 打卡计划

SpringBoot代码生成器

Kerwin

Java 开源

程序员的时间管理

Kerwin

程序员

数据加工

阡陌r

关于如何判断一个list是否为空的思考

Leetao

Python Python基础知识 列表

week6 学习总结

Geek_2e7dd7

设计模式总篇:从为什么需要原则到实际落地(附知识图谱)

Kerwin

Java 设计模式

6 个珍藏已久 IDEA 小技巧,这一波全部分享给你!

楼下小黑哥

Java IDEA

图解SQL Server 2008 R2安装

JackWangGeek

sql

简述 CAP 原理

不在调上

没内鬼,来点干货!SQL优化和诊断

Kerwin

MySQL

nginx在重定向时端口出错的问题

烫烫烫个喵啊

nginx

因为 Django ORM update,我今天差点「从删库到跑路」

AlwaysBeta

数据库 django 编程 程序员

疫情年逆风翻盘

Kerwin

程序员

有朋自远方来 不亦说乎,请多关照哈

InfoQ_353bc6b96230

图解SharePoint Server 2010安装

JackWangGeek

SharePoint

图解Windows Server 2008 R2安装

JackWangGeek

windows-server

week6

Geek_2e7dd7

架构师训练营 - 第六周 - 学习总结

韩挺

redis系列之——一致性hash算法

诸葛小猿

redis 一致性hash redis集群

Mybatis执行流程浅析(附深度文章推荐&面试题集锦)

Kerwin

Java mybatis

没内鬼,来点干货!volatile和synchronized

Kerwin

Java volatile synchronized

【计算机网络】你需要知道的链路层知识

烫烫烫个喵啊

计算机网络 链路层 交换机

架构师训练营 - 第六周 - 作业

韩挺

Elasticsearch从入门到放弃:再聊搜索

Jackey

elasticsearch

防患于未然,应对“删库跑路”的一种解决思路-InfoQ