我应该如何处理源代码管理项目中的秘密值?

Posted

技术标签:

【中文标题】我应该如何处理源代码管理项目中的秘密值?【英文标题】:How should I handle secret values in a project in source control? 【发布时间】:2013-04-09 08:15:00 【问题描述】:

我的问题与this one 基本相同,但针对的是 Windows Store App、c# 和 Visual Studio。我想有一种简单的方法将项目中的秘密值保存在一个可以在源代码控制中忽略(未签入)的文件中。我应该如何构建我的项目以以一种易于构建/源代码控制的方式存储应用程序机密?

我的第一个想法是将它存储在一个 XML 文件中(未签入),并在运行时加载它,但这会使安装它的用户可以使用它,所以它应该在构建时完成。构建项目时,如何存储几个秘密值并让 Visual Studio 在我的代码中替换它们?

【问题讨论】:

我永远不会把秘密放在源代码管理中——当新用户加入项目时手动添加它们。 我不清楚为什么“安装它”的用户可以访问不在源代码管理中的 XML 文件。它捆绑在您的安装程序中吗?如果是这样,请将其取出并使其成为运行时依赖项。 @PeterRitchie 这正是我要说的。我的问题意味着我怎样才能使项目构建过程变得简单而不在源代码控制中具有该价值。即“检查项目,然后使用您的应用程序密码执行 x”。为了清楚起见,我进行了编辑。 @Kohanz 例如,如果该值存储在 xml 文件中,并将其作为内容文件复制并在运行时读取,则安装该应用程序的用户将有权访问该文件文件/值,就像包中包含的任何图像资产一样。 @roiuser 是的,所以我建议您不要将该 XML 文件作为内容包含在内,而只是从预定位置读取它。您可能应该重构它,以便从构建中排除的 XML 文件仅包含您不想共享的秘密字段(例如密码) 【参考方案1】:

在我公司,我们决定为您提供以下解决方案。在配置文件中,我们将部分与外部配置中的“秘密”值链接起来。 外部配置在源代码控制上。首先不是,但是在我们的构建服务器丢失磁盘时出现问题后,我们决定将其存储在有备份的地方更安全。源代码管理中的文件夹(也可以在文件服务器上)实际上仅限于对需要此文件的人进行读写。构建过程结帐“项目”文件夹加上“配置”文件夹并进行构建。构建“配置”文件夹后删除。对构建服务器的访问也受到限制。

【讨论】:

我真的在 Visual Studio 中寻找更多关于如何存储/替换这些值的技术解决方案。我不担心在任何地方备份或签入应用程序机密。 所以将副本配置文件存储在几乎没有人可以访问的地方以及构建服务器结帐项目和此配置文件上。您也可以使用像 SnowCheetach 这样的工具,只将 transfarmations 保存在“安全”的地方。更多关于这里的工具:hanselman.com/blog/… 这没有帮助。我从来没有提到过构建服务器,这仍然没有告诉我如何或何时读取该文件。我的问题是关于阅读和使用价值观的技术,而不是关于保护它的语义【参考方案2】:

一种选择是将机密存储在源代码管理中,但以加密形式存储。在您的开发或构建环境中,使用环境变量来存储密钥并即时解密。这样您就可以获得源代码控制的好处,同时保证您的信息安全。

即使你使用 app.config 或 web.config 也可以这样做,你只需要在启动时从代码中修改配置。

埃里克

【讨论】:

【参考方案3】:

更新 如果您将秘密放在不受信任的区域(例如公共源代码控制),则它很容易受到攻击。即使它是加密的,只要足够努力,它也可以被检索到。

真正让它遥不可及的唯一方法是拥有一个与第 3 方 API 交互的外部服务。这有其自身的权衡(例如,您在 cmets 中提到的用户身份验证)。特别是如果您的开发人员在测试时需要使用 3rd 方 API,我认为没有其他替代方案可以限制秘密的公开。

【讨论】:

这与应用程序本身无关。这是针对第三方 API 进行身份验证的秘密。我从来没有说过这是为了应用程序的配置。 Live Connect 集成是第 3 方集成,但它是在 Windows 应用商店级别而不是应用级别设置的。次优的解决方法是有一个中间服务来回答来自您的应用程序的请求并将它们转发到带有密钥的第 3 方 API。根据谁控制服务器安全,服务器端机密可能位于服务器上的配置文件中,而不是其他任何地方。 您的建议是添加额外的服务器以防止 API 机密?我仍然必须以某种方式对用户进行身份验证,但现在我有一个额外的跳跃。这似乎是多余的,并且没有提供比加密值更好的东西。除此之外,这与保护最终用户的密钥有关,而不是我的问题,这与保护密钥不受源代码控制/其他开发人员的影响有关。 外部服务可防止用户和开发人员发现。如果你把它放在源代码中,无论是否加密,它都是易受攻击的。您只是想阻止公共源代码控制冲浪者获取它吗? 另请注意,如果您将其加密存储在源代码中,我假设您仍然需要在将其发送到第 3 方 API 之前对其进行解密。所以现在问题已经转移到保护解密密钥而不是秘密上。【参考方案4】:

在您的项目中创建一个新的类文件,其中包含所有秘密值的插槽,并为所有这些值保存虚拟/测试值。将其与项目的其余部分一起检查到源代码控制中,以便任何构建它但无法访问机密的人都将获得某种测试版本。

然后,使用真正的秘密值创建该类文件的副本,并将其放在源代码控制之外的某个位置。在预构建事件中编写一个批处理脚本来查找此类文件,如果找到,则用它替换项目中包含的虚拟文件。

这样,您的项目仍然可以在源代码管理中,任何人都可以检查、构建并在测试模式下运行它。您的秘密文件/值仅存储在您的构建服务器上,因此只有在您构建项目时,它才会具有真正的值。

请记住在某处备份您的机密文件。还要记住 .NET 代码可以很容易地反编译,因此您的秘密可能不像您希望的那样秘密 - 任何具有 .NET 反射器的用户都可以看到您的发布程序集中的所有代码,包括您的秘密类。

【讨论】:

以上是关于我应该如何处理源代码管理项目中的秘密值?的主要内容,如果未能解决你的问题,请参考以下文章

您如何处理公共 git 存储库中的敏感数据?

如何处理 Google App Engine 中的秘密?

当我推送到 GitHub 时如何处理秘密 API 密钥,以便在克隆存储库时我的项目仍然有效?

我应该如何处理 Python 中的包含范围?

我应该如何处理数据库项目中的用户?

KnockoutJS:我应该如何处理繁重的小部件初始化代码?