Constrain LINQ2SQL Datacontext to specific SQL Application Role - sql-server

In SQL Server you are able to have application role security, through which you are able to for example give specific permissions that originate from specific applications.
You can execute sp_SetAppRole() to set the application role but was wondering how this could be accomplished when using a LINQ2SQL datacontext with the least amount of friction.
I've seen this link:
http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/e25e98a6-b0ac-42fc-b70c-2b269a7fa1cb but was hoping for a cleaner approach/

My conclussions (see below section for the why):
Using SQL application roles doesn't plays well with connection pooling and also shouldn't be used directly in final user apps (only on a business tier).
The SQL alternative would take away a lot of advantages from using linq, as it relies in SPs.
My recommendation:
If you have a business tier/server, do authorization at the application level instead of relying on sql authorization. If you still want to authorize, have an account associated to the business tier application, and associate a normal role to it.
If it is a client app that connects directly to sql. The user will still have the permission to call whatever his(her) identity has access to, and the app password is there. If you are not comfortable with the user having that level of access, you need a business tier.
If you still want to proceed with the approach, turn off connection pooling. To reduce the open/close overhead, open connections explicitly.
Full explanation/references:
One issue is it doesn't plays well with connection pooling. That is regardless of linq2sql. See at the end of this in msdn.
There are 2 alternatives since sql server 2005 (msdn link), one is also mentioned in the thread you linked to, but it also points out it can go wrong.
Note that its an unsecured option in a 2 tier scenario, like when the application used by the clients connects directly to sql. In those cases the pwd for any application in the client's computer would be exposed in those. Its more secure if it is a business tier the ones that connects, but that's precisely the case where you really want connection pooling.
The another alternative mentioned in my second link to msdn, works well with connection pooling. It is based on stored procedures, and the execute as statement. The execute as is called inside the procedure, and after the procedure is executed the context is reverted. That is great but really would be giving away a lot from what you get with linq2sql by going the sp route.

Related

Using Windows Authentication with Sql Server with Windows applications

Microsoft recommends using Windows authentication when connecting a Windows application to an SQL server database.
http://msdn.microsoft.com/en-us/library/89211k9b.aspx
I understand this to mean that the database must have a user with enough permissions to manipulate data and that user links to the currently logged in Windows user. If this is true, how do I prevent the user from bypassing the application and simply modifying data directly in the database?
It seems like I am stuck between using Windows Authentication and potentially allowing users to modify data directly in the database, or attempting to hide the connection string password somewhere so only the app can modify this data.
If you're that concerned about it, you can implement a logon trigger on the server that for certain people (e.g. members of a certain Windows group), they can't log in unless the application name has a certain value. Note that this is weak security since it's pretty easy to set the application name (even in SSMS). It can/will slow down the logon process, though. So keep that in mind if that's a concern for you.
Alternatively, you can have your application authenticate to and interact with an application server, after which the application server connects to and interacts with the database. The application server can run as a service account, to which you'd grant the permissions you need. This way, the end users' accounts aren't in the database to do raw DML against the db.
But I agree with the other answer here: stored procedures are the classic answer to this question.
It is possible to create stored procedures / views etc and only allow the user permission on those. This prevents the user from accessing the database structure directly, and you maintain control over what the user can do (via creating the functionality in the stored procedures / views). If using windows credentials, I think that this would be the best solution.
This site explains how to grant there permission on stored procedures.
http://msdn.microsoft.com/en-us/library/ms345484.aspx
Here is the list of options, for posterity:
Windows authentication only
Pros: simple, No secret to hide.
Cons: user can easily modify data bypassing your app
Password in connection string
Pros: simple, prevents user meddling in your db's.
Cons: have to hide a password yourself, which is always the worst option.
Sprocs access
Create sprocs to access your data, grant access only to those sprocs. No one but the dbo can alter tables.
Pros: Tightest control over what both the user and the application can do to the data
Cons: Higher coupling of database and application; more expensive than the first 2 options.
Proxy
Create a second executable, whether a web or a windows service, with which your GUI application communicates. The 2nd executable can run with different, securely hidden credentials (IIS, Windows Services).
Pros: Decoupled database and executable, securely hidden secrets.
Cons: By far the most expensive solution.

Multiple database users for ASP.Net MVC project SQL Server Auditing, or roll our own?

We currently have a SQL Server 2008 instance set up for our ASP.Net MVC application, and the SQL Server instance uses built-in auditing (I believe CDC?)
We also have our ASP.Net application set up to use one connection string specified in web.config for the entire application, no matter who is logged in (of about ~50 users)
The problem: We want to be able to include among the audit information the username of the user who made the particular change in question.
It looks like we can only do that in one of two ways:
Change our application setup so that every single user gets their own database login. This would require us to use dynamic connection strings (perhaps not too terrible), but moreover it would be a pain in the ass to add a new user to the system and the admins could no longer do it automagically via the application's interface (I think).
Use another solution from within the ASP.Net app itself. This would allow us to trivially add any bit of information in the application we wish, but would involve scrapping the entire builtin solution and essentially starting from scratch with a significant effort.
Someone must have run into this problem before with auditing - is #1 feasible? Or is #2 the only way we can go here?
Thanks
Option #1 is pain for the admins, a little complicated code for "dynamic" connection strings, and calling sp_addlogin to create users. But the worst is that separate DB login for every user also allows them to query DB directly (if they know instance & database names, which could leak to them in any way and "see" DB server through the network). Direct access to the DB is something that may crash every application. Don't do it, unless you're very sure that DB server is not directly reachable to the users.
About #2. How about adding column "LastModifiedLogin" to every table, where you put login of logged in user during every insert/update? This shouldn't crash CDC and you got what you want. However auditing delete is little problematic, because you issue statement and have no longer row where you could place the login. You may organize seperate "DeleteAudit" table where you put name of table, row identifier and user login on every delete, but that's only rough idea.
If you use NHibernate for data access, I would advise you to consider switching CDC to NHibernate Envers, which is very neat solution.

Application vs SQL server 2008 accounts issue

Good day all,
I am studing the following case:
Scenario: An application connects to the production database(SQL server 2008) using a generic "SA" user instead of the domain user. This is making traces\logs\organization harder, because everything is flagged as done by SA user!
NOTE: In the application the domain user/password is used, the generic account is only regarding to the database.
Questions: What would be the best pratice in this case? every user should have an account to log in the database? (sql using windows authentication) there are +- 500 users is that an issue regarding to database performance? or a generic account is indicated?
Many thanks!
As others have mentioned, Active Directory and Windows Authentication might be more appropriate if that's an option. But if not...
If the application has a central place that creates the connection & transaction prior to update, you may be able to use SET CONTEXT_INFO to pass along the "real" application user while still using a shared SQL account for the login.
Then in your auditing triggers you can pull the information back out again using the CONTEXT_INFO() function
This is the approach used by at least one commercial auditing tool
See also similar SO questions here and here which reference context_info and a blog post Exploiting Context_Info for Fun and Audit which gives an NHibernate example.
Nitpick on something else in your question: you said it's using sa user. Maybe that was just an example, but probably the application should not have so many rights on the server. Create a user with only the rights needed for the particular database(s) that application uses. This limits the impact of any future security vulnerability (e.g. SQL Injection) in your application. And to take it one step further, you might have one connection string with a read-only user account, and then at the point where you create a transaction to update data, switch to a connection string with the read/write user account. You still get most of the benefits of connection pooling, but you limit even further the impact of any application-tier bugs.

SQL Server Authentication or Integrated Security?

We have some corporate intranet users using a WinForms app to work on a system with SQL server behind. Integrated Security is setup, allowing all users update and delete permissions, where application security limits how and where table updates take place.
However, some users are power users with SQL query tools at their disposal, and access the DB directly for building reports. However, with integrated security, they have default update rights on tables where they should not have, as the application apply rules to the updates.
Is this an example of where it's more appropriate providing the app with a central SQL authenticated login, whilst users get read only rights for integrated security?
As Jon mentioned stored procedures would give you the protection over direct table modifications. There are other options too. You can use SQL Server's "Application Role" (via sp_setapprole proc). This enables you to continue to use a separate ID for everyone but only at application connection time (through the front-end) are the user's rights elevated.
A major downside to using a shared ID is you lose track of who is submitting SQL to the server though if they're all internal you can get to the machine name.
Something else is concerning though. It sounds as if your users can connect to the database and run queries at will. You run a major risk of downtime in the application due to user behavior in the directly connected SQL sessions. If you can pull it off you may want to try to have a reporting database created that is updated at intervals that your business can tolerate, i.e., daily. HTH
I presume from the way that you've worded your question that your app executes sql statements directly. If you could refactor it so that it executes stored procedures, you could grant exec rights on the procedures and deny direct updating of the tables. This might not be possible though, depending on what your app does.
sql authentication is one option. Stored procedures are another. However, building more granular roles for assigning just the appropriate permissions to just the appropriate user types is where you should really be looking.
Additionally, I would really avoid giving these users direct access to the DB at all. Security reasons aside, it doesn't take much for a user who isn't proficient in SQL to accidentally execute a query that will swamp your database server and create an effective denial of service. Even pros can do this accidentally from time to time.
Instead, give them access to a reporting services or analysis services type solution, or use replication to give them access to a clone of the data. This way your production system is protected.
Personally I would do all application data access through stored procedures. I would set Integrated security to only allow users to run the SP's and not manipulate the data directly.
Advanced access can be given to DB admins to manipulate the data directly when needed.
Group based permissions will provide you with much more flexibility for access rights, and less administrative burden when controlling these with integrated security.

What are the best practices on MS-SQL when Windows Authentications is not an option?

What is the best option for a windows application that uses SQL server authentication? Should I create a single SQL account and manage the users inside the application (using a users table). Or should I create a SQL server account for each user. What is your experience? Thank you!
Depends on whether the username/password for the SQL server would be exposed to the user, and whether that would be a problem. Generally for internal apps (in smaller organisations), one would trust the users not too log in directly to the sql server. If you have a middleware layer (ie webservices) the password can be hidden from user.
I prefer to use a general login for the DB and manage users in the application. Even if you do create a login to sql for each application user, they could still connect directly, so why not just use a generic sql login that is easier to manage. This is of course assuming all users have the same accesses.
One good practice, if the users potentially can get direct access to the db, would be to grant access only through Stored Procedures and not directly to tables, so that only certain actions can be performed. Steer away from writing business logic or security checks (except basic ones) within the stored procs.
One way I would solve your problem is to write some webservices that check security and does your CRUD (via datasets, etc), but again it depends on the app and environment.
In summary if you have a middle layer or all users have the same access manage the user within the application and use a single user login. Otherwise use a login per user or role.
One option that I have used in the past is to use the ASP.NET Membership Provider. It makes authentication a breeze to use. The only drawback that I saw was that it added a bunch of tables to your database.
The code for using it is very straight-forward.
Here's a blog post about using this in a Windows app. http://msmvps.com/blogs/theproblemsolver/archive/2006/01/12/80905.aspx Here's another article with more details. http://www.c-sharpcorner.com/UploadFile/jmcfet/Provider-basedASP.NET10162006104542AM/Provider-basedASP.NET.aspx
Here's another article that talks about using it with Windows applications: http://www.theproblemsolver.nl/usingthemembershipproviderinwinforms.htm
Google for "ASP.NET 2.0 Membership Provider", and you will get plenty of hits.
What about having SQL accounts based on the level of permissions needed for the task. For example you could have a read only account just used for reporting if your system has a lot of reporting. You would also need an account what has write access for people to change their passwords and other user admin tasks.
If you have situations where certain users are only going to have access to certain data I would have separate accounts for that data. The problem with using 1 account is you are saying that there is no SQL injection anywhere in your application. That is something everyone would strive for but sometimes perfect security is not possible, hence the multi-pronged approach.

Resources