Recommended ways to create a new database from an ASP.Net application - asp.net

Our ASP.Net application uses SQL Server 2008. Most of the time the application connects to SQL Server using a SQL account with very limited access rights.
However once in a while we need to be able to create a new database on the fly. As such we need elevated permissions and I am a little nervous about storing this connection string in Web.config, which may be in a DMZ.
We are considering writing a Windows service to run on the SQL Server machine (i.e. not in the DMZ) which will monitor a table for requests to create a new database, but it seems like overkill.
Any suggestions for alternatives or recommended practices?

You can store the connection string in the registry and protect that by limiting access to the specified registry keys. That's one of the ideasI ran across back in .Net 1.1 as a reccomendation from Microsoft. The concept is still the same in 2.0 and up. Here's a link to the documentation.
http://msdn.microsoft.com/en-us/library/aa302406.aspx
It sounds like you're already concerned about security, so I'm guessing you've read through or at least run across the "Building Secure ASP.Net applications" section of the MSDN library. The link above is in the how-To section of that guide. Hopefully this is helpful.
Also, if you DO store your connection info in the web.config, at a minimum, encrypt those portions.
And I just ran across this. Probably more like what you were looking for.
http://msdn.microsoft.com/en-us/library/aa302388.aspx#secnetch08_storingsecrets

If you are using mixed mode authentication in your database connection strings (I.E., username and password) then you should encrypt the web.config connectionStrings element.

What about using a stored procedure to create the database? I haven't tried it; the one part I'm worried about is specifying the database name through a variable. By using the stored proc, you only need to grant your web id execute access on the stored proc.
Another option would be to create a console app (instead of a service). Then use a job scheduler to run the job every 15 or 30 minutes or upon request if you have a capable scheduler. That will be much simpler than writing a service; it just isn't an "instant" process. I do this for some Active Directory work that triggers off of web site updates (I didn't want to give my web id Domain Admin priveleges).

Related

Best practices for connecting from ASP.NET Core to SQL Server?

I've had some recent difficulty with SQL Server not liking the default AppIdentityUser for logins, so I went ahead and created a custom DB user with write access.
But it made me wonder - is this the best approach?
I was wondering what the best SQL Server login approach would be for Asp.Net Core. I know there's a question similar to this for normal .NET, but you can't encrypt a Core web.config/appsettings.json (well, in a quick and straightforward manner).
Here are the options as I see them:
Connect via SQL Server ID that is stored in appsettings.json.
Pro: Already configured.
Cons: Password in web.config/appsettings.json; have to specifically configure SQL Server ID. Not centrally revokable.
Connect via user NT ID via ASP.NET "AppIdentityUser".
Pro: No passwords in appsettings.json.
Cons: Not centrally revocable. Seems to be restricted to the server name for user.
Connect via Active Directory user.
Pro: Easily revokable.
Cons: Active directory user password in appsettings.json. Could be bad if somebody accidentally reuses that user in another application in the company, and that user gets breached.
Are there other options that I'm missing? Which of these options are used in which situations? Which are more standard? Are there pros and cons that I'm not thinking about?
You should absolutely use a custom SQL Login to connect to the database. Under the hood, the SQL Login could be tied to a local account, service account, network account, etc. It doesn't actually matter.
The real issue you seem to be having here is in not wanting (rightly) to expose login credentials in plain text. I'm not sure why you keep referring to Web.config here, as ASP.NET Core doesn't use that. Instead, there's various configuration providers that can be optionally utilized. By default, ASP.NET Core (at least since 2.0) adds a JSON config provider that looks for appsettings.json and appsettings.{environment}.json in your project, a command-line configuration provider, a user secrets config provider, and finally an environment variable configuration provider.
The last two are the most interesting for your circumstances. In development, you should use user secrets. In production, you should use environment variables. However, neither stores secrets in an encrypted way. The benefit to either approach is that the secrets are not in your project, and therefore also not in your source control. Even though neither is encrypted, it's not as big of a concern as you might think. Getting at the secrets in either would require direct access to the server/development machine. Additionally, user secrets is by default tied to a particular user account, accessible only to that user, and environment variables can be set up the same way. Therefore, someone would need to both gain access to the machine and gain access to the particular account. That's actually a pretty high bar, and if it were to occur, exposing a database password is really the least of your concerns at that point.
Nevertheless, if you want true encryption, you have the option of using Azure KeyVault. KeyVault can be used whether or not your application is actually hosted in Azure, and while it's not free, it's exceedingly cheap.
Finally, you can always create your own config providers or source third-party ones. For example, while the default JSON provider doesn't support encryption, you could potentially write one that does.

Component Services application not running properly on Windows Server 2012

I'm new to this old stuff... I've set up my COM+ application (Classic ASP) on Windows Server 2012, but could only get it to run by unchecking "Enforce access checks for this application" in the application properties. It now runs okay, but any time the application tries to hit the database in any way, I get nothing. I've checked access to the necessary folders (as far as I know) and the user (local user, in the identity tab) has read/write access. Any ideas? And is more information needed?
As you probably already know, Windows Server releases are an ever-changing minefield of permission issues (aka user identity issues). What worked under 2008 may no longer under 2012.
The components in a classic ASP solution pretty much all have the potential to be running as different identities in the context of Windows.
Typical examples of unexpected identities are System, Network Service, and IUSR.
Where these options bite are, for example:
In IIS your web site has an assigned app pool in which it runs. The app pool has a user identity assignment;
In IIS, your virtual folders map to physical folders under Windows and there is access security there;
With COM you get a further identity option to set - this is the 'run-as' identity, which is the effective user that executes the COM components for you.
With a database such as MS SQL Server, you get the concept of user connection security which can be set to use Windows user authentication (trust the windows user) or userid/pwd required. So if you use, for example ADODB, in your code you must supply a connection string that you have to match to the connection settings the DB expects and will allow.
From your description I assume that you have the IIS site up and running, and your issue is confined to DB access from the COM components. You need to establish how the COM components connect to the DB and check that the DB will accept the credentials in use. If you are using Windows Authentication for the DB then you need to confirm for sure the run-as identity that is in use. In my setup we create a dedicated Windows user that we set aside specifically to use for COM so that we can be absolutely sure of the identity, and in our most verbose logging from the COM components we capture the run-as identity just to confirm it is all wired up correctly.
We do the same with dedicated Windows users for the IIS app pool user too. In general you are better off being sure which identity is in use by assigning it yourself rather than taking the default. Additionally, the defaults such as Network Service seem to have a diminishing amount of privs in Windows overall.
Word of caution - on the other hand do not give your dedicated users more access than they need, for example making them members of the Administrator group when you are frustrated or feeling your way through permission issues. Sure, assign these on a very temporary basis to confirm that access privs are the issue, but be sure to remove such assignments as soon as you possible can.
EDIT: I had this half written when your comment came in. You say that there was a missing component - I had not considered that potential as you seemed to be saying that the config worked but COM did not. Well done for solving your issue. I will leave this answer in place as some of what I have written could be useful for future folks walking the same or similar path.

Security Issues ASP.NET integrated Authentication

We currently use a connection string to authenticate our database credentials. Due to grown and compliance the developers are no longer allowed to "see" the database credentials that our websites use. Are solution to this problem is use Integrated Authentication. We planned on setting up a user per App Pool and then allowing that use access to the Database.
My question is: Are there any security concerns around this approach? As far has removing the DB credentials from the connection string, is there a better(easier or simpler) approach we should/could be taking?
If you need to secure and audit access to the production database then Windows Authentication is a better choice than Sql Authentication for a number of reasons:
You can control exactly who can access the database via NT groups and permissions, which means you know who specifically has access to the database. The pool of access with sql authentication is only limited by who knows the password. Given n people who know the password, tracking who did what at a certain point of time is trickier (but not impossible) given that.
Only your sysadmins need know the password for the nt identity with access to the database; in fact, much of the config can be done only knowing the username
Logins and access can be tracked at the domain level far more easily than with SQL Server logins.
What it wont give you is:
Ability to ensure that the developers can't see production data - whoever writes the app can easily include some diagnostic routines to select out data
Ensure that production data only stays in production - anyone making a backup of the production database (say to restore it to a UAT environment for testing) could easily expose production data.
Problems with this approach have already been discussed in other posts; in particular, with ASP.Net applications, you have to consider whether or not you are going to use Impersonation/Delegation (webserver can act as the NT user accessing it) or a Trusted User model (where you configure a fixed identity to access certain resources).
This is further complicated by the IIS version you are using.
If your connection string is stored in a web.config file, you could create a separate production version of that file that the deverlopers can't see. That's easier to test and setup than integrated authentication using app pools.
One word of warning though: If you restrict developers that much, it will slow down their velocity of change. Since the rest of the world does keep moving, this usually ends with the application becoming a dead legacy package. That's dangerous if you plan to grow, improve or extend.
Use of application pool's identity can be quite complicated to set up, consider trust and delegation problem.
A better option can be securing connection strings using encryption.

right place to have the connection string

Working with Azure web role that communicates to a SQL Azure database. Currently when I generate an edmx file for the SQL Azure database the connection strings + the username password are added to web.config file. I did a search and there were several entries on how to encrypt web.config/how to use that to switch between dev and prod but I am thinking of moving conn string out of web.config.
Is there a way by which I can move the connection string to the service definition file? Is that a recommended approach? If I move the connection string elsewhere can I still use the edmx and generated objectcontext classes (cause my existing code uses the automatically generated entity class).
It is best to move your connection strings into service config file. This allows you to switch over to a different SQL Azure database w/o redeployment. Switching to a different SQL Azure database w/o redeployment is useful when one has crashed or is timing out and you have a backup ready on a different server to switch over to.
You will need to initialize your object contexts by providing the connection string separately however.
Use the RoleEnvironment.IsAvailable to find out if you're running under Azure and the following code to read the setting in .cscfg:
var connectionString = RoleEnvironment.GetConfigurationSettingValue("ConnectionString");
I recommend having the connection string in both places, Service Configuration file (.cscfg) and Web.config. Where I also recommend from the beginning to have your web role able to run outside an Azure environment. It will impact your productivity in the long run. Especially with daily development where you do small changes and need to run the project locally to verify. Running your service locally in IIS, IIS express or Cassini (the codename for the Asp.net env) is currently faster than running your project in the local azure emulator (the devFabric).
Regarding your second question about storing the username and password. It all depends on the level of security that you're looking for. The information stored inside your .cscfg are transmitted over https and secured in the Azure cloud the same way your application is secured. That being said, I would store the TEST account credentials in the project for testing and would only put the PRODUCTION storage account credentials in the .cscfg at deployment time to the public/production service.

Best practice for passing actual user names from ASP.Net to SQL Server

I am looking for a best pratice to use the actual username in tSQL, while at the same time, my ASP.Net application logs into SQL Server with a global login, configured in the connection string in the web.config file.
This ASP.Net application is written as an extension to a SharePoint2007 implementation. The database this applies to is a legacy database, not a SharePoint database.
The application in question needs to log each insert, update and delete in audit (shadow) tables, including date&time and username. This is done by triggers.
The triggers use the SYSTEM_USER value, so that the global login is always written to the audit table.
There are about 2700 stored procedures in the system, and I guess that half of them perform DML statements.
What would be the best way to change the application so that the actual username is logged? My ASP.Net application knows the usernames. In fact, all of my users log in to the ASP.Net application with an Active Directory account.
I am considering the following options:
Use integrated security; but what about permissions that should only be granted throught the application, not to be used when connection with some other SQL client?
Set some global variable on each connection that is opened; but in the current code, each requests opens many connections, sometimes hundreds of them, to process the request.
Passing the username in the stored procedures, adding a field to each table. The trigger than simply reads the usernames from the tables in stead of deriving it; however, this requires a lot of modifications in database objects, potentially generating a lot of bugs.
Any comments on these options or perhaps other options to consider?
I normally use context info. Integrated security with impersonation will defeat connection pooling and passing username to procs just feels plain wrong.

Resources