A detach és az NTFS jogosultság

Azért szeretek fórumot olvasni, mert mindig tanulok. Vagy vmi hasznosat, vagy azt, hogy nem ezt a fórumot kellene olvasni. Ma délután találkoztam a magyar Technet SQL fórumon egy érdekes kérdéssel:
Miért nem működik a következő script, miért dob a második lépés access denied-ot, mikor explorerből, Total Commanderből megy az átnevezés? Sőt, ha elmásolják és vissza, akkor utána már lehet xp_cmshellel is átnevezni.

exec sp_detach_db 'database'
exec xp_cmdshell 'rename d:\mssql\data\database.mdf database.old.mdf'

Azaz a detach sikerül, utána a cmdshell meg access denied-ot mond. Ez roppantul felkeltette a kíváncsiságomat, és pont volt egy kis időm is, úgyhogy ránéztem a dologra. Kipróbáltam a W2K3-SQL2K8 express asztali gépemen, és pont ezt tapasztaltam. Mivel az express tele van meglepetésekkel, megnéztem a 2K3-SQL2K5 virtuális gépemen is, és dettó. Ezután megnéztem a jogosultságokat az adatbázis fájlokon, ha már access denied a hiba, és azt láttam, hogy az attacsolt fájlokhoz a SQL service-t futtató csoportnak meg az Administrators csoportnak full control joga van, a detacsolt fájlokon meg csak az én saját, nem-adminisztrátor useremnek van full controlja. Ha attacsoltam, visszakerült a SQL service joga is. Szóval kiderült, hogy a DBCC DETACHDB, amit a sp_detach_database hív a lelke mélyén (meg lehet nézni a master adatbázisban a definícióját), kicsit trükkösen kezeli a jogokat. És mivel elvette a SQL userem jogát, az xp_cmdshell elég csúnyán megbukott, mert ugye alapból a SQL user nevében próbálkozik futtatni a parancsokat. Ha bármikor valakinek kételye volna, nagyon egyszerű kideríteni, hogy kinek a nevében futnak a parancsok:

exec xp_cmdshell 'echo %username%'

Ez pont ki fogja írni. Vissza is kaptam a SQL service accountom nevét.
Munkám jellegéből adódóan nekiálltam megoldást keresni – és találtam is, egy elég egyszerűt: mivel a DBCC a parancsot kiadó felhasználónak ad kizárólagos jogot a fájlra, kíváncsi voltam, hogy mi történik, ha nincs megfelelő Windows account, azaz egy SQL loginnal adom ki a parancsot. Szerencsém volt, annak idején Paul Randal vagy az elődei nem vették a fáradságot, hogy megkeressék, ki az OS user a háttérben, hanem ilyen esetben egyszerűen nem nyúl a jogosultsághoz a DBCC. De mit lehet tenni, hogy szegény embernek ne kelljen egy külön SQL accounttal belogolnia ahhoz, hogy ezt le tudja futtatni? Erre való az EXECUTE AS parancs, ami – mint neve is sugallja – az SQL-es runas/sudo (kinek melyik). Végül a következőképpen néz ki a script:

EXECUTE AS LOGIN='tivadar'
exec sp_detach_db 'database'
REVERT
exec xp_cmdshell 'rename d:\mssql\data\database.mdf database.old.mdf'

Ahol tivadar egy sa vagy dbo jogosultságú SQL user. Az xp_cmdshell működése miatt a REVERT akár a végén is lehet, mivel akár tivadar, akár a ténylegesen belogolt sa jogú felhasználó adja ki a parancsot, az úgyis a SQL service account nevében fog lefutni (hacsak nem piszkáltuk meg a rendszert).
Ennek fényében már világos az is, hogy az elmásolt-visszamásolt fájlra miért futott le az átnevezés hibátlanul: a visszamásolásnál a könyvtár jogosultságai visszaíródtak szépen a fájlhoz.
Az SQL Server eme működési jellegzetességéről el lehet vitatkozni, hogy bug vagy feature – szerintem bug, mert hozzá kellene adnia a detacsoló júzernek a full controlt, nem pedig felülírni az egészet. Majd meglátjuk, hogy mit szól ehhez a Microsoft – betoltam nekik egy fix requestet :) Mindenesetre roppant rendes vagyok, és elvégtam előlük a menekülés útját: megírtam, hogy ha szerintük ez így jó, vagy nem akarnak a DBCC DETACHDB-be belehekkelni a két szép szememért, no problem – de akkor írják bele a BOL-ba, hogy van egy ilyen apró mellékhatás… Connect a király :)

Update: a connecten megírták, hogy ez benne van a BOL-ban. Csak nem ott, ahol számítottam rá. már megint beégtem :)

Leave a comment