I have doubt on storing web.config files in Git-hub, is it recommended?
Is this not a security vulnerability?
Also web.config for different environments will be different in different enviroments, hence how to keep different versions of web.config is same repo and branch?
Yes, it is.
Use server-level secrets to store sensitive information like DB connection strings.
In IIS you can use ASPNET_REGIIS - it lets you add secret configuration that IIS can access, but that isn't held in plain text with the web files.
In .NET core there's new Microsoft.Extensions.SecretManager.Tools that does the same thing.
For different environments you can have multiple web.config files, for instance web.release.config and web.debug.config.
Your web.config file itself is not a security issue. The keys you probably have inside it like connections strings are indeed very much sensitive and should not be in version control. The problem is how to manage those keys without having them in the web.config (or any other version controlled settings/config file).
Keith is correct that you should use server-level secrets. If your managing the server yourself you can use his method of setting them but if your using a service you'll need to set the keys up however they specify.
An example on Azure
How and where to define an environment variable on azure
Another on Heroku
https://devcenter.heroku.com/articles/config-vars
Setting up the server-level secrets is only the first step. Once you've pulled the keys out of the web.config you'll have to set them up locally. Here's a blog post that talks about setting them using your local machine.config.
http://krow.tech/posts/Keeping-Your-Secret-Configs-Private
Related
I am wondering the general convention for keeping configuration information related to the fields below for 2 concerns below:
A > Security concern
B > Update concern (in case the config should be updated by the user instead of developer).
1) I define database connection string information (database, user and password) in web.config. Is there another way i.e. keeping in cs file? I think it is impossible to keep it in the same database that application use.
2) My application send e-mail and I define the credentials in the *.cs class of e-mail. Is it true? By keeping into account that this info is changed and there is no developer to support, is it good idea to keep them in database and allow user to update them via application?
3) What is the approaches for all of the scenarios (config, update and *.cs file)? For example when keeping e-mail credentials in the database, should I get these info from database just before the usage? Or is there another approach i.e. writing it to a temporary file and then reuse it until it is changed in the database, etc.)
Any help would be appreciated.
Keeping info such as connection strings and credentials in source code is generally a bad practice. And it is not safer than storing it in Web.config (not encrypted) because all
resources can be simply extracted from code.
For web applications the best practice is to store all your sensitive information in one place (like web.config) but encrypt it during deployment.
To encrypt web.config you can use aspnet_regiis tool that can be found here
%windows%\Microsoft.NET\Framework\versionNumber
For example
c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe
with keys -pef or -pe. You can encrypt only particular sections like <connectionString> and keep other sections not encrypted.
For more information please see Encrypting and Decrypting Configuration Sections amd How to: Encrypt a web.config File
It's generally a good idea to encrypt sensitive application configuration data. There are a couple of approaches available to you, depending on what kind of application you have.
For web applications, you can use the DPAPI and aspnet_regiis to encrypt the configuration. See Encrypt and deploy app.config for sample code.
Alternatively (if you have a desktop application or don't want aspnet_regiis) you can have a look at protected configuration sections as described here: https://msdn.microsoft.com/en-us/library/hh8x3tas.aspx
To answer your specific questions:
1) Keep it in the web.config and encrypt it. Hardcoding in a .cs file is flawed from a security perspective (code can be decompiled) and it will make it difficult to change as your code moves from environment to environment (dev -> uat -> prod)
2) Again, don't store credentials in a .cs file. You can provide a UI for users to manipulate config but remember that they may break the config and you'll need a mechanism to restore to a known good config
3) If you are concerned about how often you read from the db (although reads are cheap as long as there are no writes) you could simply read all the config into a class on startup. That way there are no temporary files to manage and the amount of reading on the db is limited.
We are developing an ASP.NET MVC 5 application. We hired some remote developers to help us with the project.
The web.config file contains connection strings and app settings that we don't want to share with these remote developers. To work on our application, these developers remote into a development desktop that we control.
What is the best practice for securing sensitive information in web.config, so that developers can still run and debug application but not read the sensitive info in web.config?
Encrypting the web.config in a development environment is pointless. The only way to truely hide the information from the developers is not to give it to them in the first place.
You must ensure that your "remote development environment" is setup only to access a development database and is configured with other development settings only.
Don't check in any sensitive data (production passwords, etc) into your source control. You can achieve this by separating the information into external .config files so they are not checked into source control. TIP: Ignore the file with the actual passwords and add another one with the same name and an extension such as .config.example that is checked in to give the developer instructions on how to setup the file on their local system (which is a helpful reminder regardless of who sets up the system from a clone of the source control repository).
Use a continuous integration server (TeamCity, Jenkins, Octopus Deploy, etc) to build sensitive information into the release workflow through environment variables. Many CI servers have the ability to hide sensitive data from the UI. You can either practice automatic deployment via CI button-click so your developers don't have access to the sensitive data that is in the CI server, or give the deployment artifact(s) to a trusted team to install in production.
There is really no reason why a developer should even be given a chance to see sensitive production data such as passwords and private keys.
Like Ingenioushax suggested, the standard way of encrypting sections of web.config is using aspnet_regiis. Here is a tutorial.
How are you deploying your application?
If you use a tool such as Octopus Deploy - that only your onshore team have access to - you can use that to store any sensitive settings. These will get inserted into your configuration file during deployment.
In Octopus Deploy these are known as configuration variables.
This assumes that the sensitive settings are for environments other than ones that the developers will use themselves (Production and UAT, for example).
You can store config variables in environment variables and read them into the app at run time - this is better because each developer and environment can have their own configs that will never collide with others.
In my Azure Web Site I have in my AppSettings section in Web.Config some references to files on my disk. When deployed to Azure those references doesn't count any more. I know that you can overwrite AppSettings in Web.Config in the Azure environtment. But what is the file structure there?
A couple of examples from my web.config that I have to solve:
<add key="DataMapPath" value="d:\inetpub\MyWebApp\App_Data\map.xml"/>
<add key="CuteWebUI.AjaxUploader.TempDirectory" value="C:\Temp\WebApp\Attachments\UploaderTemp"/>
The first file tells our code to look for the map.xml-file in the App_Data-directory.
The last one tells our upload-controll where to upload files. I maybe should have used Azure Blob Storage here instead but that would need some major refactoring of our code.
Is there som best practices on this topic?
Our WebApp is running in production today, but I want to try out MS Azure. But I doesn't want to do to many code changes to make it work in Azure.
I have also read you can spin up an Virtual Machine (Windows Server) but that is overkill for my needs right now. We may go that way in the end, but for this testing-purpose it should be made simple.
Any suggestions on how this could be solved? Someone done this before? I guess someone has. Indeed.
If I do have read and write access to the file system for my Web Site I maybe could use this:
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TheFolder");
This would be appropriate for both on-premise and Azure deployment. But then I have to do some changes in our code.
You have multiple options:
Option 1: Use the App Settings of your web app to set custom settings for your website.
Option 2: Create multiple versions of your web.config (Visual Studio supports this) and deploy different versions to Azure and your local machine
Option 3: Make your path's relative to the paths of Azure Web App's environment variables
There's a HOME environment variable in your Azure Web App that resolves to the equivalent of inetpub for your site. Your app data folder is located at %HOME%\site\wwwroot\AppData.
There's also a TEMP environment both on Azure Web Apps and on your local machine. You can make your second setting relative to the TEMP environment variable value.
Actually you won't have this kind of "control" using azure web sites. To keep your app as it is, use Azure Virtual Machines.
I have a web application built in ASP.NET MVC that will be used by several clients. Each client has its own database to store information, but each instance will have the same functionality. I am using tips from this question/answer How can I host multiple websites in IIS 7 and use the same MVC application for all them? to consolidate to a single app folder for easier maintenance.
Right now, I setup each client in its own folder and each with its own Web.Config file. There are a couple of appConfig settings as well as the connectionStrings that are unique to that client.
What I would like to do is have a single app folder that contains the MVC project, but the application then dynamically pulls the correct web.config folder (stored in another folder.) I will select the web.config probably based on the host settings (i.e. www.domain.com loads the domain.web.config file.)
I would like for this to update the behavior of the ConfigurationManagement object. I have seen several posts on how to load a configuration file (and most are regarding app.config for desktop apps) but not how to make it a semi-global change or unique characteristics of ASP.NET MVC and web.config.
How can I accomplish this?
What you are looking to do is called multi-tenancy. And this is quite complex task.
You can't really play about with web.config substitution and for one request give one file and for another request give another config. What if 2 requests from different tenants will come exactly at the same time?
At the moment we are converting our application to multi-tenancy and this is very complex task, so can't really be described in one answer on SO.
You can have a look on this write-up http://www.scribd.com/doc/140181293/setting-up-an-mvc4-multi-tenant-site-v1-1
Also if you google for "multi-tenancy MVC" you'll get many articles on that.
Basic principles for our multi-tenancy look like this: DI container is aware of different tenants and knows that request for tenant1.site.com should use configuration set 1 and for request tenant2.site.com configuration set 2 should be used.
Apart from DI container, no other component knows about tenants. And DI container orchestrates the configurations. Connection strings are sitting in configuration objects and these objects are given to EF contexts before they are created... somewhat complex.
If your case is simple and you don't use caches, to substitute the connection strings, I'd save them outwith web.config and provide them based on tenant request. Probably you can get away without complex DI setups.
The overhead of maintaining multiple config files is small if you use external config files to isolate the connection strings that are unique to the customer leaving the bulk of the config file unchanged.
<?xml version='1.0' encoding='utf-8'?>
<configuration>
<connectionStrings configSource="connections.config"/>
</configuration>
For more options about resolving config information at runtime look at
http://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx
For app settings in an internal file see Moving Settings to another config file
I have situation described bellow:
In CMS was implemented two presentation server which aren't on same machine. Client want to enable IIS caching only on one machine, but changing manually web.config isn't suggested. So I am planning to make some C# code which will make changes in web.config in order to ensure proper cache settings. Is it possible or exist any other solution ( change other settings, edit other files...) for the problem?
"You can configure the element at the server level in the ApplicationHost.config file or at the site, application, or at the directory level in a Web.config file."
If you have physical access to the server you can run from the console appcmd.exe:
appcmd.exe set config -section:system.webServer/caching /+"profiles.[extension='asp',policy='CacheUntilChange',kernelCachePolicy='CacheUntilChange']" /commit:apphost
Check this link: http://www.iis.net/ConfigReference/system.webServer/caching
EDITED
The first answer to this question says how to configure caching at folder level, the 2nd answer for file level:
How to configure static content cache per folder and extension in IIS7?
If you didn't specify any caching rules at file or folder level, disabling global caching should do it.