如何安全配置CI服务器以对二进制文件进行数字签名? [英] How do I securely configure a CI server to digitally sign binaries?

查看:394
本文介绍了如何安全配置CI服务器以对二进制文件进行数字签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有许多网站解释如何在 .pfx 证书文件上运行 signtool.exe 下至:

  signtool.exe sign / f mycert.pfx / p mypassword / t http://timestamp.server.com \ 
/ d我的说明file1.exe file2.exe

持续集成CI过程设置(使用TeamCity),与大多数CI过程一样,执行一切:检出源代码,编译,将所有.exes签名,将软件包签入安装程序,并签署安装程序.exe。目前有3个构建代理,运行相同的虚拟机,任何一个都可以运行此过程。



不安全的实现



为了完成今天,我做一对夫妇Bad Things(TM)的安全性:.pfx文件是在源代码控制,它的密码是在构建脚本(也在源代码控制)。这意味着任何有权访问源代码仓库的开发人员可以使用pfx文件,并做任何他们想要的恶意内容。 (我们是一个相对较小的开发商店,并相信每个有访问权限的人,但显然这还不太好)。



最终的安全实现



所有我可以找到的正确,这是你:




  • 保持pfx和

  • 仅指定几个人可以访问签名文件
  • $ b $ b
  • 只有在未连接的专用计算机上签署最终版本,该计算机保存在锁定的文件库中,直到您需要为此代码签名仪式带出。



虽然我可以看到这个安全性的优点。它是一个非常沉重的过程,通过这个过程,安全地保存证书的备份,确保代码签名机处于工作状态等)。



我确定有些人跳过步骤,只是手动签名文件与存储在他们的个人系统上的证书,但这仍然不是很大。



它也与在安装程序中使用的签名文件不兼容(这也是由构建服务器构建的) - 这在您已安装的.exe有一个UAC提示以获得管理员访问。



中间地带?



更关心不向用户展示一个可怕的不受信任的应用程序UAC提示,而不是证明它是我的公司。同时,在每个开发人员(加上QA和高级技术支持)访问的源代码存储库中存储私钥和密码显然不是一个好的安全实践。



我想要的CI服务器仍然在构建过程中,像今天一样,但没有密码(或证书的私钥部分)以供访问源代码存储库的每个人访问。



有没有办法保持密码不建立或安全某种方式?我应该告诉signtool使用证书存储(我怎么做,有3个构建代理和构建作为非交互式用户帐户运行)?还有什么?

解决方案

我最后对@giulioVlan建议的方法做了一个非常相似的方法, b
$ b

MSBuild任务



我创建了一个新的MSBuild任务执行signtool.exe。此任务有两个主要目的:




  • 隐藏密码以防显示

  • 可以在失败时重试时间戳服务器

  • 可以轻松调用



资料来源: https://gist.github.com/gregmac/4cfacea5aaf702365724



这特别需要所有输出,并通过一个sanitizer函数运行它,用所有*替换密码。



我不知道一个方法来检查正常的MSBuild命令,所以如果你在命令行上直接传递密码到signtool.exe使用它将显示密码 -



注册表中的密码



我辩论了一个几个方法来存储密码带外,并最终结算使用注册表。它很容易从MSBuild访问,它是相当容易手动管理,如果用户没有RDP和远程注册表访问机器,它实际上是相当安全的(任何人都可以说吗?



这可以很容易地通过msbuild读取:

  $(注册表:HKEY_LOCAL_MACHINE\SOFTWARE\1公司Dev @ CodeSigningCertPassword)
pre>

并且很容易通过regedit管理:





为什么不在其他地方?




  • 在构建脚本中:任何具有源代码的人都可以看到

  • 在源代码控制中加密/混淆/隐藏:如果有人获得源代码的副本

  • 环境变量:在Teamcity Web UI中,每个构建代理都有一个详细页面,它实际显示所有环境变量及其值。

  • 构建服务器上的文件:可能,但似乎更有可能无意中通过文件共享访问,

    在标签中:

     < Import Project =signtool.msbuild.tasks/> 

    (你也可以把这个文件放在其他任务的通用文件中, p>

    然后,无论您要用于签名的目标:

      ; SignTool SignFiles =file1.exe; file2.exe
    PfxFile =cert.pfx
    PfxPassword =$(注册表:HKEY_LOCAL_MACHINE\SOFTWARE\1公司Dev @ CodeSigningCertPassword)
    TimestampServer =http://timestamp.comodoca.com/authenticode;http://timestamp.verisign.com/scripts/timstamp.dll/>

    到目前为止,这个功能很好。


    There are many sites that explain how to run signtool.exe on a .pfx certificate file, which boil down to:

    signtool.exe sign /f mycert.pfx /p mypassword /t http://timestamp.server.com \
      /d "My description"   file1.exe file2.exe
    

    I have a continuous integration CI process setup (using TeamCity) which like most CI processes, does everything: checks out source, compiles, signs all .exes, packages into an installer, and signs the installer .exe. There are currently 3 build agents, running identical VMs, and any of them can run this process.

    Insecure implementation

    To accomplish this today, I do a couple Bad Things(TM) as far as security is concerned: the .pfx file is in source control, and the password for it is in the build script (also in source control). This means that any developers with access to source code repository can take the pfx file and do whatever nefarious things they'd like with. (We're a relatively small dev shop and trust everyone with access, but clearly this still isn't good).

    The ultimate secure implementation

    All I can find about doing this "correctly", is that you:

    • Keep the pfx and password on some secure medium (like an encrypted USB drive with finger-based unlock), and probably not together
    • Designate only a couple of people to have access to sign files
    • Only sign final builds on a non-connected, dedicated machine that's kept in a locked-up vault until you need to bring it out for this code-signing ceremony.

    While I can see merit in the security of this.. it is a very heavy process, and expensive in terms of time (running through this process, securely keeping backups of certificates, ensuring the code-signing machine is in a working state, etc).

    I'm sure some people skip steps and just manually sign files with the certificate stored on their personal system, but that's still not great.

    It also isn't compatible with signing files that are then used within the installer (which is also built by the build server) -- and this is important when you have an installed .exe that has a UAC prompt to get admin access.

    Middle ground?

    I am far more concerned with not presenting a scary "untrusted application" UAC prompt to users than proving it is my company. At the same time, storing the private key AND password in the source code repository that every developer (plus QA and high-tier tech support) have access to is clearly not a good security practice.

    What I'd like is for the CI server to still sign during the build process like it does today, but without the password (or private key portion of the certificate) to be accessible to everyone with access to the source code repository.

    Is there a way to keep the password out of the build or secure somehow? Should I be telling signtool to use a certificate store (and how do I do that, with 3 build agents and the build running as a non-interactive user account)? Something else?

    解决方案

    I ended up doing a very similar approach to what @GiulioVlan suggested, but with a few changes.

    MSBuild Task

    I created a new MSBuild task that executes signtool.exe. This task serves a couple main purposes:

    • It hides the password from ever being displayed
    • It can retry against the timestamp server(s) upon failures
    • It makes it easy to call

    Source: https://gist.github.com/gregmac/4cfacea5aaf702365724

    This specifically takes all output and runs it through a sanitizer function, replacing the password with all *'s.

    I'm not aware of a way to censor regular MSBuild commands, so if you pass the password on commandline directly to signtool.exe using it will display the password -- hence the need for this task (aside from other benefits).

    Password in registry

    I debated about a few ways to store the password "out-of-band", and ended up settling on using the registry. It's easy to access from MSBuild, it's fairly easy to manage manually, and if users don't have RDP and remote registry access to the machine, it's actually reasonably secure (can anyone say otherwise?). Presumably there are ways to secure it using fancy GPO stuff as well, but that's beyond the length I care to go.

    This can be easily read by msbuild:

    $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\1 Company Dev@CodeSigningCertPassword)
    

    And is easy to manage via regedit:

    Why not elsewhere?

    • In the build script: it's visible by anyone with source code
    • Encrypted/obfuscated/hidden in source control: if someone gets a copy of the source, they can still figure this out
    • Environment variables: In the Teamcity web UI, there is a detail page for each build agent that actually displays all environment variables and their values. Access to this page can be restricted but it means some other functionality is also restricted
    • A file on the build server: Possible, but seems a bit more likely it's inadvertently made accessible via file sharing or something

    Calling From MSBuild

    In the tag:

    <Import Project="signtool.msbuild.tasks"/>
    

    (You could also put this in a common file with other tasks, or even embed directly)

    Then, in whichever target you want to use for signing:

    <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" />
    

    So far this works well.

    这篇关于如何安全配置CI服务器以对二进制文件进行数字签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆