如何在使用WiX安装期间加密app.config文件部分?

时间:2021-10-05 07:29:05

I have found an example for encrypting a web.config during installation here, but my app is a windows service. The aspnetreg_iis method works only for web.config files.

我在安装过程中找到了加密web.config的示例,但我的应用程序是一个Windows服务。 aspnetreg_iis方法仅适用于web.config文件。

I know how to programatically encrypt the config file, but I don't think I can do that using WiX. Am I wrong? Any ideas?

我知道如何以编程方式加密配置文件,但我不认为我可以使用WiX做到这一点。我错了吗?有任何想法吗?

2 个解决方案

#1


4  

Here is what I ended up with...

这是我最终得到的......

I used WiX and DTF to created a managed code Custom Action to encrypt a given section of a config file:

我使用WiX和DTF创建了一个托管代码Custom Action来加密配置文件的给定部分:

    public static void EncryptConfig(Session session)
    {

        var configPath = session["APPCONFIGPATH"];
        var sectionToEncrypt = session["SECTIONTOENCRYPT"];

        var fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configPath;
        var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        ConfigurationSection section = configuration.GetSection(sectionToEncrypt);

        if (!section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            section.SectionInformation.ForceSave = true;
            configuration.Save(ConfigurationSaveMode.Modified);

        }
    }

Part of my lack of understanding that prompted this question was not knowing that you can safely create custom actions in managed code using DTF. Documentation is sparse on DTF, but once you get it working, it is great.

我提到这个问题缺乏理解的部分原因是不知道您可以使用DTF在托管代码中安全地创建自定义操作。 DTF上的文档很少,但是一旦你开始工作,它就很棒了。

I found that this only worked if I scheduled the custom action after InstallFinalize.

我发现只有在InstallFinalize之后安排自定义操作时,这才有效。

Here is the WiX config to make it happen:

以下是实现它的WiX配置:

<InstallExecuteSequence>
  <Custom Action="EncryptConfigurationFiles" After="InstallFinalize" />
</InstallExecuteSequence>

<Fragment>
    <Binary Id="YourProject.CustomActions.dll" SourceFile="$(var.YourProject.CustomActions.TargetDir)$(var.YourProject.CustomActions.TargetName).CA.dll" />
    <CustomAction Id="EncryptConfigurationFiles" BinaryKey="YourProject.CustomActions.dll" DllEntry="EncryptConfig" Return="check" />
</Fragment>

These blogs/sites helped me get there and much of the code from above was derived from them:

这些博客/网站帮助我实现了目标,上面的大部分代码都源于它们:

http://geekswithblogs.net/afeng/Default.aspx http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx http://blogs.msdn.com/jasongin/archive/2008/07/09/votive-project-platform-configurations.aspx

http://geekswithblogs.net/afeng/Default.aspx http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx http://blogs.msdn.com/jasongin/archive/2008/07/ 09 /还愿项目平台,configurations.aspx

@PITADeveloper... Thanks for the response. I found that I did not need to load the assembly to encrypt the config file.

@PITADeveloper ...感谢您的回复。我发现我不需要加载程序集来加密配置文件。

If you use this, you should use a try catch and return an ActionResult... The above is pseudo-code.

如果你使用它,你应该使用try catch并返回一个ActionResult ...上面是伪代码。

Finally, I'm using the DataProtectionConfigurationProvider. For the RSA Provider, I think there are a couple more hoops to jump through.

最后,我正在使用DataProtectionConfigurationProvider。对于RSA提供商,我认为还有更多的环节可以跳过。

I hope this helps someone!

我希望这可以帮助别人!

#2


3  

You should be able to do it within a custom action. The catch that I've found is that loading an assembly for an ExeConfigurationFileMap will throw an exception, but you can handle that by adding an AssemblyResolve handler to the AppDomain. This is kind of a hack-up from a rich-client app I wrote to encrypt/decrypt protected configuration sections using a machine encryption key. It's probably not the prettiest code, but I'm hoping you can get the picture from it. This code assumes that you have the ProtectionProvider you want to use defined in the config file.

您应该能够在自定义操作中执行此操作。我发现的问题是为ExeConfigurationFileMap加载程序集会引发异常,但您可以通过向AppDomain添加AssemblyResolve处理程序来处理它。这是一种来自我使用机器加密密钥加密/解密受保护配置部分的富客户端应用程序的hack-up。它可能不是最漂亮的代码,但我希望你能从中得到它的图片。此代码假定您具有要在配置文件中定义的ProtectionProvider。

//class global
static System.Reflection.Assembly DefiningAssembly;

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

static System.Reflection.Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
     return DefiningAssembly;
}

Then, you can load your configuration like this:

然后,您可以像这样加载配置:

DefiningAssembly = System.Reflection.Assembly.LoadFrom("path to defining assembly for config");

//Set the Configuration using an ExeConfigurationFileMap - This works for any .config file.
ExeConfigurationFileMap CfgMap = new ExeConfigurationFileMap();
CfgMap.ExeConfigFilename = "path to config file";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(CfgMap, ConfigurationUserLevel.None);

List<string> DefiningAssemblyTypes = new List<string>();
foreach (System.Type type in DefiningAssembly.GetExportedTypes())
{
     DefiningAssemblyTypes.Add(type.Name);
}

foreach (ConfigurationSection tempSection in config.Sections)
{
     if (DefiningAssemblyTypes.Contains(tempSection.ElementInformation.Type.Name))
     {
          section = tempSection;
          break;
     }
}
ProtectionProviderName = section.SectionInformation.ProtectionProvider.Name;
section.SectionInformation.ProtectSection(ProtectionProviderName);
config.Save(ConfigurationSaveMode.Minimal, true);

I hope this helps you, best of luck.

祝你好运,祝你好运。

#1


4  

Here is what I ended up with...

这是我最终得到的......

I used WiX and DTF to created a managed code Custom Action to encrypt a given section of a config file:

我使用WiX和DTF创建了一个托管代码Custom Action来加密配置文件的给定部分:

    public static void EncryptConfig(Session session)
    {

        var configPath = session["APPCONFIGPATH"];
        var sectionToEncrypt = session["SECTIONTOENCRYPT"];

        var fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configPath;
        var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        ConfigurationSection section = configuration.GetSection(sectionToEncrypt);

        if (!section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            section.SectionInformation.ForceSave = true;
            configuration.Save(ConfigurationSaveMode.Modified);

        }
    }

Part of my lack of understanding that prompted this question was not knowing that you can safely create custom actions in managed code using DTF. Documentation is sparse on DTF, but once you get it working, it is great.

我提到这个问题缺乏理解的部分原因是不知道您可以使用DTF在托管代码中安全地创建自定义操作。 DTF上的文档很少,但是一旦你开始工作,它就很棒了。

I found that this only worked if I scheduled the custom action after InstallFinalize.

我发现只有在InstallFinalize之后安排自定义操作时,这才有效。

Here is the WiX config to make it happen:

以下是实现它的WiX配置:

<InstallExecuteSequence>
  <Custom Action="EncryptConfigurationFiles" After="InstallFinalize" />
</InstallExecuteSequence>

<Fragment>
    <Binary Id="YourProject.CustomActions.dll" SourceFile="$(var.YourProject.CustomActions.TargetDir)$(var.YourProject.CustomActions.TargetName).CA.dll" />
    <CustomAction Id="EncryptConfigurationFiles" BinaryKey="YourProject.CustomActions.dll" DllEntry="EncryptConfig" Return="check" />
</Fragment>

These blogs/sites helped me get there and much of the code from above was derived from them:

这些博客/网站帮助我实现了目标,上面的大部分代码都源于它们:

http://geekswithblogs.net/afeng/Default.aspx http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx http://blogs.msdn.com/jasongin/archive/2008/07/09/votive-project-platform-configurations.aspx

http://geekswithblogs.net/afeng/Default.aspx http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx http://blogs.msdn.com/jasongin/archive/2008/07/ 09 /还愿项目平台,configurations.aspx

@PITADeveloper... Thanks for the response. I found that I did not need to load the assembly to encrypt the config file.

@PITADeveloper ...感谢您的回复。我发现我不需要加载程序集来加密配置文件。

If you use this, you should use a try catch and return an ActionResult... The above is pseudo-code.

如果你使用它,你应该使用try catch并返回一个ActionResult ...上面是伪代码。

Finally, I'm using the DataProtectionConfigurationProvider. For the RSA Provider, I think there are a couple more hoops to jump through.

最后,我正在使用DataProtectionConfigurationProvider。对于RSA提供商,我认为还有更多的环节可以跳过。

I hope this helps someone!

我希望这可以帮助别人!

#2


3  

You should be able to do it within a custom action. The catch that I've found is that loading an assembly for an ExeConfigurationFileMap will throw an exception, but you can handle that by adding an AssemblyResolve handler to the AppDomain. This is kind of a hack-up from a rich-client app I wrote to encrypt/decrypt protected configuration sections using a machine encryption key. It's probably not the prettiest code, but I'm hoping you can get the picture from it. This code assumes that you have the ProtectionProvider you want to use defined in the config file.

您应该能够在自定义操作中执行此操作。我发现的问题是为ExeConfigurationFileMap加载程序集会引发异常,但您可以通过向AppDomain添加AssemblyResolve处理程序来处理它。这是一种来自我使用机器加密密钥加密/解密受保护配置部分的富客户端应用程序的hack-up。它可能不是最漂亮的代码,但我希望你能从中得到它的图片。此代码假定您具有要在配置文件中定义的ProtectionProvider。

//class global
static System.Reflection.Assembly DefiningAssembly;

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

static System.Reflection.Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
     return DefiningAssembly;
}

Then, you can load your configuration like this:

然后,您可以像这样加载配置:

DefiningAssembly = System.Reflection.Assembly.LoadFrom("path to defining assembly for config");

//Set the Configuration using an ExeConfigurationFileMap - This works for any .config file.
ExeConfigurationFileMap CfgMap = new ExeConfigurationFileMap();
CfgMap.ExeConfigFilename = "path to config file";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(CfgMap, ConfigurationUserLevel.None);

List<string> DefiningAssemblyTypes = new List<string>();
foreach (System.Type type in DefiningAssembly.GetExportedTypes())
{
     DefiningAssemblyTypes.Add(type.Name);
}

foreach (ConfigurationSection tempSection in config.Sections)
{
     if (DefiningAssemblyTypes.Contains(tempSection.ElementInformation.Type.Name))
     {
          section = tempSection;
          break;
     }
}
ProtectionProviderName = section.SectionInformation.ProtectionProvider.Name;
section.SectionInformation.ProtectSection(ProtectionProviderName);
config.Save(ConfigurationSaveMode.Minimal, true);

I hope this helps you, best of luck.

祝你好运,祝你好运。