有许多网站可以解释如何在signtool.exe
证书文件上运行.pfx
,该文件归结为:
signtool.exe sign /f mycert.pfx /p mypassword /t http://timestamp.server.com \
/d "My description" file1.exe file2.exe
我有一个持续集成的CI流程设置(使用TeamCity),与大多数CI流程一样,完成所有工作:检查源代码,编译,签署所有.exes,将软件包签入安装程序,然后签署安装程序.exe。目前有3个构建代理程序,运行相同的VM,并且其中任何一个都可以运行此过程。
为了实现这一点,就安全性而言,我做了一些Bad Things(TM):.pfx文件在源代码管理中,并且它的密码在构建脚本中(也在源代码管理中)。这意味着任何能够访问源代码存储库的开发人员都可以获取pfx文件并执行他们喜欢的任何恶意内容。 (我们是一个相对较小的开发商店,相信每个有访问权限的人,但显然这仍然不是好事。)
我能找到的所有这些"正确",就是你:
虽然我可以看到这个安全性的优点..这是一个非常繁重的过程,并且在时间方面很昂贵(运行此过程,安全地保留证书备份,确保代码签名机器正常工作国家等)。
我确定有些人会跳过步骤,只是手动签署存储在个人系统上的证书的文件,但这仍然不是很好。
它也不兼容在安装程序中使用的签名文件(也由构建服务器构建) - 当您安装了具有UAC提示符的.exe时,这一点非常重要。获取管理员权限。
我更关心的是没有提出一个可怕的"不受信任的应用程序" UAC提示用户比证明它是我的公司。同时,将私钥和密码存储在每个开发人员(以及QA和高级技术支持)都可以访问的源代码存储库中显然不是一个好的安全实践。
我希望CI服务器在构建过程中仍然像今天一样签名,但没有密码(或证书的私钥部分)可供访问源的每个人访问代码库。
有没有办法将密码保留在构建之外或以某种方式保护?我应该告诉signtool使用证书存储区(我如何使用3个构建代理程序和构建作为非交互式用户帐户运行)?别的什么?
答案 0 :(得分:7)
我最终采用了与@GiulioVlan建议的非常类似的方法,但稍作修改。
我创建了一个执行signtool.exe的新MSBuild任务。此任务有两个主要目的:
来源:https://gist.github.com/gregmac/4cfacea5aaf702365724
这专门接受所有输出并通过清洁功能运行它,用全部*替换密码。
我不知道审查常规MSBuild命令的方法,因此如果您使用命令行直接将密码传递给signtool.exe将显示密码 - 因此需要执行此任务(除了其他好处)
我讨论了几种存储密码“带外”的方法,最后决定使用注册表。它很容易从MSBuild访问,手动管理相当容易,如果用户没有RDP和远程注册表访问机器,它实际上是相当安全的(否则有人会这样说吗?)。据推测,有很多方法可以使用花哨的GPO来保护它,但这超出了我想要的时间。
这可以通过msbuild轻松阅读:
$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\1 Company Dev@CodeSigningCertPassword)
通过注册表很容易管理:
在标签中:
<Import Project="signtool.msbuild.tasks"/>
(你也可以把它放在一个包含其他任务的公共文件中,甚至可以直接嵌入)
然后,在您要用于签名的任何目标中:
<SignTool SignFiles="file1.exe;file2.exe"
PfxFile="cert.pfx"
PfxPassword="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\1 Company Dev@CodeSigningCertPassword)"
TimestampServer="http://timestamp.comodoca.com/authenticode;http://timestamp.verisign.com/scripts/timstamp.dll" />
到目前为止,效果很好。
答案 1 :(得分:0)
一种常见技术是在版本控制中保留密钥和证书,但使用密码或密码来保护它们。密码保存在机器本地的环境变量中,可以从脚本轻松访问(例如%PASSWORD_FOR_CERTIFICATES%
)。
必须注意不要以纯文本格式记录这些值。