Friday 2 December 2022

How do I grant view permissions so a SQL Login can see only one database?

 I want to create a database (SAMPLE) with an system administration account and then access it using a SQL Login, similar to a service account.

That SQL Login should not be able to see the other databases in my server instance. Online, there are many articles that offer one of three variations on a solution.

Option 1. do the following a) DENY ANY DATABASE to the user and then b) grant permissions on the database in the User Mappings. This does not work.

Option 2. do the following a) DENY ANY DATABASE to the user and then b) ALTER AUTHENTICATION on the database. This works, but changes the ownership of the database to the user SQL Login. I don't want this. The system admin account used to create the database needs to remain its owner. The SQL Login should be able to view it.

Option 3. involves using "contained" databases, which is not an option for me.

Conceptually, I am thinking there should be a fourth option that looks something like:

Option 4. do the following a) DENY ANY DATABASE to the user and then b) GRANT VIEW ON DATABASE::SAMPLE TO SAMPLE_USER. This would deny blanket visibility while restoring itemized visibility, but I have not figured it out.

Testing Results:

This is what the SAMPLE_USER sees when I implement Option 1. It does not expose the SAMPLE database to the SAMPLE_USER Login, even though it is mapped. This does not work.

54116-001.png

This is what SAMPLE_USER sees when I implement Option 2. This works, however, it changes the database ownership which I cannot allow.

54015-002.png

I am going to add a follow on with details of how this is configured. But, the question is, how do I grant view permissions to ONE database that does not change the ownership of that database?


--------------------------------------------------------------------------------------------------------------

Answer:

Bottom line: We cannot limit what the SQL Login sees without changing is role in an unacceptable way, but we can control what it can access.

https://www.mssqltips.com/sqlservertip/2995/how-to-hide-sql-server-user-databases-in-sql-server-management-studio/

Per the article,

Conclusion
…there are limited options to hiding databases. Once you hide all databases the only logins that can see the databases are the logins that are the owners of the database or if the login is a sysadmin. Also, each database can only have one owner, so you can’t assign multiple owners to the same database.

Solution:

Start with a database (SAMPLE), a database level user (SAMPLE_USER) that is linked to a server level login (SAMPLE_LOGIN).

Use the server level login (SAMPLE_LOGIN) to set its Mappings to include the SAMPLE database.

54050-d.png

Here you can see what my SAMPLE_LOGIN sees at the server level (everything) while it throws an error if I try to access any database…

54096-a.png

In contrast, when SAMPLE_LOGIN tries to access a database that it is mapped to (as SAMPLE_USER is a database level user account that links to the server level SAMPLE_LOGIN), it can see the objects inside that database that have been granted to it under database user’s Securable permissions.

54107-b.png 54108-c.png

No comments:

Post a Comment