Problem
Recently I was supporting a third party application. It queries to determine what tables it has permissions to before it proceeds with the rest of its functionality. We had implemented permissions based on the best practice of creating roles, assigning the permissions to the roles, and then making the users members of the roles. The application was querying INFORMATION_SCHEMA.TABLE_PRIVILEGES and of course didn't find any permissions directly against the user in question. We ended up granting explicit permissions to the user so the application would work, but I'm more interested in the general case. How can I determine permissions for an individual user?
Solution
Let's take the simplest case, where permissions are assigned directly against objects such as tables and views. If you're following security best practices, creating roles and assigning permissions to roles, then you're right, INFORMATION_SCHEMA.TABLE_PRIVILEGES is going to fail you. To see this, let's set up a simple example. I'm using the Testing database here, just a small database I've created for the demo. I'd advise you to create your own so you can walk through the example.
Now that we have a user, a role, a table, and security to query the table assigned to the role, let's use INFORMATION_SCHEMA.TABLE_PRIVILEGES and query for the user's permissions.
We don't get anything back because INFORMATION_SCHEMA.TABLE_PRIVILEGES only handles the explicit case where the user is directly granted the permission. Since the permission is coming from the role TestUser is a member of, nothing comes back. However, the issue isn't just limited to INFORMATION_SCHEMA.TABLE_PRIVILEGES:
The issue here is that the grantee, the database user or role that has the permission, is not the user. While the user receives the permission, these specific queries don't do it for us. There are some tools that would work, including a system function, fn_my_permissions(). However, the problem with fn_my_permissions() is you'll have to impersonate the user in question like so:
Also, you have to state the object explicitly. Another option is HAS_PERMS_BY_NAME, but this also requires impersonation:
So what can we do? Actually, we do need to query permissions for the roles the user is a member of. This query will do the job, but only if you're not nesting roles. If you are nesting roles, then you're looking at a Common Table Expression to get the list of all roles the user belongs to. But again, let's consider the simplest case, where no roles are nested.
And there you have it. While the security best practice is to use roles for security, determining what access an individual user has can be a little frustrating. SQL Server isn't alone on this, as we encounter the same issue on Windows. That's why it's really important to design your security model well and simplify it as much as you can so things can be easily understood.
Source Collected from MSSQLTIPS.COM
No comments :
Post a Comment