Hogyan delegáljunk jogosultságokat

Alapvetően két esetben érdekes a jogosultság delegálása:

  • magasabb szintű jogosultság ellenőrzött használata esetén és
  • fejlesztői jogosultság kiterjesztése.

Míg az előbbire az adatbázis biztonságának növelése, jogszabályi követelmények, egyéb szabályozások (pl. PCI, SOX, stb.) miatt, addig az utóbbi eset a fejlesztői munka elősegítése lehet a cél. Az SQL Server 2005 verziótól működik az un. security trimming, ami azt jelenti, hogy minden felhasználó annyit lát a rendszerből, amennyihez jogosultsága van a DMV, DMF és a system catalog view lekérdezések során. Például egy “egyszerű” felhasználó nem láthatja az összes session-t a sys.dm_exec_sessions DMV-ben, csak a sajátját. Itt jön be a jogosultság delegálása: ha azt szeretném, hogy minden session-t lásson a felhasználó – maradva a fenti példánál – akkor adhatok neki VIEW SERVER STATE jogot is. Igen ám, de ekkor hozzáférhet olyan információkhoz/DMV-khez is, amikhez nem akartam jogot adni neki. Az alábbi példa során csak a sys.dm_os_ring_buffers DMV-hez akarok jogosultságot adni, egy “egyszerű” felhasználónak:

Első lépésben létrehozok egy teszt adatbázist:

1USE [master];
2GO
3CREATE DATABASE [DelegateDb]
4GO

A delegáláshoz szükségem lesz egy tanúsítványra, mely a hitelesítő szerepet fogja betölteni:

1USE [master];
2GO
3CREATE CERTIFICATE [DelegateCert] ENCRYPTION BY PASSWORD = 'password'
4WITH SUBJECT = 'Delegate cert',
5     EXPIRY_DATE = '20201231';
6GO

Következő lépésben két felhasználót hozok létre:

  • HighPrivilegedLogin: ez lesz, akinek megadom a VIEW SERVER STATE jogosultságot, de közvetlenül nem csatlakozhat az SQL Server-hez – visszavonom a - CONNECT jogát – csak az előbbi jog delegálásához fogom használni. Ez a login a DelegateCert tanúsítványból lesz létrehozva.
  • LowPrivilegedUser: ez lesz, akinek csak EXEC joga lesz a DelegateDb adatbázisban
 1USE [master];
 2GO
 3CREATE LOGIN [HighPrivilegedLogin] FROM CERTIFICATE [DelegateCert];
 4GO
 5REVOKE CONNECT SQL FROM [HighPrivilegedLogin];
 6GO
 7GRANT VIEW SERVER STATE TO [HighPrivilegedLogin];
 8GO
 9CREATE LOGIN [LowPrivilegedUser] WITH PASSWORD = 'password';
10GO

Eljutottam odáig, hogy van egy teszt adatbázisom és két loginom, illetve egy tanúsítványom. Most elkezdem felhasználni ezeket: a DelegateCert tanúsítványra a DelegateDb adatbázisban is szükségem van, ezzel fogom “aláírni” az egyik eljárásomat, amely segítségével a LowPrivilegedUser hozzá fog férni a DMV tartalmához. Ehhez elmentem a tanúsítványt a privát kulcsával együtt:

1USE [master];
2GO
3BACKUP CERTIFICATE [DelegateCert] TO FILE = 'c:\temp\sql.cer'
4      WITH PRIVATE KEY ( DECRYPTION BY PASSWORD = 'password' ,
5      FILE = 'c:\temp\sql.pvk' ,
6      ENCRYPTION BY PASSWORD = 'password' );
7  GO

Ezek után visszaállítom a DelegateDb-ben a DelegateCert tanúsítványt. Azonban ehhez előbb létre kell hoznom az adatbázis MASTER KEY-t.

 1USE [DelegateDb];
 2GO
 3CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'password';
 4GO
 5CREATE CERTIFICATE [DelegateCert] FROM FILE = 'c:\temp\sql.cer'
 6WITH PRIVATE KEY
 7(FILE = 'c:\temp\sql.pvk',
 8 DECRYPTION BY PASSWORD= 'password',
 9 ENCRYPTION BY PASSWORD='password')
10GO

Most létrehozok egy eljárást, ami visszaadja a fenti DMV sorait, illetve a “hívó” és a “futtató” felhasználók neveit.

1USE [DelegateDb];
2GO
3CREATE PROCEDURE [DelegateElevatedThingsToDo]
4AS
5SELECT ORIGINAL_LOGIN() AS [Caller], SUSER_NAME() AS [Executor];
6SELECT * FROM sys.dm_os_ring_buffers;
7GO

Az adatbázisban létrehozom a LowPrivilegedUser felhazsnálót és adok EXEC jogot neki.

1USE [DelegateDb];
2GO
3CREATE USER [LowPrivilegedUser] FOR LOGIN [LowPrivilegedUser];
4GO
5GRANT EXEC ON SCHEMA::dbo TO [LowPrivilegedUser];
6GO

Ha most megpróbálom ezzel a felhasználóval futtatni a fenti eljárást, hibát fogok kapni:

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

Ez a hiba a DMV lekérdezésre vonatkozik. Ahhoz, hogy legyen jogosultsága, “aláírom” az eljárást a DelegateCert tanúsítvánnyal.

1ADD SIGNATURE TO [DelegateElevatedThingsToDo]
2BY CERTIFICATE [DelegateCert] WITH PASSWORD = 'password'
3GO

Ezek után már működni fog, el tudja érni a LowPrivilegedUser a DMV tartalmát:

1EXECUTE AS LOGIN = 'LowPrivilegedUser';
2GO
3EXEC [DelegateElevatedThingsToDo];
4GO
5REVERT

Hurrá, nem kell sysadmin jog, sem semmilyen más elevált jog, így a DBA is nyugodt lehet, hogy a fejlesztő nem “rongálja” az éles szervert :-).

Az adatbázist és a fentieket, az alábbi kód segítségével lehet kitörölni, ha nincs már rá szükség:

 1USE [master];
 2GO
 3ALTER DATABASE [DelegateDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
 4GO
 5DROP DATABASE [DelegateDb];
 6GO
 7DROP LOGIN [HighPrivilegedLogin]
 8GO
 9DROP LOGIN [LowPrivilegedUser]
10GO
11DROP CERTIFICATE [DelegateCert];
12GO