Δεν είναι λίγοι αυτοί που πιστεύουν ότι το να είναι κάποιος database owner είναι το ίδιο με το να ανήκει στο database role db_owner. Η απάντηση είναι ότι δεν είναι, αν και σε πρώτη ανάγνωση έτσι φαίνεται.
Η ουσιαστική διαφορά είναι ότι ο πρώτος είναι ο πραγματικός owner και μπορεί να κάνει τα πάντα στην database. Εξάλλου μην ξεχνάμε ότι όποιος είναι sysadmin στο SQL Server instance στην κάθε database "μπαίνει" σαν dbo, που είναι ο database owner.
Όποιον έχουμε βάλει στο database role db_owner απλά του έχουμε εκχωρήσει το δικαίωμα να κάνει τα πάντα χωρίς όμως αυτό να σημαίνει ότι από αυτά τα πάντα δεν μπορούμε να του κόψουμε κάποια.
Για του λόγου το αληθές δοκιμάστε το παρακάτω script.
Στο step 1 δημιουργώ δύο SQL Logins χωρίς κανένα δικαίωμα σε επίπεδο instance και μια demo database με τα defaults.
Στο step 2 αναθέτω στον user1 να είναι database owner στην demo database
Στο step 3 δίνω το δικαίωμα να μπορεί να χρησιμοποιεί την demo database στο user2 και μάλιστα με δικαιώματα dbo καθώς το κάνω μέλος στο db_owner database role.
Στο step 4 είναι η πρώτη αποκάλυψη της αλήθειας καθώς φαίνεται ξεκάθαρα ότι ο user1 είναι dbo δηλαδή ενώ ο user2 είναι απλά ο user2.
Στο step 5 δημιουργώ έναν πίνακα και βάζω δύο records
Όπως είναι φυσικό (step 6) και οι δύο χρήστες μπορούν να κάνουν τα ίδια πχ SELECT.
Αν προσπαθήσω στο user1 (step 7) να αφαιρέσω το δικαίωμα του SELECT δεν με αφήνει να το κάνω διότι είναι database owner και φυσικά συνεχίζει να διαβάζει κανονικά τα δεδομένα και όχι μόνο.
Αν όμως στον user2 (step 8) δοκιμάσω να αφαιρέσω το δικαίωμα του SELECT αυτό γίνεται και φυσικά ο user2 δεν μπορεί να διαβάσει δεδομένα παρόλο που ανήκει στο db_owner database role!!!.
To τελικό συμπέρασμα είναι ότι πρέπει να είμαστε προσεκτικοί στο ποιον χρήστη βάζουμε να είναι database owner καθώς σε ένα περιβάλλον που ζητάει μόνο τα απαραίτητα δικαιώματα στους χρήστες αυτό είναι μαχαιριά στην πλάτη.
Ακόμα και το εύκολο βήμα να βάζουμε το SA σαν dbo δεν είναι καλό αλλά από άποψη συντήρησης είναι και αυτό διότι είναι sysadmin.
Μια καλή εναλλακτική λύση για αυτό είναι να δημιουργηθεί ένας απλός χρήστης στο SQL Server στον οποίο να αφαιρέσουμε το δικαίωμα CONNECT και αυτόν να βάζουμε σαν dbo σε κάθε database. Μπορεί να μας δυσκολέψει λίγο σε πιθανά restores σε άλλον server αλλά μπροστά στην ασφάλεια αξίζει το να σπαταλήσει κάποιος 5 λεπτά περισσότερο σε μια τέτοια περίπτωση.
Μπορεί να φανεί υπερβολικό αυτό σε αρκετούς όμως όταν στα χέρια σου είναι δεδομένα που κοστίζουν πολλά εκατομμύρια καλό είναι να είσαι προσεκτικός σε κάθε λεπτομέρεια ακόμα και αν σου κολλήσουν την ρετσινιά του παρανοϊκού. Καλύτερα αυτό παρά κάπου αλλού.
-- step 1
USE [master]
GO
CREATE LOGIN [user1] WITH PASSWORD=N'P@ssw0rd', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO
CREATE LOGIN [user2] WITH PASSWORD=N'P@ssw0rd', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO
CREATE DATABASE demo
GO
-- step 2
USE demo
go
EXEC dbo.sp_changedbowner @loginame = N'user1', @map = false
GO
-- step 3
CREATE USER [user2] FOR LOGIN [user2]
GO
ALTER ROLE [db_owner] ADD MEMBER [user2]
GO
-- step 4
EXECUTE AS LOGIN='user1';
SELECT USER_NAME()
REVERT;
GO
EXECUTE AS LOGIN='user2';
SELECT USER_NAME()
REVERT;
GO
-- step 5
CREATE TABLE T(COL1 INT,COL2 NVARCHAR(100));
GO
INSERT INTO T VALUES (1,'ANTONIOS CHATZIPAVLIS'),(2,'SQLSCHOOL.GR')
GO
SELECT * FROM T;
GO
-- step 6
EXECUTE AS LOGIN='user1';
SELECT * FROM T;
REVERT;
GO
EXECUTE AS LOGIN='user2';
SELECT * FROM T;
REVERT;
GO
-- step 7
DENY SELECT ON T TO USER1;
GO
EXECUTE AS LOGIN='user1';
SELECT * FROM T;
REVERT;
GO
-- step 8
DENY SELECT ON T TO USER2;
GO
EXECUTE AS LOGIN='user2';
SELECT * FROM T;
REVERT;
GO