65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Azure Websites 和 GitHub 保管敏感配置文件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (7投票s)

2013 年 6 月 4 日

CPOL

9分钟阅读

viewsIcon

53884

downloadIcon

121

一种将敏感配置值(如连接字符串)保存在源代码控制存储库之外,但仍可供本地和云应用程序使用的策略。我们特别关注 Azure 网站和 GitHub。

引言

随着 Azure 网站的推出,它提供了从 TFS 和 GitHub 等源代码控制系统进行的自动部署,配置到 Azure 的自动部署变得相对容易,这样您就可以进行签入并观察部署的发生。您找到的大多数在线演示都建议,如果您正在为部署构建网站并且需要存储敏感值(如存储连接字符串),则应将它们放在您的web.config中。如果您使用提供对源代码受限访问的源代码控制存储库(如 TFS),则可以愉快地将这些值添加到您的web.config并进行签入,并知道它们不会被他人看到。但是,**如果您使用的是公共源代码控制系统(如 GitHub),您可能不希望他人看到您的敏感配置设置。**

Azure 网站允许您通过 Azure 管理门户修改配置设置,这在一定程度上解决了这个问题,让您可以确保您的云网站具有正确的配置值,并确保它们是安全的。但是,对于您希望在本地web.config以及在云中都使用的设置呢?例如:

  • 服务总线连接字符串
  • 存储连接字符串
  • OAuth 提供商秘密信息等....

如果您将它们添加到您的web.config并将其签入 GitHub,任何人都可以看到(并可能使用)它们。但是,如果您仅通过 Azure 管理门户进行添加,则它们在本地将不可用。当然,必须有一种方法可以两者兼顾,对吗?在本文中,我将介绍一种避免此问题的方法,使您可以在本地存储秘密配置设置,将其排除在源代码控制之外,同时还在云中使用正确的设置。

注意:如果您使用的是Node.js,我发现了一篇非常好的教程,它解决了相同的问题,在此处

源代码下载

本文的所有源代码都可以在此处找到。我还为无法在 CodeProject 上访问 GitHub 的用户上传了解决方案的 zip 文件

背景

到目前为止,我看到有几种将配置秘密排除在 GitHub 之外的方法。第一种涉及

  1. 添加一个包含秘密值的配置文件
  2. 进行签入
  3. 使用git update-index --assume-unchanged命令告诉 Git 在未来忽略此文件的更改,并将其添加到您的.gitignore文件中
  4. 对此文件进行更改,这些更改将不会被签入
虽然这在您只有一个分支时有效,但一旦您切换分支,此方法就会失效,因为 Git 会检测到您的配置文件中的更改,您将不得不对其进行撤销或签入。

另一种选择是使用提交前和提交后钩子来在签入和签出时自动添加/删除您的秘密配置值,如此处所述。不幸的是,提供的解决方案使用了 Python 脚本,我们无法从标准的 Visual Studio ASP.NET 解决方案中自动使用它。

我们想要一种易于实现、适用于 ASP.NET Web 项目(包括 MVC 和 ASP.NET Web pages)并与 Azure 和 GitHub 集成的方法。这正是我将要提供的。

解决方案

入门

为了给您提供这项技术如何工作的完整解释,我们首先需要设置一个网站并将其从 GitHub 部署到 Azure。为此,我们需要

  • 使用 MVC 4 Internet 应用程序模板在 Visual Studio 2012 中创建一个示例 ASP.NET 网站
  • 配置 Git 的源代码控制,并将我们的网站签入 GitHub,以便源代码对所有人公开可见
  • 注册 Azure 试用账户
  • 创建一个网站
  • 设置从 GitHub 存储库到 Azure 的自动部署

创建网站并设置 GitHub 源代码控制

此处的文章提供了如何从 GitHub 设置持续部署到 Azure 的一个很好的示例,如果您不熟悉 Git 或 Azure,建议您阅读它。在我们的示例中,我已经下载了 Git Explorer for Windows,并创建了一个名为CodeProjectConfigStrategy的本地存储库,如下图所示:

接下来,我将打开 Visual Studio 2012,并创建一个新的MVC Web Application,确保其Location与我之前创建的 Git 存储库位于同一文件夹中,如下图所示:

接下来,我将排除 NuGet 包,如本文所述。我还向我的.gitignore文件添加了一个条目,以从源代码控制中排除整个/packages目录。我的解决方案现在看起来与以下类似:

最后,我将返回 GitHub Explorer,提交我的更改,然后按Sync按钮,以便将我的更改推送到 GitHub。现在我需要创建一个 Azure 网站并进行部署。

在 Azure 中创建网站并设置自动部署

如前所述,此处的文章提供了一个关于如何从 GitHub 设置自动部署的良好示例,在标题为“*Deploy files from a repository web site like BitBucket, CodePlex, Dropbox, GitHub, or Mercurial*”的部分中。如果您正在按照操作,我建议您阅读它,以便您熟悉如何将 Azure 网站与 GitHub 集成以进行自动部署。

在我的情况下,我

  1. 注册了 Azure 免费试用并登录到 Azure 管理门户
  2. 创建了一个名为codeprojectconfigstrategy的网站(http://codeprojectconfigstrategy.azurewebsites.net/
  3. 配置了网站,使其能够从我之前创建的 GitHub 存储库自动部署
最终结果是如下所示的网站,没什么特别之处。

保护我们的配置秘密安全

现在我们有了一个标准的 MVC Web 应用程序。试想一下,如果我们想添加一些需要使用配置值的内容,例如 Azure 服务总线的连接字符串,或者用于 OAuthn(使用 Facebook)的 API 密钥?这适用于您需要将敏感值存储在web.config文件中的任何情况,但我将使用 Azure 服务总线连接字符串作为示例。我们将如何处理这个问题?

为了演示目的,您可能有一些访问服务总线连接字符串的代码,如下所示:

string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); 

在您的web.config中,您可能会将 Azure 服务总线的存储连接字符串放在如下位置:

<appSettings>
    <add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://exampleservicebus.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=longlongsecretguid" /> 

现在,这在本地调试时可以正常工作,如果我们进行签入并将其部署到 Azure,也可以正常工作,因为我们的云实例将能够访问web.config中的连接字符串。但是,如果我们现在签入此文件,访问我们 GitHub 存储库的其他人可以看到并使用我们的连接字符串。那么,我们如何阻止这种情况发生呢?

将敏感配置设置移至单独的文件

首先,我们将向我们的解决方案添加两个新文件,一个名为HiddenSettings.config,另一个名为HiddenSettings.template.config。两者都应将它们的生成操作设置为Content,就像web.config文件一样。这意味着它们将在网站发布时自动部署。

接下来,我们将更新web.config文件以使用我们HiddenSettings.config文件中的值,如下更新AppSettings元素(如果您不熟悉它的工作原理,请参阅此链接):

<appSettings file="HiddenSettings.config"> 

接下来,我们打开HiddenSettings.template.config文件并添加以下内容:

<?xml version="1.0"?>
<appSettings>
</appSettings> 

然后,我们打开HiddenSettings.config文件并为所有我们想要覆盖的敏感配置设置添加条目。在我们的例子中,我们只有一个,如下所示:

 <?xml version="1.0"?>
<appSettings>
  <add key="Microsoft.ServiceBus.ConnectionString" 
value="Endpoint=sb://exampleservicebus.servicebus.windows.net/;
SharedSecretIssuer=owner;SharedSecretValue=longlongsecretguid" />
</appSettings> 

接下来,我们返回web.config文件并将敏感值替换为虚拟值,以向使用我们解决方案的其他人表明此值需要使用他们自己的选定值进行更新。

<appSettings>
    <add key="Microsoft.ServiceBus.ConnectionString" value="ThisWillBeOverriddenAtRuntimeByYourSecretValue" /> 

最后,我们在解决方案根目录中打开.gitignore文件,并为我们的HiddenSettings.config文件添加一个条目,以确保它不会被签入源代码控制。例如:

HiddenSettings.config 

添加一个生成后事件,以便我们的 HiddenSettings.config 文件将在生成服务器上自动创建

在此阶段,我们已将敏感值移至单独的配置文件,并向.gitignore添加了一个条目,以确保它们不会进入源代码控制。但是,如果我们将其签入,则部署到 Azure 将会失败,因为当在生成服务器上执行发布时,发布过程将找不到HiddenSettings.config文件,因为它不存在,因为它从未被签入。这就是我们的空HiddenSettings.template.config文件发挥作用的地方!我们将配置一个生成后事件,以便如果生成过程找不到HiddenSettings.config文件(例如,如果它在生成服务器上),它将自动创建它,并使用HiddenSettings.template.config文件的内容填充它。

为此,我们需要

  • 在记事本或其他文本编辑器中打开我们的MvcApplication1.csproj文件
  • 找到AfterBuild元素(默认情况下已注释掉)
  • 取消注释它,并用以下代码替换它:
 <Target Name="AfterBuild">
    <Copy SourceFiles="HiddenSettings.Template.config" 
    DestinationFiles="HiddenSettings.config" SkipUnchangedFiles="true" 
    Condition="!Exists('HiddenSettings.config')">
    </Copy>
  </Target> 

如您所见,这会查找HiddenSettings.config文件,如果不存在,则会创建它并将HiddenSettings.template.config的内容复制到其中。

在 Azure 中签入和更新我们的设置

我们现在可以将我们的项目签入 GitHub,同时知道我们的秘密是安全的。但是,我们需要确保这些设置在部署到 Azure 时可供我们的应用程序使用。Azure 网站允许您使用管理门户中提供的值覆盖web.config文件中的配置值。为此,我

  • 转到管理门户
  • 打开codeprojectconfigstategy网站并单击Configure选项卡
  • 导航到App Settings部分,并为Microsoft.ServiceBus.ConnectionString添加一个条目,其值指向我们的生产服务总线,如下所示:


现在我们的 Azure 网站将具有正确的值,我们的本地网站也将具有正确的值,而且我们没有任何敏感数据可供他人从 GitHub 中看到!太棒了!

Using the Code

如果您想查看解决方案,所有源代码都可以在 GitHub 此处找到。

随时根据您的意愿下载和浏览代码。微笑 | :)如果您对如何改进此解决方案有任何意见或想法,也请告诉我。

关注点

虽然这不是解决最初问题的唯一解决方案,但我认为它最能利用 ASP.NET 和 Azure 网站自带的内置功能,例如:

  • 将配置设置存储在单独的文件中
  • 利用生成后过程
  • GitHub 自动化源代码控制
  • 在 Azure 管理门户中更新应用程序设置
最后,如果您发现本文有用,请务必查看我的主要 CodeProject 文章 - https://codeproject.org.cn/Articles/584534/YouConf-Your-Live-Online-Conferencing-Tool,其中包含许多此类提示,可帮助您构建一个坚如磐石的 Azure 网站。这是我在 Azure Developer Challenge 中发现的众多发现之一。

感谢阅读,希望您学到了一些有用的东西!

历史

  • 2013/06/04 - 初始文章
  • 2013/06/09 - 除了 GitHub 链接外,还添加了源代码下载
© . All rights reserved.