If a user is not authorized to see a database canI exclude that database from even appearing inManagement Studio for that user
TIA,
Barkingdog
Technology Tips and News
If a user is not authorized to see a database canI exclude that database from even appearing inManagement Studio for that user
TIA,
Barkingdog
I found the server-level permission "View any database", denied it to the test user, and found exactly that. The user couldn't see (under SSMS) any databases whatsoever including the one he is theDBO of! How can I assign him permissions to see that one database but no othersin theSSMS tree?
TIA,
Barkingdog
P.S. The evidence is if I removed that permission from "public" then no one -- maybe eventhe sa? - could see any databases in SSMS.!
How are you making the user an owner? Are you making him a member of db_owner or are you using the alter authorization statement to make the user the actual owner of the database?
You can tell by looking at the owner_sid in sys.databases - the sid should point to the owning login. If the login is the owner of the database, denying that user view any database will not prevent him from viewing the database in sys.databases or Management Studio.
Jack Richins
SDE Sql Server
I made him a member of the db_owner.
When I run
sp_helpuser
<DBName>it returns x01 as the SID for the username dbo.
When I run
use DBName
select
* from sys.databasesit returns.......
0x010500000000000515000000AAB950D6A501....
for the owner sid of the database.
So the user is not the DBO (though he belongs to that role).
Then back to my original question. How can I deny a user from seeing any databses in the SSMS tree that he does not have permission to access?
TIA,
Barkingdog
DENY VIEW ANY DATABASE to the test login. This prevents the user from seeing any databases for which the user is not the DBO. You can make the user a DBO by using ALTER AUTHORIZATION DATABASE::<database> TO <login>. Being a member of db_owner is not sufficient to see the database if "view any database" was denied.
This is not very clean and may not work for you if you can't make this user login the actual DBO of the database you want him to administer or have multiple logins you want to secure in this manner as only a single login can be the actual DBO of a database.
This is something we're investigating for future improvements. So if you could provide some details on what you would like this login to be able to do and what you don't want the login to see or do, it could help us better solve your problems as we design future versions of SQL Server. Also whether you use SQL Logins or Windows Integrated Logins - how many different logins you'd like to secure in this way, and anything else you think might be relevant.
Thanks,
Jack Richins
SDE SQL Server
Dear Jack,
This whole issue took me by surprise. In our shop we have three teams of developers and all thedevelopment datbases are in a single sql instance.One of the group leaders asked me if there is any way to preventthose not in his group from even seeing the database display name under SSMS and sql tools (e.g. query editor, via OLEDB).I don't know the reason for his concern --developers outside his groupare not authorized to even view his databasesbut from a security perspectiveit seems reasonable:If a user doesnot have access to a databse, why should the database even "exist"for that user.This applies regardless of the form of Windows authentication used.
TIA,
Barkingdog
Thanks, this isn't a scenario we'd been discussing so I'm glad you brought this up. I'm sorry we don't have a solution for you now, but hopefully in the future we can do something to enable this.
Thanks,
Jack Richins
SDE SQL Server
The main issue here is that determining what databases a user can see is an expensive check, as the permissions to access the database are stored in the database itself, so verifying them requires a database access. This prevents a general solution from being available through SSMS - some customers managehundreds of databases on a single server, which would make such checks prohibitive.
You can still write a view in SQL Server 2005 that could filter rows using "has_dbaccess() = 1" as a predicate, but you should only do this if you have a limited number of databases, as it would be too expensive otherwise.
I also want toaddthat we're aware of this request and we're looking at ways to address it.
Thanks
Laurentiu
This is what I ended up doing:
--SQL 2005
If
@@version like 'Microsoft SQL Server 2005%'Begin
-- Create Login only if it doesn't exist: IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE [name] = @Username) Begin Set @dsql ='create login ' + @Username + ' with password = N'''+ REPLACE(@password, '''', '''''') + ''', DEFAULT_DATABASE=' + QUOTENAME(@DBName) + ', CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF' execute (@dsql) set @dsql = 'use master; GRANT CONNECT SQL TO ' + QUOTENAME(@DBName) execute( @dsql ) End --Deny ability to see anything other than master, tempdb and user database. Set @dsql = 'use master; deny VIEW any DATABASE to ' + @Username --Print @dsql execute (@dsql)End
--Add user as dbo to database.
Set
@dsql = @DBName + '.dbo.sp_changedbowner ' + @Username--Print @dsql
execute
(@dsql)But, I don't think you can grant multiple user's to DBO, so you will only have one user that can see master, temp, and their database.
-Chuck Lathrope
This is possible for a single user login as you can only asign ownership of a database to a single user.
Should be ok for most small hosting situations. This is how I achieved it under SQL server 2008...
1. Right click the users logon under the users database if they exist and remove
(Note: Do not remove the user from under the main security login)
2. Run the following query
USE <customersdatabase>
ALTER AUTHORIZATION ON DATABASE::<customerdatabase> to <customerlogin>
USE MASTER
DENY VIEW ANY DATABASE TO <customerlogin>
Isn't the right way around this is to create instances for each separate group/application/user/whatever?
That way each group can have anything up to sa rights on their own instance and not know about or affect any of the other groups databases?
Obviously there will be some overheads but it seems to be the most secure and flexible option? You can have unlimited instances now can't you?
This is possible for a single user login as you can only asign ownership of a database to a single user.
Should be ok for most small hosting situations. This is how I achieved it under SQL server 2008...
1. Right click the users logon under the users database if they exist and remove
(Note: Do not remove the user from under the main security login)2. Run the following query
USE <customersdatabase>
ALTER AUTHORIZATION ON DATABASE::<customerdatabase> to <customerlogin>
USE MASTERDENY VIEW ANY DATABASE TO <customerlogin>
My friend, this works really good!
thank you a lot, you're a machine!
tested on SQL Server 2008 R2.
For me works (Sql2008R2)! Very simple and very useful.
Thank you very much.
Yes. This works really well! I tested this on SQL Server 2012 R2.
Thanks a ton!
Firstly, I decided to respond to this particular entry in this forum mostly because of the answers supplied, this one seems to have satiated the larger selection of people who happened across it and decided to respond as such. Secondly, my response below is in no means an antagonistic response to the solution provided. Lastly before moving on, I hope somewhere out there a Moderator/Person is actually still being alerted to these posts (especially since at least someone other than myself has posted here in 2015). If I am wrong, misunderstanding, or simply ignorant to some point made below I strongly encourage anyone to please set me straight and/or respond as such because I earnestly would like to understand any viable solution to this post's question, especially in regard to non-trivial (moderate to large Enterprise level) implementation.
To The Point Of It All:
Yeah, this "solution" still supposes that my only intention is to give <customerlogin> DBO access to <customerdatabase> ... when <customerlogin> is meant to have only, say role membership in db_datareader, this is the egregiously far away from my intended concern.
I find that nearly a decade from when this thread starts (and 3+ versions of SQL Server as of this posting later) this simple question is still answered in complete oblivion of the point a bit unsettling.
Case: I have a SQL <2005-2012,"2014"> Server (call it <server> here forward). I have use for both Integrated Security *and* SQL User logins (call them <user> here forward) for multi-various reasons which should not matter to the point. Explicitly to gain further insight only, the Integrated Security users can be either Local Users OR Domain Users OR Security Group(s), etc. I have no reason for any specific <user> to have DBO rights on any Database as I am the DBA for <server>. I inevitably encounter cases wherein I want/need to give a <user> direct access to <database> in some fashion. However, I want the granular control to be able to give them something to actually use for that purpose. Microsoft SQL Server Management Studio (SSMS) (or even nebulously <interface> here on) is, at times, the perfectly viable option depending on the <user>.
Problem: I can, generally within all <server> listed above, grant granular control to <user> for everything from CONNECT and LOGIN through explicit <database> and even explicit <action> (select, execute, etc.) on explicit <table,column,etc.>.
However, none of the proposed solutions address how to enforce the necessity to have <interface> only display to <user> what has been granted, despite all of <server> permissions available. How can I ensure <user> not only
DOESN'T have access to (which is sadly the harder problem which actually has solutions going all the way back through at least MSDE and SQL 2000) <server, database, action, table, column, etc.> which I haven't given access, and not only DOES have access
to <server, database, action, table, column, etc.> which I have given access to, but ONLY display to the <user> the parts which are applicable to them. Plenty of those pieces and parts have been implemented at least to the degree wherein
GRANT, REVOKE, DENY, ALLOW, etc. semantics allow me some level of ability to the semantical intent I am ultimately trying to implement, but far less is *still* applying my intention to relate that access clearly to <user>.
In specifics to this forums question... Why is there a DENY VIEW ANY DATABASE syntax with no corollary GRANT VIEW DATABASE <user> and DENY VIEW DATABASE <user> to date to simply allow my intention to be met without having to make the <user>
a DBO? I understand the cumulative access would immediately make the GRANT VIEW DATABASE <user> statement would likely yield a net gain of no change if the user were already prefaced with DENY VIEW ANY... but there still seems to be no earnest (nor straightforward)
mechanism to accomplish (as a surface-level view) a simple task: Let the DBA be able to set any <user> access and usage to the degree to which their business policies are set, and in doing so, relate those settings to <user>. The closest
approximation to an answer I've seen thusfar without trying to convince a DBA to just make DBOs for all the above premises is something like
http://www.mssqltips.com/sqlservertip/1593/granting-view-definition-permission-to-a-user-or-role-in-sql-server/
Think in terms of how Microsoft handles System Folders and Files, Network Shares, Active Directory (GPOs, User/Computer ACLs, etc.) and/or more generally the philosophical difference in usage between a Windows 2000 desktop and a Windows 8.1 desktop (then apply domain semantics for an even clearer relation). I realize the scopes are different and I realize there has to be a fine line between "too little", "too much", and "good enough"... but in this instance, I still cannot fathom the disconnect between what a Microsoft Domain Admin and a Microsoft SQL Admin fundamentally can and cannot do.
Solution: ?