The first thing to understand about SQL Server security is that SQL Server is built with the idea that security has to be granted. In other words, if SQL Server sees no applicable permissions for a user, the user has no access. If you're familiar with Windows file or share permissions, it works the same way.
GRANT
In order for a user to be able to do something, he or she must be given permission to do it. We do this via the GRANT command. However, before we demonstrate that, let's do some setup of a test role and a test user in a test database I've created (aptly called TestDB):
Create Test User
Create Tables and Permissions
Now let's create a schema, a couple of tables, and let's GRANT the ability to select against the first table.
Test Harness Queries
Once that is done, let's use two "test harnesses" to test the user's ability to access the tables in question. Note that with the current permissions, the user should only be able to issue a SELECT against the first table.
Seeing the Permissions
In order to see the permissions that are granted, we'll use the sys.database_permissions catalog view. If you issue this query now, you'll see the first GRANT we made. Re-use this query to see the permissions after each change:
REVOKE
REVOKE undoes a permission, whether it's a GRANT or a DENY (more on DENY in a minute). If you issue the following REVOKE and then check the permissions, you'll note that the GRANT that was previously present for Test.Table1. After issuing the revoke command, re-run the test harness queries above against that table and you'll see that the user cannot query the table any longer.
Remember, REVOKE doesn't cancel a GRANT. It doesn't block a GRANT. It removes a permission at the level specified to the security principal (user or role) specified. That's why we say it undoes a permission.
DENY
DENY blocks access. DENY trumps all other access. If a user has both a GRANT and a DENY on a given object, by whatever means, the DENY will take effect. For instance, let's consider the case of a GRANT SELECT against the Test schema. This would give the ability to issue a SELECT against any table or view in the Test schema. Try just applying this permission, re-checking the permission, and then testing the user's access to both Test.TestTable and Test.TestTable2. You'll see the user can now issue a SELECT query against both tables.
If you're not familiar with schemas and how they affect permissions, see this tip on nested permissions due to securables. Sometimes, if you look for an explicit permissions against a table or stored procedure, you won't see it. However, the user can execute the SELECT or EXECUTE respectively. If this is the case, then the permission is on a securable that contains the object. That's what we're doing here. The Test schema contains the TestTable and TestTable2 tables. So if a user has SELECT permissions against the Test schema, it also has SELECT permission against any tables and views within the Test schema.
Now let's apply a DENY. In this case I'm applying a DENY explicitly to the test user instead of going through a role. And I'm only applying it to the Test.TestTable object. Now re-run the test harness queries. You'll see the access is denied. However, you can still query Test.TestTable2. There isn't a DENY applied against it.
And if you re-run the permissions script, you'll see all the permissions granted, to include the DENY.
No comments:
Post a Comment