一、镜像签名到底是什么,为什么要搞这个

很多开发者在开发容器应用的时候,都会遇到一个头疼的问题:怎么保证自己拉下来的镜像,就是官方原本的版本,没被人偷偷改过?比如你要拉一个官方的Redis镜像,结果拉到的是被黑客植入了挖矿程序的版本,那整个系统都得遭殃。镜像签名就是用来解决这个问题的,简单说就是给镜像盖个“专属印章”,只要印章没被伪造,就能证明镜像没被篡改过。

那这个印章是怎么盖的呢?核心就是用非对称加密的那套逻辑,简单说就是有一对钥匙,一把是公开的公钥,一把是只有自己知道的私钥。盖印章的时候用私钥,验证印章的时候用公钥。因为私钥只有自己有,所以别人就算拿到公钥,也盖不出一模一样的印章,也就没法伪造。

举个生活里的例子,就像你给银行发转账申请,银行会用它的私钥给转账结果盖个章,你拿到结果后,用银行公开的公钥去验证这个章是不是真的,就能确定结果没被中间人篡改过。镜像签名的逻辑和这个一模一样,只是把“转账结果”换成了“镜像文件”。

1.1 非对称加密在签名里的作用

可能有人会问,为什么不用对称加密?对称加密是一把钥匙加密也用这把钥匙解密,要是钥匙被人拿到了,整个体系就崩了。非对称加密的公钥可以随便公开,就算被别人拿到,也没法用公钥生成签名,只有私钥能做这件事,安全性高很多。

这里给大家举个简单的非对称加密示例,用Shell命令就能模拟签名和验证的过程,先明确技术栈:Shell(基于OpenSSL工具)。

首先生成一对密钥,私钥用来签名,公钥用来验证:

# 生成2048位的RSA私钥,私钥文件命名为harbor_private.key
openssl genrsa -out harbor_private.key 2048

# 从私钥中提取公钥,公钥文件命名为harbor_public.key
openssl rsa -in harbor_private.key -pubout -out harbor_public.key

接下来模拟给一个“镜像摘要”签名,镜像摘要其实就是镜像的唯一标识,就像人的身份证号,只要镜像内容改了,摘要就会变。我们先创建一个模拟的镜像摘要文件:

# 模拟生成镜像摘要,内容是一串随机字符,这里用echo写入文件
echo "sha256:1a2b3c4d5e6f7g8h9i0j" > mock_image_digest.txt

然后用私钥给这个摘要签名,生成签名文件:

# 用私钥给摘要文件签名,生成签名文件mock_signature.sig
openssl dgst -sha256 -sign harbor_private.key -out mock_signature.sig mock_image_digest.txt

最后用公钥验证这个签名是不是真的:

# 用公钥验证签名,如果验证成功会输出Verification successful
openssl dgst -sha256 -verify harbor_public.key -signature mock_signature.sig mock_image_digest.txt

如果验证成功,就说明这个摘要没被篡改过,对应的镜像自然也是安全的。要是有人改了摘要里的内容,再用原来的公钥验证,就会输出Verification failure,这样就能及时发现问题。

二、Harbor的镜像签名机制是怎么运作的

Harbor作为国内常用的容器镜像仓库,它的签名机制不是自己凭空造的,而是基于Docker官方的Notary项目来实现的。Notary是专门用来给容器镜像做签名和验证的工具,Harbor把它集成到了自己的系统里,让开发者不用单独操作Notary,就能完成签名和验证。

Harbor的签名流程大概分三步:第一步是生成或导入签名用的密钥对,第二步是给要发布的镜像签名,第三步是验证拉取的镜像签名是否合法。

2.1 密钥对的管理

Harbor里的密钥对有两种,一种是项目管理员自己生成的,一种是导入的。一般来说,项目管理员会在自己的开发机上生成私钥,然后把公钥导入到Harbor的对应项目里。这样项目里的所有成员,拉取镜像的时候,都会用这个公钥来验证签名。

这里要注意,私钥一定要保管好,不能泄露,不然别人就能用你的私钥伪造签名了。就像你家的钥匙丢了,别人就能进你家一样。

2.2 签名的具体流程

当你要给一个镜像签名的时候,首先要把镜像推到Harbor的项目里,然后在Harbor的管理界面或者用命令行触发签名操作。Harbor会自动调用Notary服务,用你导入的私钥给镜像的摘要生成签名,然后把签名和镜像绑定在一起,存到Harbor的数据库里。

举个具体的Harbor签名示例,技术栈:Shell(Harbor CLI命令)。首先你要先登录Harbor,然后给指定的镜像签名:

# 登录Harbor仓库,替换成自己的Harbor地址、用户名和密码
docker login https://your-harbor-address -u admin -p Harbor12345

# 给镜像打标签,格式是harbor地址/项目名/镜像名:标签
docker tag nginx:alpine your-harbor-address/my-project/nginx:alpine

# 推送镜像到Harbor
docker push your-harbor-address/my-project/nginx:alpine

# 用Harbor CLI给镜像签名,需要先安装Harbor CLI工具,替换成自己的地址和镜像名
harbor image sign --address https://your-harbor-address --project my-project your-harbor-address/my-project/nginx:alpine

签名成功后,你可以在Harbor的项目页面里,找到这个镜像的签名信息,确认签名已经生成。

2.3 签名验证的流程

当你要拉取一个镜像的时候,Harbor会先检查这个镜像有没有签名,如果有,就会用项目里导入的公钥来验证签名是不是合法。如果验证通过,就允许拉取;如果验证不通过,就会拒绝拉取,同时给出错误提示。

验证的示例同样用Shell命令:

# 拉取Harbor里的镜像,Harbor会自动验证签名
docker pull your-harbor-address/my-project/nginx:alpine

如果镜像的签名验证失败,Docker会输出类似“签名验证失败,镜像不可信”的错误,这样你就不会拉到被篡改的镜像了。

三、Harbor镜像签名的安全保障措施

镜像签名本身已经很安全了,但Harbor还做了很多额外的安全保障措施,让整个签名体系更可靠。这些措施主要包括密钥的安全存储、签名的强制验证、访问控制和日志审计四个方面。

3.1 密钥的安全存储

Harbor不会把用户的私钥存在自己的服务器上,而是要求用户自己保管私钥,或者用硬件安全模块(HSM)来存储。HSM是专门用来存储密钥的硬件设备,就算服务器被攻破,HSM里的密钥也不会被泄露。

另外,Harbor还支持密钥的定期轮换,就是每隔一段时间换一次密钥对,就算旧的密钥不小心泄露了,新的密钥也能保证后续的签名安全。

3.2 签名的强制验证

Harbor的项目管理员可以设置项目的镜像验证规则,比如要求所有拉取的镜像都必须有合法的签名,没有签名的镜像一律不能拉取。这样就能避免开发者因为疏忽,拉到没有签名的不安全镜像。

设置强制验证的示例,技术栈:Shell(Harbor CLI命令):

# 给my-project项目设置强制验证签名的规则,替换成自己的Harbor地址和项目名
harbor project update --address https://your-harbor-address --name my-project --verify-signatures true

设置完成后,任何拉取这个项目里镜像的操作,都会被强制验证签名,没有签名的镜像直接被拒绝拉取。

3.3 访问控制

Harbor的签名操作只有项目管理员才能做,普通成员只能拉取镜像,不能给镜像签名。这样就能避免普通成员不小心篡改签名,或者用自己的私钥给镜像签名,导致验证不通过的问题。

另外,Harbor还支持给不同的项目设置不同的密钥对,比如开发项目用一套密钥,生产项目用另一套密钥,就算开发项目的密钥泄露了,生产项目的镜像也不会受影响。

3.4 日志审计

Harbor会记录所有和签名相关的操作,比如谁什么时候给哪个镜像签了名,谁什么时候拉取了镜像,验证签名的结果是什么。这些日志会保存一段时间,管理员可以随时查看,一旦发现异常操作,就能及时处理。

查看签名日志的示例,技术栈:Shell(Harbor CLI命令):

# 查看my-project项目的签名相关日志,替换成自己的Harbor地址和项目名
harbor audit log list --address https://your-harbor-address --project my-project --type image_sign

这个命令会输出所有和镜像签名相关的日志,包括操作人、操作时间、操作结果等信息。

四、应用场景、优缺点和注意事项

4.1 应用场景

Harbor镜像签名的应用场景主要有三个:第一个是生产环境的镜像拉取,生产环境对安全性要求高,必须保证拉取的镜像没有被篡改;第二个是跨团队的镜像共享,比如A团队把镜像推到Harbor,B团队拉取的时候,通过签名验证就能确定镜像的来源和完整性;第三个是合规性要求,很多行业比如金融、医疗,要求所有的软件都有可信的来源,镜像签名就能满足这个要求。

4.2 技术优缺点

优点方面,首先是安全性高,通过非对称加密的签名机制,能有效防止镜像被篡改和伪造;其次是集成方便,Harbor把签名机制集成到了自己的系统里,开发者不用单独学习Notary的操作,就能完成签名和验证;第三是灵活性强,管理员可以根据自己的需求设置验证规则,比如强制验证、不同项目用不同密钥等。

缺点方面,首先是有一定的学习成本,虽然Harbor集成了签名机制,但还是需要开发者了解非对称加密、Notary等相关知识;其次是会增加少量的操作步骤,比如生成密钥、导入公钥、给镜像签名等,会比普通的推镜像多花一点时间;第三是对旧版本的Docker和Harbor支持不好,旧版本的Docker可能不支持签名验证,需要升级版本才能使用。

4.3 注意事项

首先是私钥的保管,私钥一定要存在安全的地方,比如硬件安全模块、加密的U盘,不能存在公共服务器或者随便分享给别人;其次是密钥的定期轮换,建议每隔3到6个月换一次密钥对,就算旧的密钥没有泄露,也能降低安全风险;第三是版本的兼容性,使用Harbor签名机制的时候,要确保Docker和Harbor的版本是兼容的,不然可能会出现验证失败的问题;第四是强制验证的设置,生产环境一定要设置强制验证签名,不能让开发者随便拉取没有签名的镜像。

五、文章总结

Harbor的镜像签名机制是保障容器镜像安全的重要手段,它基于非对称加密和Notary项目,通过给镜像盖“专属印章”的方式,保证镜像的完整性和来源可信。Harbor还通过密钥安全存储、强制验证、访问控制和日志审计等措施,进一步提升了签名体系的安全性。

在实际使用中,开发者只要按照规范生成密钥、导入公钥、给镜像签名,就能有效避免拉到被篡改的镜像。虽然签名机制有一定的学习成本和操作步骤,但相对于容器安全的重要性来说,这些成本都是值得的。