Setting up database access - database

Which is the better way to set up access on some databases that my web apps query. I can only think of one pro for one and one con for the other, so I need some other input before making a final decision.
Option 1 – 10 apps, 10 databases, 1 Service Accounts for each app (User does not have direct access)
All query requests go through the Service Account to the database. The con I can think of is that there is no record of who sent the request, just that the SA accessed the db with a request.
Option 2 – 10 apps, 10 databases, User has direct access (no Service Account)
All query requests from the app go directly to the db and each request is logged, identifying who sent the request from what app. This setup could be locked down further by allowing the specific app access only to db/tables/columns that it needs to complete the request/query. The obvious pro is there would be no anonymous requests; all requests could be traced back to the requester and not just to a SA.

If by Service Account you refer to a functional account or database account for the application. This is the way to go. If you need to log who did the request your application should have user authentication and do the logging of the request.
The other alternative of a database account per user is not scalable and if you have to provide a database id for each user, which the user will be using to connect, it also has security implications.
By having the application between the user and the database you isolate the database from the outside and the only access is what the applications permits.

Related

Per user database authentication in Django

Good afternoon,
I am writing a front-end for a research database that holds sensitive health information. My institution has a policy that user actions be logged by the SQL server so that they can perform audits on the server log files in the event of a breach.
Because of this policy, I cannot connect Django to the db as a system user (otherwise, all users of the front-end actions would be logged by the server as the Django system user instead as the actual user individually).
Is there a way to connect to the DB using per user credentials so that actions performed on the front end will be logged as that user on the db server? I have been able to find a lot of information about using multiple databases, but nothing about per user authentication of those databases.
Thank you in advanced!
I don't think you can do that, the user that connect to the database need to have access to all the tables.
I had a similar issue when I wanted to use Django models outside Django and restrict access to certain models for certain users.
I ended up using SQLAlchemy and its automap feature on the existing Django database. Then you can connect to the database using your SQL users.
However, if you don't mind all the users accessing all the tables and are only concerned about the logs, maybe you can use a different settings.py or at least a different DATABASES configuration for each user?
I was able to accomplish this by giving the SQL user the IMPERSONATE permission and performing EXECUTE AS prior to the DB queries that I needed to have logged in models.py.
cursor = self.connection.cursor()
try:
cursor.execute("EXECUTE AS " + get_current_user()
except DatabaseError as e:
cursor.close()
raise e

How do I configure database connection per user account in Spring Data?

We have a requirement that user account can provide username/password for database. This means that after user account is loaded, the user should use his own database connection for persistence.
How do I configure that in Spring Data?
Which database?
Which ORM implementation?
Spring has the AbstractRoutingDataSource, which lets you change the DataSource at runtime.
You could also use a delegation pattern, where the web server connects as a limited user, and then changes role to a different user if their authentication is successful. See How to run SQL SET statements against db at start of connection/session using Hibernate? and Switch role after connecting to database
You'll probably need to disable caching in your ORM too.

Settings per connected user

I have an windows forms application which I'm migrating from MySql to MsSql. In MySql we are using database users for every user. So every user connects to the database using their own account. This is not what we want, because in the future we want the application set open to the world and database users is not a thing on the wishlist. So this is going away.
The problem is that many views work with a function which uses CURRENT_USER() to give access to records (because users are part of a department and are not allowed to see all records of all departments).
In MsSql we are using just one type of connectionstring, but every application connects the database directly. Is it possible in MSSQL to store variables per connection so I can identify a user in the view by the variable I set after creating the connection?
So it would be like this:
Start application
Users logs on
Application creates connection with mssql
Application sets a variables on sql-server
User opens a screen with a view
SQL server returns the view using the variable that has ben set earlier to only return the allowed records to view.
So every user must have it's own variable. Is that possible?
Application is build with NET and iBatis. Not the best combination, but iBatis is to much integrated to throw it all overboard.
While this may or may not be possible, it's definitely not the right way to go. As you said, you're using a single connection string, and likely using a pool of connections to access the database. As you want users to be able to pick any available connection in the pool to do their queries, you don't want any user state (or any state at all for that matter) to be tied to the connection.
As you're opening up to the world, you don't want the application to directly connect to the database. Instead, you should implement middleware that will handle authentication and access rights, and only return data from the database that the user may access. So instead of
user application <- iBatis -> MSSQL
you'll have:
user application <- HTTP/something else -> API <- iBatis -> MSSQL
This is the approach taken used by websites as well. In addition, you'll be able to add functionality like caching, connection pooling etc. to the API, making it possible to support more users.

database access impersonation

My objective is to prevent direct user access to the database server. One way is to create a WCF service or web service in the middle between the front end application and the database server.
First of all, the users will be authenticated to the application. Subsequently the application will connect through the WCF service to perform business logic operations. The WCF service will perform the database related operations by using one windows account. This will prevent other users to directly access the database server, since the permission will only be granted to specific one windows account.
Here are my questions : Even though the database access is only granted to one windows account and the WCF will use this windows account to perform database related operations, is it possible to mark all database related operations with the credential of the logged in user ?
Update
Thanks for the replies. Seems like the above scenario is not achievable. I am currently exploring the SQL 2008 Application Role feature. One of the example is here. But after further exploration, apparently there is an issue with the connection pooling.
Update
There is a stack overflow thread here regarding SQL Server Application Role
You'd have to have every user set up in sys.server_principals to enable context switching like EXECUTE AS which would mean that they have direct db access anyway.
If you enabled kerberos/delegation, the same applies. Links One and Two
You'd have to pass in the user name as a parameter on each SQL call, or use CONTEXT_INFO perhaps.
Note: every MS Office user has MSQRY32.EXE which acts as a query tool. If you want no direct DB access, then you need to ensure there are no permissions set or granted
Depends.
If your database and WCF service are on the same box and you do a lot of jiggery pokery to impersonate then it is possible. As soon as you move your DB to another box then it stops working.
This is a known limitation and the reason is impersonation will create a token which will get you to a box but this is not passable to another box. I tried to find the Q&A where MS guy had answered but still havent been able to. Whenever I find it, will update.

Is it true that SQL auth is only great for multiple role apps?

I believe Windows auth is the best practice to use to connect to SQL DB. I am hear talking about application user account..
Is it true that SQL auth is only great for multiple role apps and window auth is only good for single role app? I never heard that windows auth with muitple role os only good for smaill internal app?
multiple Windows logins = multiple connections = no pooling = poor scaling?
The problem with using Windows auth for a web application is that many web applications store their application users' credentials in the same SQL database that is used for other application data.
So you have a chicken-and-egg problem. You can't authenticate the user before connecting to the database, and you can't connect to the database without authenticating the user.
It should be possible to use Windows authentication, and then also have application-specific attributes of the user stored inside the database. But most people find this cumbersome to administer, and also limiting to portability of the application.
For example, if one of the feature of the application allows users to change their own password, then the process running your web application needs the privilege to alter a Windows password, which may mean that the application needs to run with Administrator privileges.
If you let the application manage user ID for the context of the application, then to change a user's password is just an SQL operation, and your application is in charge of enforcing security for that.
I'm not sure what you mean by single-role and multi-role app. I have built apps before where there are multiple SQL Server Database Roles, each with a Windows Domain Group of users allowed in that role. So user management is completely within Active Directory, with a 1-1 correspondence between the Domain Group and the Database Role.
We typically did not manage the security within the application itself except obviously declaratively during the database creation where each object was granted access by particular roles according to the design. Typically, in a simple case, we relied on db_datareader role being granted for general usage to non-specific groups of users like database and network administrators for troubleshooting or report-writers or business analysts for ad hoc reporting. Actual users of the app would be granted execute on the relevant SPs to be able to modify any data (so all data creation or modification was through SPs and only explicit members of the ThisAppsUsers AD group could do it). Any advanced SPs (say, merging or deleting accounts) would only be accessible by ThisAppsAdmins AD group. And that was usually all we needed for moderate-sized applications. For more complex functionality, it was also possible to interrogate AD directly for custom attributes (user is an admin only for this customer account but for others is just a user)
This same technique can be used with SQL Server logins, but of course the individual SQL Server logins have to be added to the database roles, and you don't have the richness of AD and have to build some kind of directory service into your database.
The ability to even use AD may not be possible for many applications, so in that case, the security architecture would obviously have to cater to that model.
using the integratedSecurity=true option for SQL JDBC , by including the JDBC auth .dll, should give you database connectivity without authenticating...

Resources