I've been working on a project to move all of our applications to use external .config files to store connection strings so they are no longer kept in source control. As part of this, we are now encrypting these connection strings on deployment.
web.config
<connectionStrings configSource="ConnectionStrings.config"/>
ConnectionStrings.config
<connectionStrings>
<add name="MyDatabase" connectionString="MyConnectionString" providerName="System.Data.SqlClient">
</connectionStrings>
This is an application that I had to update from .NetFramework 4.0 to .NetFramwork 4.7.2 due to restrictions on our build server.
To encrypt the connection strings I have been running the following command (on the web server) for all of our applications thus far with no issue. Several of these were framework upgrades as well. Note: we give each of our web apps their own app pool.
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe" -pe "connectionStrings" -app "/MyApplication" -site "Default Web Site"
Every site so far has worked without issue in all of our environments. Now this most recent one, when encrypted, causes an infinite redirect loop with the same error each loop of
Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
If I go to the server and run the command line to decrypt, it succeeds and the app functions properly. I'm baffled and non of my coworkers have any idea either. I know it has to be something specific to this one application but I don't know where to begin. It is an old app that I didn't even work on and know nothing about. I've looked through numerous pages of similar RSA complaints but none of them seem to be this specific issue. And yes I am able to replicate this on multiple servers and even on my own machine.
Related
I'm setting up ci-deployment using jenkins for multiplice ASP.NET MVC 5 EF CF application with MySQL-Database on a Windows Server 2012 R2 node. The app gets compiled first using msbuild and then published on IIS with msdeploy. ConnectionStrings will be replaced using the -setParamFile parameter, which works.
The problem: After calling the app on the target server, I get the following MySQL error:
MySql.Data.MySqlClient.MySqlException: Access denied for user 'myUser'#'myIp' (using password: NO).
The MySQL-Doc say that this means the clinent had tried to connect without password.
This is really confusing me because my ConnectionString certainly contains a password! In the Web.config from the folder of the IIS-App it looks like this:
<add name="MyContext" connectionString="Server=SERVERIP;Database=MYDBNAME;Uid=DATABASEUSER;Pwd=PWD;Convert Zero Datetime=True;" providerName="MySql.Data.MySqlClient" />
Which is valid, because the app is running fine on local debugging and a Windows Server 2012 R2 based testsystem, where I deployed the app using Web-Publishing function of Visual Studio.
I have the suspicion that my Web.config gets overwritten, but can't find out where and why. I took a look in the local Machine.config file of the target-server, but in contrast to another thread with nearly the same problem this isn't containing my ConnectionString (And I even can't imagine why this should gonna happen).
First, this is related to another question here on SO:
I've read and debugged my issue with the following SO article & blog:
MetadataException: Unable to load the specified metadata resource
and
http://blogs.teamb.com/craigstuntz/2010/08/13/38628/
BUT...I'm still having questions beyond just this 'fix'
I have a WebAPI (2.1), the connection string in my WebAPI is as so:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://*/ProjectModel.csdl|
res://*/ProjectModel.ssdl|
res://*/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
When I call ToList() on a DbSet in my WebAPI (pseudo code):
DbContext _DbContext = new ProjectEntities();
DbSet<TEntity> _dbSet = _DbContext.Set<TEntity>();
_dbSet.ToList();
It works great!
When I call the same from within a WINDOWS SERVICE, I get the following error:
The app.config entry for the connection string is exactly the same as the web.config:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://*/ProjectModel.csdl|
res://*/ProjectModel.ssdl|
res://*/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
Now, the blog shows to reference the dll manually as so:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://Project.Data.dll/ProjectModel.csdl|
res://Project.Data.dll/ProjectModel.ssdl|
res://Project.Data.dll/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.0.1;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
This does NOT work/fix the issue
The only way I've been able to fix it, is to use the fully qualified name:
<connectionStrings>
<add name="ProjectEntities" connectionString="
metadata=res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.csdl|
res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.ssdl|
res://Project.Data, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null/ProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=192.168.250.125\sqlexpress;
initial catalog=Project;
persist security info=True;
user id=***;
password=***;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Why does this work like this? Why would this work in a web project, but not a windows service project?? I recently changed from EF5 to EF6, and this error has popped up - all this code worked previous to upgrading EF. Does anyone have any insight as to why and how/if I can just use * for the dll name in my connection string?
I thought it was an issue of where the service .exe was running and a file wasn't copied locally, but nope, the Project.Data.dll is there and it's the right version.
I used FusionLog to try and find the error, and no luck there. I'm pretty confused.
Why this happens?
The issue you are having is just a result of extra security measures to prevent binary planting or DLL hi-jacking attack (read more) when running your application as as windows service.
Why should I care?
As you probably know, there is a specific, well documented order in what every referenced DLL file is looked up. Usually it starts to search DLL in current application directory and then goes away to more "public" locations like PATH folders, GAC, etc.
Main idea of binary planting is to plant malicious DLL file in a folder which is checked before folder of the legit DLL. Loading such malicious DLL would allow attacker to gain control over the system.
Usually windows services run under elevated account (LocalSystem, LocalService, NetworkService, etc) therefore windows services are good target for binary planting attacks.
What can I do?
Microsoft have taken extra precaution steps to reduce security risks and there is a good reason for that. But you can try to work around you issues.
1) Current directory is not what you expect
Windows service starts in system folder (usually something like C:\Windows\System32)
Good news are that it is very easy to fix. You just have to change current directory on services startup.
System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
See blog post from Phil Haack;
2) Read documentation thoroughtly
According to EF documentation, wildcard character has special meaning and it limits places where runtime will look for DLL files:
If you specify a wildcard (*) for assemblyFullName, the Entity
Framework runtime will search for resources in the following
locations, in this order:
1) The calling assembly.
2) The referenced assemblies.
3) The assemblies in the bin directory of an application.
As your working folder is set to system folder and you references probably are not there, EF might end up looking in wrong places and your assemblies containing resources might not be loaded.
3) Stay safe with fully qualified assembly names
Although I am not completely sure about this and haven't tested, but Microsoft just might have disallowed Windows services to load DLL without providing fully qualified assembly name to reduce risk of injecting malicious DLL files;
Good read on securing your Windows services here (specially chapter 5).
4) Debug it!
EF6 happens to be open source project. This means that you can get full source of it and debug it. You can find project on CodePlex here.
Copy the dll containing ProjectEntities to different path and then reference the same in your service project.
I'm afraid I wasn't able to reproduce the error that you received, or answer why you needed to change the metadata.
That said, I did learn that, for the EF connection string, the Windows Service required a different provider connection string than the WebApi did.
The following are the steps to reproduce your error. The only difference is that I'm using localdb not SQLExpress.
The resultant code from my steps-to-reproduce is online at GitHub here: https://github.com/bigfont/EntityFrameworkWindowsServiceWebApi.
Here are those steps:
Create Web API Project
Create ASP.NET Web API 2 Empty Project (MyWebApi)
With NuGet, Install-Package EntityFramework -ProjectName MyWebApi
Add a new ADO.NET Entity Data Model called MyProjectModel.
Add an Entity called Entity1.
Generate the database from the model, calling it MyProject and using localdb.
Run the db creation script on (localdb)\v11.0
Add a new WebApi Controller named ValuesController with a Get method that queries the database.
Test by running in Visual Studio and going to localhost:123456/api/get
See: https://msdn.microsoft.com/en-us/data/jj205424.aspx
Create Windows Service Project
Create Windows Service (MyWindowsService)
Use NuGet, Install-Package EntityFramework -ProjectName MyWindowsService
Add a new ADO.NET Entity Data Model called MyProjectModel.
Add an Entity called Entity1.
Generate the database from the model, calling it MyService, using localdb.
Run the db creation script on (localdb)\v11.0
Add to the OnStart method some code that queries the database.
Add NT AUTHORITY\SYSTEM as a localdb Login and as a MyService db User.
Test by installing, starting, and writing to file:
PowerShell Installation, Startup, and Uninstall
Release> installutil .\MyWindowsService.exe
Release> Start-Service MyService
Release> installutil .\MyWindowsService.exe /u
localdb connection string in the Windows Service
In the connection string for the Windows Service, I wasn't able to use (localdb)\v11.0. Instead, I needed to use the named pipe. I found the named pipe with this command line:
> SqlLocalDB.exe info v11.0
Name: v11.0
Version: 11.0.2100.60
Shared name:
Owner: MY_COMPUTER\Shaun.Luttin
Auto-create: Yes
State: Running
Last start time: 2015-04-09 5:54:34 PM
Instance pipe name: np:\\.\pipe\LOCALDB#1010101\tsql\query
The resultant connection string, using the Instance pipe name, looked like this.
<connectionStrings>
<add name="MyProjectModelContainer"
connectionString="
metadata=
res://*/MyProjectModel.csdl|
res://*/MyProjectModel.ssdl|
res://*/MyProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=np:\\.\pipe\LOCALDB#4BCE6D95\tsql\query;
initial catalog=MyService;
Integrated Security=True;
MultipleActiveResultSets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Whereas the WebApi connection string looked like this:
<add name="MyProjectModelContainer"
connectionString="
metadata=
res://*/MyProjectModel.csdl|
res://*/MyProjectModel.ssdl|
res://*/MyProjectModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=(localdb)\v11.0;
initial catalog=MyProject;
integrated security=True;
MultipleActiveResultSets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
See also: http://www.connectionstrings.com/sql-server-2012/
Needing to use a different connection string with a Windows Service that we do with a WebApi project is a similar problem to what you found. From Sql Server Management Studio, from Visual Studio, and from the WebApi, we can connect by calling the data source (localdb)\v.11 whereas from a Web Service we need to call it by it's instance named pipe.
Here's a suspicion: It might be that there are multiple instance of localdb on the computer, and that we needed to absolutely specify which one we want to use. Unfortunately, this doesn't help answer why you needed to change the metadata.
This is a similar though different problem than what you faced, because you needed to change the Entity Framework metadata whereas I needed to change the provider connection string. Coincidence?
Please follow the steps bellow:
1.Write click on edmx file and then click open with of the related entity.
2.Select xml editor and click open.
3.Scroll from top to bottom of the .edmx xml file and look for any error marks.
4.If you mind errors then fix that.
5.Rebuild the solution and if no errors found then congratulations :)
We have a wcf service that runs as an application in a separate application pool on our webserver in a subfolder. We upgraded to .NET 4.5 in Dec. and EF5 in January. We did our standard web deploy yesterday which does not touch this code, and the WCF service stopped working.
We can move the old code to a different production server and it works. When using the old code on the production site we get a code produced error that indicate connectivity issues to the database (Unable to LogIn).
We tried deploying the WCF with upgraded 4.5 and EF5, but get runtime errors: "The type initializer for 'System.Data.Entity.Internal.AppConfig' threw an exception." We have done all the config changes indicated, such as defaultConnectionFactory, for EF5. When doing so, the WCF starts giving a 301 redirection to the service endpoint when calling any service method. We are stumped as why a normal web deploy would cause these issues, and why we can't deploy upgraded EF versions to get us out of this hole.
This is a live and very active service used by our business partners.
Resolved. Event log says nothing. It looked to be a binding issue between IIS and the interface. Turned out to be conflicting web.config's keeping the IIS from loading the web.config fully/causing duplicate entries. The only config item that caused the break was an EntityFramework connect string. We run EF5.0 on .NET 4.5. Here is the offending connection string:
String in root Web.Config:
<add name="MyConfigurationEntities" connectionString="metadata=res://*/MyConfigurationModel.csdl|res://*/MyConfigurationModel.ssdl|res://*/MyConfigurationModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SERVER1;Initial Catalog=MyConfiguration;User ID=sa;Password=XXXX;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
String in web service Web.Config:
<add name="MyConfigurationEntities" connectionString="metadata=res://*/MyConfigurationModel.csdl|res://*/MyConfigurationModel.ssdl|res://*/MyConfigurationModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=Server1;Initial Catalog=MyConfiguration;User ID=sa;Password=XXXX;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Our folder structure is:
/web.config
/webservices/webservice/web.config
I'm working on this for some time and I have no idea anymore what to do.. so here is the problem.
I've got a Azure Webservice, which works perfectly localy. It should connect to a Azure SQL Database (I use the same ConnectionString for debug AND azure.. so it SHOULD be right)
Using IntelliTrace, I find these Errors:
Requested registry access is not allowed.
System.IO.FileNotFoundException Could not load file or assembly 'EntityFramework, Version=6.0.0.0, Culture=Neutral....
System.Data.Entity.Core.ProviderIncompatibleException
System.Data.SqlClient.SqlException A network-related or instance-specific error occured while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct... (This about 50 times)
System.Threading.WaitHandleCannotBeOpenedException No handle of the given name exists.
System.Security.SecurityException Requested registry access is not allowed
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironmentException error
System.Threading.WaitHandleCannotBeOpenedException No handle of the given name exists.
(Exception stack, top newest, bott oldest)
In my web.config I setup EF and ConnectionString like this:
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="EntityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework" requirePermission="false"/>
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Server=SERVER.database.windows.net;Database=LeagueMetaDatabase;User ID=USER#ksew7pk8ad;Password=PW;Trusted_Connection=False;Encrypt=True;" providerName="System.Data.SqlClient"/>
</connectionStrings>
I also deactivated "Specific Version" for the EF assembly and activated "Copy Local".
I checked in the bin folder of the service on the server, the dll is there.
The service uses a lot of async, but as already said it works localy.. I also installed .NET 4.5.1 on the server just to be sure that is not the problem
// Edit
First of all, thanks for all the help so far!
I tried narrowing the problem down.. reconstructing the hole project and trying to find what does not work. It seems that async Tasks can NOT read the ConnectionString in the Web.config on the Azure Server Cloud. In the emulator, it works. I hardcoded the ConnectionString into the Context and it is working this way.
Anyone can tell me what creates this behaviour and how I can put it back into the Web.config?
How is your solution deployed to Azure? Are you using a Cloud Service or Web Site? If you're running an Azure Web Site the problem might be related to your connection string name being the same in both the web.config and also your Azure Web Site. If this is the case you might want to try renaming the connection string defined in the Azure Management Portal for you web site. This can be done through the Configure management page.
Hope this helps.
Are the DB & Cloud Service in same data center? If not, link your resources via the Azure control panel and/or make sure that you have enabled "allow azure services to connect" in the DB configure section.
Also, make sure your SERVER connection specifies "tcp" - The Windows Azure SQL Database service is only available with TCP port 1433. To access a SQL Database database from your computer, ensure that your firewall allows outgoing TCP communication on TCP port 1433 (from Guidelines for Connecting to Windows Azure SQL Database). If you grab the ADO connection string from the DB dashboard page, you should see:
Server=tcp:{your_servername}.database.windows.net,1433;Database={your_database_name};User ID={your_userid};Password={your_password_here};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;
First of all, thanks for all the help so far!
I tried narrowing the problem down.. reconstructing the hole project and trying to find what does not work.
It seems that async Tasks can NOT read the ConnectionString in the Web.config on the Azure Server Cloud. In the emulator, it works. I hardcoded the ConnectionString into the Context and it is working this way.
Anyone can tell me what creates this behaviour and how I can put it back into the Web.config?
I am trying to deploy a simple windows desktop app using a SQL Server database.sdf file. I have followed the steps in this walkthrough about 10 times and I still am having problems. http://msdn.microsoft.com/en-us/library/bb546200.aspx
In my app.config file my connection string is this:
<add name="VendorTracker_2._0.Properties.Settings.Database1ConnectionString"
connectionString="Data Source=C:\Users\Eamon\Documents\Visual Studio 2008\Projects\VendorTracker 2.0\VendorTracker 2.0\Database1.sdf"
providerName="Microsoft.SqlServerCe.Client.3.5" />
According to the walkthrough, the windows installer should recognize that I am using a SQL Server CE .sdf file and create a new connection string:
<add name="VendorTracker_2._0.Properties.Settings.Database1ConnectionString1"
connectionString="Data Source=|DataDirectory|\Database1.sdf"
providerName="Microsoft.SqlServerCe.Client.3.5" />
It does add this connection string to the app.config file. Now I have both connection strings listed in the app.config file. When I deploy the app onto my development computer, it works fine, no problem connecting to the .sdf file.
But when I copy the install folder and everything inside of it to a different "testing" computer I get the following error when I try to run the app:
The path is not valid. Check the directory for the database. [ Path=C:\Users\MyName\Documents\Visual Studio 2008\Projects\VendorTracker 2.0 Database1.sdf].
The app continues to run but there is no data and It will not allow me to save anything to the database.
Why doesn't the .sdf file get deployed with the connection string:
Data Source=|DataDirectory|\Database1.sdf
like it is suppose to? Driving me nuts. I have tried everything. Has anyone successfully used a SQL Server CE .sdf file with a stand alone windows desktop app? I know they are used a lot for mobile devices but that shouldn't make a difference. Please help.
Oceantrain
You must change the connection string manually. Also, consider carefully where you place the file, as not all places are writable