Encrypted config section plus BCL.Build - asp.net

I'm trying to update LinqKit in an ASP.Net 4.0 Web Application which uses encrypted config sections to obfuscate the connectionstrings section. We also use config transforms.
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configProtectedData>
<providers>
<add keyContainerName="FooBarKeys" useMachineContainer="true" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" name="FooBarProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</configProtectedData>
<connectionStrings configProtectionProvider="FooBarProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
...
For projects targeting .Net 4.0, LinqKit 1.1.7+ depends on Microsoft.Bcl.Async, and Microsoft.Bcl.Build is required in any projects referencing class libraries which use Microsoft.Bcl.Async.
When I build, I get this error:
The "EnsureBindingRedirects" task failed unexpectedly.
System.Xml.XmlException: App.config must have root configuration element. Line 2, position 2.
at Roxel.BuildTasks.EnsureBindingRedirects.ThrowXmlException(String message, Exception inner, IXmlLineInfo info)
at Roxel.BuildTasks.EnsureBindingRedirects.LoadAppConfig(String appConfigPath)
at Roxel.BuildTasks.EnsureBindingRedirects.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
File: packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets line 97
If I change <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> to <configuration>, I get XML validation warnings for web.config:
The 'keyContainerName' attribute is not allowed.
The 'useMachineContainer' attribute is not allowed.
The 'description' attribute is not allowed.
The 'configProtectionProvider' attribute is not allowed.
The element 'connectionStrings' has invalid child element 'EncryptedData' in namespace 'http://www.w3.org/2001/04/xmlenc#'. List of possible elements expected: 'add, remove, clear'.
I tried using <configuration xmlns:c="http://schemas.microsoft.com/.NetConfiguration/v2.0">, with <c:configProtectedData> and <c:connectionStrings>. This validates, but fails at runtime:
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Error Code 0x80070032
Config Error The configuration section 'c:configProtectedData' cannot be read because it is missing a section declaration
Config Source:
5: </configSections>
**6: <c:configProtectedData>**
7: <providers>
How do I use these libraries in a .Net 4.0 Web App such that it builds, has a valid web.config and runs?

Related

How to use ASP.NET 4.8 ConfigBuilders with system.serviceModel section of web.config

I have an ASP.NET 4.8 app that I am trying to integrate configuration builders into. I have installed the NuGet package Microsoft.Configuration.ConfigurationBuilders.Environment and added the required sections to Web.config (heavily truncated here).
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
</configSections>
<configBuilders>
<builders>
<add name="EnvironmentExpand" mode="Expand" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment" />
</builders>
</configBuilders>
<system.serviceModel configBuilders="EnvironmentExpand">
....
</system.serviceModel>
</configuration>
When I run the application I get an HTTP 500 response from every action, with the message Unrecognized attribute 'configBuilders'. Intellisense in Visual Studio also highlights configBuilders and says The configBuilders attribute is not allowed.
If I remove the configBuilders attribute from system.serviceModel the application runs correctly although of course none of the placeholders in that section are expanded.
If I remove the configBuilders attribute from system.serviceModel and add it to another section, for instance connectionStrings, the application runs and the placeholders in the connectionStrings section are replaced.
Clearly there's something different about the system.serviceModel section but I don't understand what or how I can work around it so that I can replace placeholders in there.
If you look at your machine.config, you'll see that system.serviceModel is a sectionGroup and not a section. ConfigurationBuilders only apply at the section level. WCF and ASP.Net for better or worse have their large configuration divided into multiple sections.

Configuration Error on web host ,Could not load file or assembly

Please i want to solve this problem i did .aspx web application and when i try to publish it by GearHost i face this problem
Server Error in '/' Application.
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: Could not load file or assembly 'MySql.Data, Version=8.0.18.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' or one of its dependencies. The system cannot find the file specified.
Source Error:
An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
Source File: C:\home\site\wwwroot\web.config Line: 14
Assembly Load Trace: The following information can be helpful to determine why the assembly 'MySql.Data, Version=8.0.18.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' could not be loaded.
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3429.0
and my web.config is
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None"/>
</appSettings>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="MySql.Data, Version=8.0.18.0, Culture=neutral, PublicKeyToken=C5687FC88969C44D"/>
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5"/>
</system.web>
</configuration>
Please can anyone help me

Why can't I encrypt web.config/appSettings using a custom configProtectionProvider on Azure (Windows Server 2012)?

I have an MVC application which is deployed to a Windows Azure hosted service running on a Windows Server 2012 virtual machine. In the web.config file, I have 3 sections encrypted using the PKCS12ProtectedConfigurationProvider: connectionStrings, dataCacheClients, and system.net/mailSettings/smtp. Here is what the relevant sections look like:
<configuration>
...
<configProtectedData>
<providers>
<add name="CustomProvider" thumbprint="[this is secret]"
type="Pkcs12ProtectedConfigurationProvider.Pkcs12ProtectedConfigurationProvider, PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d" />
</providers>
</configProtectedData>
...
<connectionStrings configProtectionProvider="CustomProvider">
<EncryptedData ... ommitted for brevity
</connectionStrings>
...
<system.net>
<mailSettings>
<smtp configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</smtp>
</mailSettings>
</system.net>
...
<dataCacheClients configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</dataCacheClients>
...
</configuration>
All of the above works perfectly fine. When deployed to Azure, the connection strings, SMTP mail, and data cache all work. The PKCS12ProtectedConfiguration provider uses my custom certificate to decrypt the sections and all is well.
However I can't seem to use the same approach to encrypt web.config/appSettings. When I try deploying something like the following to Azure...
<configuration>
...
<appSettings configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</appSettings>
...
</configuration>
...then I get the following exception:
Server Error in '/' Application.
Configuration Error
Description: An error occurred during the processing of a configuration file
required to service this request. Please review the specific error details
below and modify your configuration file appropriately.
Parser Error Message: An error occurred loading a configuration file: Could not
load file or assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' or one of its dependencies.
The system cannot find the file specified.
Source Error:
Line 41: </EncryptedData>
Line 42: </connectionStrings>
Line 43: <appSettings configProtectionProvider="CustomProvider">
Line 44: <EncryptedData ...>
Line 45: <EncryptionMethod .../>
Source File: E:\sitesroot\0\web.config Line: 43
Assembly Load Trace: The following information can be helpful to determine why
the assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' could not be loaded.
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value
[HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure
logging.
To turn this feature off, remove the registry value
[HKLM\Software\Microsoft\Fusion!EnableLog].
However I know the PKCS12ProtectedConfigurationProvider.dll is in the /bin folder because:
I remoted into the VM and saw it in both approot/bin and siteroot/bin
When I deploy with the appSettings unencrypted, the other 3 sections are successfully decrypted using this dll.
It's almost as if the assembly loader can't look for the PKCS12ProtectedConfigurationProvider.dll file until after it parses and loads the appSettings section. I have tried omitting the Version, Culture, and PublicKeyToken parts of the provider config section, but then the error just changes to this:
Parser Error Message: An error occurred loading a configuration file: Could not
load file or assembly 'PKCS12ProtectedConfigurationProvider' or one of its
dependencies. The system cannot find the file specified.
Is it possible to encrypt web.config/appSettings using a custom configProtectionProvider when deploying to a Windows Azure hosted service running on a Windows Server 2012 virtual machine? If so, what am I missing here?
Update:
After posting this I turned on the Fusion!EnableLog registry key and now I get this additional information in the exception:
Assembly Load Trace: The following information can be helpful to determine why
the assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' could not be loaded.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\NETWORK SERVICE
LOG: DisplayName = PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d
(Fully-specified)
LOG: Appbase = file:///d:/windows/system32/inetsrv/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: D:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from D:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider.DLL.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider/PKCS12ProtectedConfigurationProvider.DLL.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider.EXE.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider/PKCS12ProtectedConfigurationProvider.EXE.
So here's another question: Why is IIS looking in the inetsrv path for this assembly instead of looking for it in the app's /bin folder? I see in the log "No application configuration file found." Does this mean the assembly binder has to find a web.config with an unencrypted appSettings section in order to parse and load it?
Did you attempt installing the assembly in the GAC yet on role start?
Information on adding assemblies to the gac on start up http://blogs.infosupport.com/adding-assemblies-to-the-gac-in-windows-azure/
I was able to fix this error by installing the NuGet package: https://www.nuget.org/packages/Pkcs12ProtectedConfigurationProvider/
I'm guessing part of the install process is registering the .dll for you.

Mono with SQL Server Membership Provider?

Apparently Mono replaces references to SQL Server membership provider with sqlite membership provider (see ASP.NET_Settings_Mapping). Is there any way to convince Mono to use SQL Server for the membership provider?
When I try to log in to my web app, I get the following:
System.Configuration.Provider.ProviderException: Operation aborted due to an exception (see Trace for details).
at System.Web.Security.SqliteMembershipProvider.ValidateUser (string,string) <0x003bb>
at DirectMail.Controllers.AccountMembershipService.ValidateUser (string,string) [0x00000] in [file].cs:404
at DirectMail.Controllers.AccountController.ValidateLogOn (string,string) [0x00040] in [file].cs:346
at DirectMail.Controllers.AccountController.LogOn (string,string,bool,string) [0x00000] in [file].cs:79
at (wrapper dynamic-method) System.Runtime.CompilerServices.ExecutionScope.lambda_method (System.Runtime.CompilerServices.ExecutionScope,System.Web.Mvc.ControllerBase,object[]) <0x001c1>
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[]) <0x00028>
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2<string, object>) <0x0015b>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod (System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,System.Collections.Generic.IDictionary`2<string, object>) <0x00036>
at System.Web.Mvc.ControllerActionInvoker/<InvokeActionMethodWithFilters>c__AnonStoreyB.<>m__E () <0x00092>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,System.Func`1<System.Web.Mvc.ActionExecutedContext>) <0x00125>
The top of the file /usr/local/etc/mono/4.0/settings.map on one Debian Linux machine is:
<?xml version="1.0" encoding="utf-8" ?>
<settingsMap>
<map sectionType="System.Web.Configuration.MembershipSection, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
mapperType="Mono.Web.Util.MembershipSectionMapper, Mono.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"
platform="Unix">
<!-- The 'what' tag specifies which region of the section to modify. The 'value' attribute value is mapper-specific and is not defined here. It can be
any expression understood by the mapper to designate the section region to modify.
-->
<what value="providers">
<!-- 'what' can contain any number of occurrences of any three elements:
replace - replace the designated region
add - add a new entry to the region
clear - clear the region
remove - remove the designatedregion
The attributes to any of the above are freeform and are not processed by the mapper manager. They are stored verbatim for the
mapper to peruse.
-->
<replace name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqliteMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqliteServer" />
</what>
</map>
<!-- ... -->
On the ASP.NET Settings Mapping page that you linked to, in the section titled "Inhibiting the settings mapping", it says that adding:
<appSettings>
<add key="MonoAspnetInhibitSettingsMap" value="anything"/>
</appSettings>
to your app's Web.config file will disable settings mapping. I found, however, that value "anything" does not work. If I use the value "true" instead, then it does:
<appSettings>
<add key="MonoAspnetInhibitSettingsMap" value="true"/>
</appSettings>
This must be a misconfiguration because an implemented sqlmembershipprovider exists for Mono 2.0. It is using a DBProviderFactory to obtain a connection. A SqlClient implementation is also there so that only leads to the conclusion that the web.config for the website is not correct, which is not unthinkable because sqlclient and sqlite almost looks the same in an overcrowded web.config.
If anyone can post that one, that might clarify the problem at hand.

Encrypting externally stored App blocks with exportable Key Provider

I have been trying for quite a while to figure out how to encrypt Application blocks that are stored in an external file called dev_entlib.config
I can see in entlib (4.1) that it's possible to use the default protection providers to encrypt the blocks but, I really need to deploy this Application on different servers and thus I would need to export the keyProvider used to encrypt the application blocks to those servers.
What I've done so far is to add a custom Protected Configuration Provider to the machine.config file in the .net v2.0* whatever folder (and all the target servers)
the custom provider is like this
<add name="MyCompanyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="MyKey"
useMachineContainer="true" />
that sits nicely beside the other default providers and even has design time support in the Entlib config tool. I then choose the protection provider for each block I want to encrypt.
Looking at the dev_entlib.config, shows that indeed the block was encrypted with my provider. My provider uses my key container. Therefore the block should be encrypted using my key container. I then Export "MyKey" to an xml file using:
c:\Windows\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis.exe -px "MyKey" "C:\keys.xml" -pri
Exporting RSA Keys to file...
Succeeded!
This key file is then copied to my sysTest server where it is imported and has access rights granted to "NT Authority\Network Services" and "ASPNET"
I then copy over my encrypted web.config and dev_entlib.config and try to display the connection strings in a small page which uses .net ConfigurationManager to get the ConnectionStrings collection and display them on the page. This page is running under IIS and the identity of the process is "NT Authority\Network Services".
The problem is, that it doesn't work! There are bad data errors or "failed to decrypt using provider MyCompanyProvider".
This approach seems to make logical sense to me but it still fails.
Does anyone have another suggestions?
Encrypt external Enterprise Library configuration files with your custom RSA key container using the Enterprise Library Configuration tool.
EntLib (4.1) uses the default protection provider RsaProtectedConfigurationProvider. But it is possible to remove this provider within your configuration file and replace it with your own with the same name which can then point to your custom key provider: "MyKey".
You should add this configProtectedData section in the configuration file that has the region that you want to encrypt (e.g. your external file: *dev_entlib.config*). You do not need to modify the machine.config file at all.
You can then choose the RsaProtectedConfigurationProvider from the Enterprise Library Configuration application for the Data Access Application Block ProtectionProvider.
You have to open this EntLibConfig.exe with Run as administrator if you are on Vista, Windows 7, Windows 2008.
Otherwise you will get an error:
Failed to encrypt the section 'connectionStrings' using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: Object already exists.
You can then copy this encrypted *dev_entlib.config* along with the web.config configuration file to your sysTest server. Open up the web.config file with Enterprise Library Configuration tool on that sysTest server should not get the error:
Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: Bad Data.
web.config
This file is pretty much empty and just points to the external Data Configuration file:
<!-- web.config -->
<configuration>
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="External Data Configuration File Source">
<sources>
<add name="External Data Configuration File Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
filePath="dev_entlib.config" />
</sources>
</enterpriseLibrary.ConfigurationSource>
</configuration>
dev_entlib.config
This file has the connection strings and the protection provider with which it should be encrypted with:
<!-- dev_entlib.config -->
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<dataConfiguration defaultDatabase="MyConnectionStringName" />
<connectionStrings>
<add name="cnHnicMediaLibrary" connectionString="Server=MyDbServer; Database=MyDbName; Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
</connectionStrings>
<configProtectedData>
<providers>
<remove name="RsaProtectedConfigurationProvider" />
<add name="RsaProtectedConfigurationProvider"
keyContainerName="MyKey"
useMachineContainer="true"
description="Uses our own encryption key container so that it will work in a Web Farm setting. We need to trick Enterprise Library, which wants to use the default RsaCryptoServiceProvider to encrypt and decrypt, by replacing this default provider with our own while this configuration is processed!"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</configProtectedData>
</configuration>
Based on:
http://entlib.codeplex.com/discussions/237555 (AvanadeSupport, Dec 8 2010 at 11:37 PM)
http://entlib.codeplex.com/discussions/10300 (shane2007, Jul 9 2007 at 1:15 PM)
http://entlib.codeplex.com/discussions/213998 (need to change the version back to 2.0.0.0)
I hope that this described the error message that you had and how to fix it.
It doesn't seem to be possible yet. My solution is to just encrypt the blocks as part of the web.config and then copy and paste those blocks into an external entLib.config file. These block should then be able to be decrypted on the target servers with the exported key.

Resources