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