Generic SQL Security

Quick intro on granting SQL rights in general- I’ve found to quickly setup SQL security I normally use the “db_datareader” and “db_datawriter” roles (assuming entity needs write access) but often times I also need them to be able to execute a stored procedure as well. I don’t want to give them much more access so I find it convenient to just create a “db_executer” role I can assign:

CREATE ROLE db\_executor
GRANT EXECUTE TO db\_executor

SSIS Security

Anyway, back to the real subject of the post, SSIS- if you have a job you want someone to run from SSIS, they need to have permissions to the SQL SSIS database. Usually I don’t want to manage individual permissions at the user level in SQL server, so a popular options is to create an AD group and grant that AD group access to the SSIS database as needed. Then one only needs to manage the AD group. More on SSIS security here.

Recently, we had a situation where we had a report that fired off a store procedure that submitted an SSIS package, waited for it to finish, and returned the results. (here’s how) We were using windows authentication which wasn’t optimal because we had to grant that group/users access to the SSIS database- and plus we had to update security in two places, the SQL SSIS database and the SSRS report.

For this situation, creating an AD group that was used by both SSRS and SSIS didn’t make sense because they would both likely diverge at some point, but mostly we didn’t want to provide those users access to log into the SQL database. So instead we created a single user account that the SSRS data source could use to connect to the SQL server- then we can just control access to the report from SSRS security. By the way, one caveat to this method is that the account can’t be SQL account- it has to be Windows authenticated account in order to run the SSIS package[s].

 

Removing SQL Users from SSIS Database

Anyways, after I did that I decided to clean up the database but found I couldn’t delete the users from the SSIS database; I got an error that dropping the user failed:

Msg 27226, Level 16, State 1, Procedure ddl\_cleanup\_object\_permissions, Line 16
The database principal has granted or denied permissions to catalog objects in the database and cannot be dropped.
Msg 3609, Level 16, State 2, Line 1
The transaction ended in the trigger. The batch has been aborted.

I quickly unchecked all the database role memberships but still couldn’t drop the user. I ended up going through a series of steps with some valuable queries that I wanted to share for future debugging. First, I looked at the permissions assigned to the user:

SELECT \*,
object\_name(major\_id) as securable,
user\_name(grantor\_principal\_id) as grantor,
user\_name(grantee\_principal\_id) as grantee
from sys.database\_permissions
where grantee\_principal\_id = user\_id('[DOMAIN]\[USERNAME]')

At this point this only showed the “CONNECT” priviledge, which I was able to revoked:

REVOKE CONNECT TO [DOMAIN\USERNAME]

Now as far as I could tell my user didn’t have any rights but I still got the same errors. I should have paid more attention to the error message- particularly the part about a trigger. This is a trigger in the SSIS database that fires off when dropping a user that has SSIS catalog permissions. SSIS has its own permissions layer and those permissions needed to be revoked in order to remove the user. SSIS catalog permission information on users can be found in [SSISDB].[catalog].[explicit_object_permissions] table. I found a handy query for querying this information and generating the SQL to revoke the permissions using catalog.revoke_permission here:

SELECT TOP 1000 [object\_type]
 ,[object\_id]
 ,[principal\_id]
 ,[permission\_type]
 ,[is\_deny]
 ,[grantor\_id]
 , 'EXEC catalog.revoke\_permission @object\_type=' + CAST([object\_type] AS VARCHAR) 
 + ', @object\_id=' + CAST([object\_id] AS VARCHAR) 
 + ', @principal\_id=' + CAST(principal\_id AS VARCHAR) 
 + ', @permission\_type=' + CAST(permission\_type AS VARCHAR)
 FROM [SSISDB].[catalog].[explicit\_object\_permissions]
 WHERE principal\_id = USER\_ID('Your User')