Unless the users is mapped to the sysadmin fixed server role (where they will connect to the database as the user dbo) then they can be limited by security on the database. (i.e. A member of db_owner will receive a security check where dbo will not.)
A quick test to see if it is a permissions issue is to temporarily grant a user sysadmin role and then see if they can delete data.... if not then I'd start looking for constraints on tables.
If they can then run the following against the database (you may get more you may need to add DELETE to your where clause):
select * from sys.database_permissions
where state_desc = 'DENY'
If permissions are set it will give you something like:
class class_desc major_id minor_id grantee_principal_id grantor_principal_id type permission_name state state_desc
----- ------------------------------------------------------------ ----------- ----------- -------------------- -------------------- ---- -------------------------------------------------------------------------------------------------------------------------------- ----- ------------------------------------------------------------
0 DATABASE 0 0 10 1 DL DELETE D DENY
1 OBJECT_OR_COLUMN 1501607433 0 10 1 DL DELETE D DENY
(2 row(s) affected)
If deny delete is set at the DATABASE level then well then there is your problem. Adjust permissions so required users are not actually DENYed access.
db_ddladmin vs db_owner
From what I can tell from what I tested and read up on, for the most part your list looks accurate except db_ddladmin
DOES allow you to CREATE SCHEMA
. I did confirm that the other security permissions you listed were indeed denied.
Denied with DDLADMIN only:
[ALTER ANY USER]
[BACKUP DATABASE]
, [BACKUP LOG]
, [CHECKPOINT]
[ALTER ANY APPLICATION ROLE]
, [ALTER ANY ROLE]
[DROP DATABASE]
Noting that the. . .
db_datareader
will allow SELECT
access to all tables
db_datarwriter
will allow INSERT
, UPDATE
, and DELETE
access to all tables
db_executor
will allow EXECUTE
access to all executable objects
Additonally, having db_ddladmin role permissions may mean. . .
Note: Since you have so many different versions of SQL Server from 2005 - 2014, it may be best to have a small set of users test
this initially to see who screams to iron out any kinks, etc.
Objects they own with this role will not be owned by DBO so you may have to deal with ownership chaning issues if there's ever a problem with something at this level. I'm not 100% certain that this would be a problem but it's worth mentioning just in case.
Source: Ownership Chains
With this role (may vary depending on the version of SQL Server) they may be able to add SQL security principles defined in the current DB to objects they own still, just not all objects (ones they do not own) nor add a new server-level defined principal to the DB level.
Additionally, not having DBO role permissions may mean. . .
Note: Since you have so many different versions of SQL Server from 2005 - 2014, it may be best to have a small set of users test
this initially to see who screams to iron out any kinks, etc.
Other Considerations
Since you state that this is being reviewed on a case-by-case basis
One of the permissions currently being limited is db_owner permissions.
This permission is being reviewed on a case-by-case basis, but a common change is to replace the db_owner permissions with the following:
- db_datareader
- db_datawriter
- db_ddladmin
- db_executor
Have you considered creating additional custom roles for more "all object" DB-level access that each person needs rather than granting them the db_ddladmin
role as that will probably give them more than they actually need to DB level objects as well.
I usually give what's needed exactly and nothing more for them to do their job and if there's a "usual" or "standard" need for DB level object access to all objects in a DB, I create a custom DB role sort of like the the db_executor
but see my below example. This way you can grant the people what they really need to ALL DB object in a particular DB if you're not getting object level explicit in your DBs for their security.
----Custom Database Roles
/* CREATE A NEW ROLE -- Execute to all stored procs including newly created ones*/
-- Database specific
CREATE ROLE db_All_StoredProc_Execute
GRANT EXECUTE TO db_All_StoredProc_Execute
/* CREATE A NEW ROLE -- Alter to all stored procs including newly created ones*/
-- Database specific
CREATE ROLE db_All_StoredProc_Alter
GRANT ALTER ANY SCHEMA TO db_All_StoredProc_Alter
/* CREATE A NEW ROLE -- View Definition to all stored procs including newly created ones*/
-- Database specific
CREATE ROLE db_All_StoredProc_View
GRANT VIEW DEFINITION TO db_All_StoredProc_View
/* CREATE A NEW ROLE - Any schema alter and create procedure permissions */
-- Database specific
CREATE ROLE db_All_CreateProc_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateProc_AlterSchema
GRANT CREATE PROCEDURE TO db_All_CreateProc_AlterSchema
GO
/* CREATE A NEW ROLE - Any schema alter and create table permissions */
-- Database specific
CREATE ROLE db_All_CreateTable_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateTable_AlterSchema
GRANT CREATE TABLE TO db_All_CreateTable_AlterSchema
/* CREATE A NEW ROLE - Any schema alter and create function permissions */
-- Database specific
CREATE ROLE db_All_CreateFunction_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateFunction_AlterSchema
GRANT CREATE FUNCTION TO db_All_CreateFunction_AlterSchema
/* CREATE A NEW ROLE - Any schema alter and create aggregate permissions */
-- Database specific
CREATE ROLE db_All_CreateAggregate_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateAggregate_AlterSchema
GRANT CREATE AGGREGATE TO db_All_CreateAggregate_AlterSchema
/* CREATE A NEW ROLE - Any schema alter and create view permissions */
-- Database specific
CREATE ROLE db_All_CreateView_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateView_AlterSchema
GRANT CREATE VIEW TO db_All_CreateView_AlterSchema
/* CREATE A NEW ROLE - Any schema alter and create schema permissions */
-- Database specific
CREATE ROLE db_All_CreateSchema_AlterSchema
GRANT ALTER ANY SCHEMA TO db_All_CreateSchema_AlterSchema
GRANT CREATE SCHEMA TO db_All_CreateSchema_AlterSchema
I also wanted to share a db_DDLAdmin_Restriction role you may want to consider to consider creating otherwise with explicit DENY
to restrict what db_ddladmin
give access to so you could at least create this on the DBs where you grant them this role and set the explicit DENY
for the actual object types, etc. you don't want them to have access to.
For example, if you know they will definitely be creating stored procedures and functions, you can exclude DENY CREATE FUNCTION
, DENY CREATE PROCEDURE
, DENY ALTER ANY SCHEMA
.
---Create ddladmin restriction custom DB role
DENY ALTER ANY ASSEMBLY TO db_DDLAdmin_Restriction
DENY ALTER ANY ASYMMETRIC KEY TO db_DDLAdmin_Restriction
DENY ALTER ANY CERTIFICATE TO db_DDLAdmin_Restriction
DENY ALTER ANY CONTRACT TO db_DDLAdmin_Restriction
DENY ALTER ANY DATABASE DDL TRIGGER TO db_DDLAdmin_Restriction
DENY ALTER ANY DATABASE EVENT NOTIFICATION TO db_DDLAdmin_Restriction
DENY ALTER ANY DATASPACE TO db_DDLAdmin_Restriction
DENY ALTER ANY FULLTEXT CATALOG TO db_DDLAdmin_Restriction
DENY ALTER ANY MESSAGE TYPE TO db_DDLAdmin_Restriction
DENY ALTER ANY REMOTE SERVICE BINDING TO db_DDLAdmin_Restriction
DENY ALTER ANY ROUTE TO db_DDLAdmin_Restriction
DENY ALTER ANY SCHEMA TO db_DDLAdmin_Restriction
DENY ALTER ANY SERVICE TO db_DDLAdmin_Restriction
DENY ALTER ANY SYMMETRIC KEY TO db_DDLAdmin_Restriction
DENY CHECKPOINT TO db_DDLAdmin_Restriction
DENY CREATE AGGREGATE TO db_DDLAdmin_Restriction
DENY CREATE DEFAULT TO db_DDLAdmin_Restriction
DENY CREATE FUNCTION TO db_DDLAdmin_Restriction
DENY CREATE PROCEDURE TO db_DDLAdmin_Restriction
DENY CREATE QUEUE TO db_DDLAdmin_Restriction
DENY CREATE RULE TO db_DDLAdmin_Restriction
DENY CREATE SYNONYM TO db_DDLAdmin_Restriction
DENY CREATE TABLE TO db_DDLAdmin_Restriction
DENY CREATE TYPE TO db_DDLAdmin_Restriction
DENY CREATE VIEW TO db_DDLAdmin_Restriction
DENY CREATE XML SCHEMA COLLECTION TO db_DDLAdmin_Restriction
DENY REFERENCES TO db_DDLAdmin_Restriction
GO
Best Answer
As per the Docs article, db_owner can perform functions that no other role or combination of roles provides, including but not limited to:
There is a diagram on the linked article that shows the fixed-role permissions for each role. Any permission not listed in that diagram is granted to the db_owner role only by default.