2009-08-12 10 views
9

Szukałem na przechowywanie jakiejś postaci identyfikatora transakcji od wyzwalacza kontroli. Rozwiązaniem okazało się użycie sys.dm_tran_current_transaction, jak w tym poście SQL Server Triggers - grouping by transactions.Bieżący identyfikator transakcji w wyzwalaczu kontroli

Jednakże, nie mogą korzystać z tego, ponieważ konto użytkownika uruchomiony SQL nie będzie mieć „widoku serwera Państwo” pozwolenie i prowadzi do błędu:

 
Msg 297, Level 16, State 1, Line 3 
The user does not have permission to perform this action. 

Czy ktoś wie alternatywa do tego poglądu, że dostarczy podobny identyfikator transakcji lub sposób użycia "Z WYKONAĆ JAK" na wyzwalaczu, aby umożliwić wybór z tego widoku.

Z moich prób "WITH EXECUTE AS" wynika, że ​​uprawnienia na poziomie serwera nie są przenoszone, co jest oczekiwane, ponieważ podszywa się pod użytkownika bazy danych.

Odpowiedz

13

Możesz rozwiązać prawie każdy problem związany z bezpieczeństwem, korzystając z podpisywania kodu. Najbardziej szczegółowa i precyzyjnie dostrojona kontrola dostępu, jest po trosze trudna do zrozumienia.

Użyj parametru EXECUTE AS OWNER w wyzwalaczu, utwórz certyfikat, podpisz wyzwalacz, upuść klucz prywatny (aby nikt inny nie mógł go użyć, aby kiedykolwiek cokolwiek podpisać), wyeksportuj certyfikat (tylko klucz publiczny), zaimportuj certyfikat do master, utwórz login uzyskany z certyfikatu, ułóż uwierzytelnienie na tym loginie (w celu uzyskania extend the database execute as impersonation), a następnie przyznaj stan serwera temu logowaniu. Jest to świetnie kontrolowana, kontrolowana kontrola praw własności. Jeśli wyzwalacz wymaga zmiany, proces podpisywania (w tym login i granty pochodzące od certyfikatu) musi zostać powtórzony. Z punktu widzenia bezpieczeństwa jest to pożądane (podpisujesz konkretny wariant wyzwalacza ), z operacyjnego punktu widzenia jest to raczej pita, ale można nim zarządzać.

create table t (i int); 
create table audit (transaction_id int); 
go 

create trigger t_audit_trigger 
on t 
with execute as owner 
after insert, update, delete 
as 
begin 
    set nocount on; 
    insert into audit (transaction_id) 
    select transaction_id from sys.dm_tran_current_transaction; 
    if (@@ROWCOUNT != 1) 
     raiserror(N'Failed to audit transaction', 16, 1); 
end 
go 

create certificate t_audit_view_server 
    encryption by password = 'Password#123' 
    with subject = N't_audit_view_server' 
    , start_date = '08/10/2009'; 
go 

add signature to t_audit_trigger 
    by certificate t_audit_view_server 
    with password = 'Password#123'; 
go 

alter certificate t_audit_view_server 
    remove private key; 

backup certificate t_audit_view_server 
    to file = 'c:\temp\t_audit_view_server.cer'; 
go 

use master; 
go 

create certificate t_audit_view_server 
    from file = 'c:\temp\t_audit_view_server.cer'; 
go 

create login t_audit_view_server_login 
    from certificate t_audit_view_server; 
go 

grant authenticate server to t_audit_view_server_login; 
grant view server state to t_audit_view_server_login; 
go 
+0

Dzięki za dodatkowy link do tematu msdn na ten temat, bardzo pouczające. –

+0

Witamy w klubie lol. Z tobą, jesteśmy teraz 4 osobami na planecie, które faktycznie czytają ten artykuł. –

+0

Jeśli masz wiele wyzwalaczy, możesz wysłać zapytanie do widoku wewnątrz funkcji zdefiniowanej przez użytkownika i podpisać tę funkcję za pomocą certyfikatu (zgodnie z sugestią w odpowiedzi nr 6 na stronie http://dbaspot.com/sqlserver-programming/197082-the- any-function-statement-return-transaction-identific-id-between-begin-trans-commit-trans.html). Następnie możesz użyć tej funkcji we wszystkich wyzwalaczach. Dlatego jest to pojedynczy obiekt, który musisz ponownie podpisać, gdy zdecydujesz się na zmianę. –

2

Mimo że nie odpowiadasz bezpośrednio na twoje pytanie, zamiast używać niestandardowej struktury kontroli, w SQL Server 2008 możesz skorzystać z technologii Change Data Capture.

Patrz następujące odniesienia z Books Online: http://msdn.microsoft.com/en-us/library/bb522489.aspx

EDIT (roztwór, dodano): Oto solucja, jak utworzyć procedurę przechowywaną, aby uzyskać dostęp do widoku systemu, wykorzystując execute jako klauzuli i używanie podszywania się.

USE MASTER; 

select * from sys.dm_tran_current_transaction 

--Create a login with view server state permissions 
CREATE LOGIN ViewServerStateLogin 
WITH password = 'Hello123'; 
CREATE user ViewServerStateLogin; 

--Create a login to test the permissions assignment 
CREATE LOGIN TestViewServerState 
WITH password = 'Hello123'; 
CREATE user TestViewServerState; 

--Test with Login 
EXECUTE AS LOGIN = 'TestViewServerState'; 
    --This obviously does not work. 
    select * from sys.dm_tran_current_transaction 
revert; 

--Grant view server state permission to the ViewServerStateLogin 
GRANT VIEW SERVER state TO ViewServerStateLogin; 

--Create a procedure to wrap the call to the system view 
CREATE PROCEDURE proc_TestViewServerState 

AS 
    SET NOCOUNT ON; 

    EXECUTE AS LOGIN='ViewServerStateLogin' 

     select * from sys.dm_tran_current_transaction 

    revert; 

RETURN(0); 

--Assign execute permission to the test accounts 
GRANT EXECUTE ON proc_TestViewServerState TO TestViewServerState 

--Grant impersonation rights to the test login 
GRANT IMPERSONATE ON LOGIN::ViewServerStateLogin TO TestViewServerState 

--Test with Procedure 
EXECUTE AS LOGIN = 'TestViewServerState'; 
    EXEC proc_TestViewServerState 
revert; 
+0

Jedyny problem z udzieleniem TestViewServerState pozwolenie podszywać jest to, że użytkownik może także zrobić: EXECUTE AS LOGIN = 'ViewServerStateLogin' select * from sys.dm_tran_database_transactions AS dtdt przywrócić Próbowałem za pomocą wykonać jak na procedura, ale ponownie podszywanie się jest uprawnieniem na poziomie serwera, a tym samym jest tracona podczas podszywania się pod użytkownika bazy danych. –

-1

zaszyfrować procedury przechowywanej, a nie dzielić PW do ViewServerStateLogin. Otrzymasz czarną skrzynkę o wystarczającej gęstości, aby zadowolić audytorów.

1

Z SQL Server 2008 firma Microsoft wprowadziła sys.dm_exec_requests, która ma na celu wycofanie sys.sysprocesses. Ten widok zwraca identyfikator transaction_id i można go wywołać bez przyznawania VIEW SERVER STATE. Podobnie jak sys.sysprocesses, zwraca szczegóły bieżącego procesu, jeśli VIEW SERVER STATE nie jest przyznany, i wszystkie procesy, jeśli jest.

Powiązane problemy