Как зашифровать разделы файла app.config во время установки с помощью WiX? - PullRequest
7 голосов
/ 21 ноября 2008

Я нашел пример для шифрования web.config во время установки здесь , но мое приложение представляет собой службу Windows. Метод aspnetreg_iis работает только для файлов web.config.

Я знаю, как программно зашифровать файл конфигурации, но я не думаю, что смогу сделать это с помощью WiX. Я ошибся? Есть идеи?

Ответы [ 2 ]

4 голосов
/ 25 ноября 2008

Вот что у меня получилось ...

Я использовал 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);

        }
    }

Часть моего непонимания, которая вызвала этот вопрос, заключалась в том, что я не знал, что вы можете безопасно создавать настраиваемые действия в управляемом коде, используя DTF. Документация на DTF редкая, но как только она заработает, это здорово.

Я обнаружил, что это работает, только если я запланировал настраиваемое действие после InstallFinalize.

Вот конфигурация 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>

Эти блоги / сайты помогли мне попасть туда, и большая часть приведенного выше кода была получена из них:

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

@ PITADeveloper ... Спасибо за ответ. Я обнаружил, что мне не нужно загружать сборку для шифрования файла конфигурации.

Если вы используете это, вы должны использовать try catch и вернуть ActionResult ... Выше приведен псевдокод.

Наконец, я использую DataProtectionConfigurationProvider. Для провайдера RSA, я думаю, есть еще пара обручей, через которые можно прыгнуть.

Надеюсь, это кому-нибудь поможет!

3 голосов
/ 21 ноября 2008

Вы должны быть в состоянии сделать это в рамках специального действия. Уловка, которую я обнаружил, заключается в том, что загрузка сборки для ExeConfigurationFileMap вызовет исключение, но вы можете справиться с этим, добавив обработчик AssemblyResolve в домен приложения. Это своего рода взлом из приложения с расширенными возможностями, которое я написал для шифрования / дешифрования защищенных разделов конфигурации с помощью ключа шифрования компьютера. Это, вероятно, не самый красивый код, но я надеюсь, что вы можете получить картину из него. Этот код предполагает, что у вас есть 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;
}

Затем вы можете загрузить свою конфигурацию следующим образом:

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);

Надеюсь, это поможет вам, удачи.

...