How To Query for Specific User Access Rights - sql-server

I have an old database that I am inheriting. The access rights are not clearly defined anywhere and I'm looking for a quick way to get them for everyone. Let's say I have a user in my database that does not belong to any membership roles. However, they have been given access to do specific things to specific tables. For example, they can run select queries on table X and run update queries on table Y. I know I can find out what they have by going to the properties for each user. I would imagine, however, that there has to be a system table somewhere that has all of this defined in it and makes it easily queryable. What would this query look like.
FYI: I am working with SQL Server 2005
Update: Is there also a way to do this for all databases on the server?

Take a look at the Security Catalog Views, then check out MrDenny's answer here which gives a query to list a user's rights. I reproduce it here (tidied up to my liking)..
SELECT [Schema] = sys.schemas.name
, [Object] = sys.objects.name
, username = sys.database_principals.name
, permissions_type = sys.database_permissions.type
, permission_name = sys.database_permissions.permission_name
, permission_state = sys.database_permissions.state
, state_desc = sys.database_permissions.state_desc
, permissionsql = state_desc + ' ' + permission_name
+ ' on ['+ sys.schemas.name + '].[' + sys.objects.name
+ '] to [' + sys.database_principals.name + ']'
COLLATE LATIN1_General_CI_AS
FROM sys.database_permissions
INNER JOIN sys.objects ON sys.database_permissions.major_id = sys.objects.object_id
INNER JOIN sys.schemas ON sys.objects.schema_id = sys.schemas.schema_id
INNER JOIN sys.database_principals ON sys.database_permissions.grantee_principal_id = sys.database_principals.principal_id
ORDER BY 1, 2, 3, 5

Things are a bit trickier actually. The effective permissions are a combination of internal database permissions (queryable as Denny's query showed above by doza) and windows group membership. Th later unfortunately is stored outside SQL, in the AD schema so you can't realy query it.
So if your goal is to display 'Access to the table X is given to domain\someuser and domain\somegroup and denied to domain\someothergroup' then you can use the catalog metadata and query it, as showed in doza's post.
However if your goal is to answer 'Does user domain\someuser have access to table X?' you can't get the answer from the query above. That's right, despite the fact that you see a record saying the domain\someuser is granted access, you cannot answer if it has effective access. Remember that a single deny trumps all grants, and if domain\user is member of domain\someothergroup group then domain\someuser is effectively denied access.
To answer the later question you must use a different mechanism, namely you have to impersonate the user at SQL level and check the permission via HAS_PERM_BY_NAME:
EXECUTE AS USER = 'domain\someuser';
SELECT HAS_PERMS_BY_NAME('X','TABLE','SELECT');
REVERT;
Is worth noting that the first question can be answered by anyone with view privileges on the security catalogs, while the later requires impersonate permission, a much more powerful privilege.

Related

how to check groups for specific user in sql server [duplicate]

In the Security/Users folder in my database, I have a bunch of security groups, include "MyApplication Users". I need to check if I am (or another user is) in this group, but I have no idea how to query for it or where I could see this information. I tried looking in the properties, but couldn't find anything. Any ideas?
Checking yourself or the current user:
SELECT IS_MEMBER('[group or role]')
A result of 1 = yes,0 = no, and null = the group or role queried is not valid.
To get a list of the users, try xp_logininfo if extended procs are enabled and the group in question is a windows group :
EXEC master..xp_logininfo
#acctname = '[group]',
#option = 'members'
For a quick view of which groups / roles the current user is a member of;
select
[principal_id]
, [name]
, [type_desc]
, is_member(name) as [is_member]
from [sys].[database_principals]
where [type] in ('R','G')
order by [is_member] desc,[type],[name]
To find the AD Group members in the Instance, we can use below query:
xp_logininfo 'DomainName\AD_GroupName', 'members'
By using this query, we can find the below states.
account name, type, privilege, mapped login name, permission path
Accepted answer from DeanG is the preferred solution for getting this info within SQL Server
You can use Active Directory tools for this. I like Active Directory Users and Computers that is part of the Remote Server Administration Tools. Follow the link to download and install the tools on Windows 7.
Once installed, you can search for a specific group name:
Then you can see group membership using the Members tab:
If you don't want to use the AD browser packaged with RSA tools, there are several others available.
You don't.
Instead you use the users and groups to grant/deny privileges, and let the engine enforce them appropiately. Attempting to roll your own security will get you nowhere fast. A banal example is when you will fail to honor the 'one deny trumps all grants' rule. And you will fail to navigate the intricacies of EXECUTE AS. Not to mention security based on module signatures.
For the record: users, roles and groups are exposed in the sys.database_principals catalog view. sys.fn_my_permissions will return the current context permissions on a specific securable.
The code that is provided on the Microsoft page here works for me, every time.
SELECT DP1.name AS DatabaseRoleName,
isnull (DP2.name, 'No members') AS DatabaseUserName
FROM sys.database_role_members AS DRM
RIGHT OUTER JOIN sys.database_principals AS DP1
ON DRM.role_principal_id = DP1.principal_id
LEFT OUTER JOIN sys.database_principals AS DP2
ON DRM.member_principal_id = DP2.principal_id
WHERE DP1.type = 'R'
ORDER BY DP1.name;
Please let me know if this works for you!

SQL Server - You do not have permission to use the bulk load statement

Using SQL Server 2016, I am trying to configure a user other than 'SA' to import a file. The code I am executing is as follows:
EXECUTE AS USER = 'DataImports';
SELECT CURRENT_USER;
EXEC xp_cmdshell 'TYPE myFileNameHere.txt'
BULK INSERT DataImports.staging_AddressBook
FROM 'myFileNameHere.txt'
WITH (DATAFILETYPE = 'char'
, FIRSTROW = 2
, FIELDTERMINATOR = ' '
, ROWTERMINATOR = '\n');
The error that I get is:
Msg 4834, Level 16, State 1, Line 20
You do not have permission to use the bulk load statement.
I have validated the following:
I do have access to the file as the user required - The cmdshell TYPE returns the rows expected. I do not appear to have a file access issue.
I have INSERT permission on the database in general.
I tested by using:
SELECT
[DatabaseUserName] = princ.[name],
[PermissionType] = perm.[permission_name],
[PermissionState] = perm.[state_desc]
FROM
sys.database_principals princ
LEFT JOIN
sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
WHERE
princ.[name] = 'DataImports';`
I do have the bulk admin role
SELECT
r.name AS [RoleName],
m.name AS [MemberName],
CASE
WHEN m.name IS NOT NULL THEN 1 ELSE 0
END AS IsMember
FROM
sys.server_principals r
LEFT JOIN
sys.server_role_members rm ON (r.principal_id = rm.role_principal_id)
LEFT JOIN
sys.server_principals m ON (rm.member_principal_id = m.principal_id)
WHERE
r.type = 'R' AND m.name = 'Dataimports';
I have even configured the user to be a sys-admin (not part of the long term plan) but I'm still getting the error.
These are the main points that have been highlighted in the other SO tickets and general searches I have performed. I can import the table as SA but not as DataImports despite what appears to be correct configuration.
This is part of a job that is being run and currently we are having to give SA access just to read a file. Security wise this is less than ideal but I cannot work out what is missing.
Any suggestions of what else to check would be gratefully received - all the basics seem to be in place.
Any suggestions
of what else to check would be gratefully received - all the basics
seem to be in place.
Few things:
GRANT ADMINISTER BULK OPERATIONS TO Dataimports
If the destination table contains triggers or checks constraints
GRANT ALTER ON TABLE DataImports.staging_AddressBook TO Dataimports
And
ALTER DATABASE [yourDB] SET TRUSTWORTHY ON;
Because of:
For security considerations, the server-scoped permissions are
stripped down when you impersonate a database user unless the system
administrator has explicitly set SQL Server to trust the impersonated
context at the server-scope. In this case, a login with the control
server server-scoped permission has no permissions to access any
particular database. Therefore, the trigger module that is executed as
this login cannot run.

Remove permission from public

please see snap shoot below.I was wondering why I can't remove the permission with following code. But I can remove the permission by using the GUI.
REVOKE ALL ON OBJECT::[dbo].[Table1] FROM [PUBLIC];
It tested this on SQL Server 2005, and the query works fine. However, do not expect the table Properties dialog to update automatically, not even after moving forward and back to another page, like Storage. You must close and reopen the dialog to see the modifications.
I checked this by running the following script in steps:
Source: How to list permissions for Public Role for a database in SQL Server.
grant select, insert, update on dbo.Table1 to public
GO
SELECT a.[name] + ' ' + v.[name] + ' ON ' + QuoteName(oo.[name])
+ '.' + QuoteName(o.[name]) + ' TO ' + QuoteName(u.[name])
FROM dbo.sysprotects AS p
JOIN master.dbo.spt_values AS a
ON (a.number = p.protecttype
AND 'T' = a.type)
JOIN master.dbo.spt_values AS v
ON (v.number = p.action
AND 'T' = v.type)
JOIN dbo.sysobjects AS o
ON (o.id = p.id)
JOIN dbo.sysusers AS oo
ON (oo.uid = o.uid)
JOIN dbo.sysusers AS u
ON (u.uid = p.uid)
WHERE 'public' = u.name
GO
revoke all on object::dbo.Table1 to public
GO
-- Run query again
Please note that a warning is issued when using revoke all: The ALL permission is deprecated and maintained only for compatibility. It DOES NOT imply ALL permissions defined on the entity.

How to find loginname, database username, or roles of sqlserver domain user who doesn't have their own login?

I have created a login and database user called "MYDOMAIN\Domain Users". I need to find what roles a logged on domain user has but all the calls to get the current user return the domain username eg. "MYDOMAIN\username" not the database username eg. "MYDOMAIN\Domain Users".
For example, this query returns "MYDOMAIN\username"
select original_login(),suser_name(), suser_sname(), system_user, session_user, current_user, user_name()
And this query returns 0
select USER_ID()
I want the username to query database_role_members is there any function that will return it or any other way I can get the current users roles?
I understand that the Domain Users login is mapped into AD group?
You have to bear in mind that user can be in several AD groups and each of them can be mapped somehow in database which may be a bit messy. Also it means you need something with multiple results :)
Try this:
select * from sys.server_principals where type_desc = 'WINDOWS_GROUP' and is_member(name) = 1
I think it should grab properly all Windows Group logins that will be tied with particular users. After that you can join it for database users i.e.:
Select u.name from YourDB.sys.syslogins l
inner join YourDB.sys.sysusers u
on l.sid = u.sid
where l.loginname = ANY (select * from sys.server_principals where type_desc = 'WINDOWS_GROUP' and is_member(name) = 1)
You have to keep in mind that - all the way - you may need to handle whole sets rather then single values.

In SQL Server 2005, is there an easy way to "copy" permissions on an object from one user/role to another?

I asked another question about roles and permissions, which mostly served to reveal my ignorance. One of the other outcomes was the advice that one should generally stay away from mucking with permissions for the "public" role.
OK, fine, but if I've already done so and want to re-assign the same permissions to a custom/"flexible" role, what's the best way to do that? What I've done so far is to run the Scripting wizard, and tell it to script object permissions without CREATE or DROP, then run a find-replace so that I wind up with a lot of "GRANT DELETE on [dbo.tablename] TO [newRole]". It gets the job done, but I feel like it could be prettier/easier. Any "best practice" suggestions?
Working from memory (no SQL on my gaming 'pooter), you can use sys.database_permissions
Run this and paste the results into a new query.
Edit, Jan 2012. Added OBJECT_SCHEMA_NAME.
You may need to pimp it to support schemas (dbo.) by joining onto sys.objects
SET NOCOUNT ON;
DECLARE #NewRole varchar(100), #SourceRole varchar(100);
-- Change as needed
SELECT #SourceRole = 'Giver', #NewRole = 'Taker';
SELECT
state_desc + ' ' +
permission_name + ' ON ' +
OBJECT_SCHEMA_NAME(major_id) + '.' + OBJECT_NAME(major_id) +
' TO ' + #NewRole
FROM
sys.database_permissions
WHERE
grantee_principal_id = DATABASE_PRINCIPAL_ID(#SourceRole)
AND
-- 0 = DB, 1 = object/column, 3 = schema. 1 is normally enough
class <= 3;
The idea of having a role is that you only need to setup the permissions once. You can then assign users, or groups of users to that role.
It's also possible to nest roles, so that a role can contain other roles.
Not sure if its best practice, but it makes sense that if you have a complex set of permissions, with groups of users that need access to multiple applications you go something like:
NT User -> NT Security Group -> SQL Server Role -> SQL Server Role A, Role B ...

Resources