Search code examples
sql-serversql-grant

SQL Server : deny select on recreated table


In SQL Server 2017, I have a user with ddladmin privileges that drops and recreates a table regularly. We need to have deny select on that table.

Only when the table is dropped, it loses the deny. I do not want to grant the user securityadmin.

How can I make sure the deny select on this table is retained each time it is recreated?


Solution

  • ...adjust

    revert
    go
    
    -- drop trigger deny_select_on_frequentlydroppedtable on database
    create or alter trigger deny_select_on_frequentlydroppedtable 
    on database  
    with execute as 'dbo' 
    for CREATE_TABLE
    as
    begin
        set nocount on;
        
        --when table name = frequentlydroppedtable
        if EVENTDATA().value('(EVENT_INSTANCE/ObjectName)[1]', 'sysname') = 'frequentlydroppedtable' 
        begin
            declare @tbl nvarchar(500) = concat(quotename(EVENTDATA().value('(EVENT_INSTANCE/SchemaName)[1]', 'sysname')), '.', quotename(EVENTDATA().value('(EVENT_INSTANCE/ObjectName)[1]', 'sysname')));
            declare @user nvarchar(150) = EVENTDATA().value('(EVENT_INSTANCE/UserName)[1]', 'sysname');
            
            if @user <> 'dbo' and IS_ROLEMEMBER('db_owner', @user) = 0 and IS_ROLEMEMBER('db_ddladmin', @user) = 1 --... any ddl admin gets deny when they create the table :)
            begin
                declare @sql nvarchar(500) = 'deny select on ' + @tbl + ' to ' + quotename(@user);
                exec(@sql)
            end
        end
    end
    go
    
    --dbo or ....
    drop table if exists frequentlydroppedtable;
    go
    create table frequentlydroppedtable(id int);
    go
    --works
    select * from frequentlydroppedtable
    go
    
    
    --create a test db_ddladmin
    create user test_db_ddladmin without login;
    go
    alter role db_ddladmin add member test_db_ddladmin;
    go
    execute as user = 'test_db_ddladmin'
    go
    drop table if exists frequentlydroppedtable;
    go
    create table frequentlydroppedtable(id int);
    go
    --permission violation, deny select
    select * from frequentlydroppedtable
    go
    
    revert
    go
    
    --cleanup
    drop table if exists frequentlydroppedtable;
    go
    drop user test_db_ddladmin;
    go
    drop trigger deny_select_on_frequentlydroppedtable on database
    go