sql-serverdjango-mssql

MSSQL Permissions not making sense in MSSQL2008


I create the database in Management Studio. Added a SQL authenticated user to the list of users for the DB.

I set up (granted) the permissions like so:

use DjangoDB;
grant select,insert,update,alter,delete,references to django;

select
 a.*,
 b.name
from sys.database_permissions a
inner join sys.database_principals b
 on a.grantee_principal_id = b.principal_id
  and b.name = 'django'

The output of this command is:

class   class_desc  major_id    minor_id    grantee_principal_id    grantor_principal_id    type    permission_name state   state_desc  name
0   DATABASE    0   0   5   1   AL      ALTER   G   GRANT   django
0   DATABASE    0   0   5   1   CO      CONNECT G   GRANT   django
0   DATABASE    0   0   5   1   DL      DELETE  G   GRANT   django
0   DATABASE    0   0   5   1   IN      INSERT  G   GRANT   django
0   DATABASE    0   0   5   1   RF      REFERENCES  G   GRANT   django
0   DATABASE    0   0   5   1   SL      SELECT  G   GRANT   django
0   DATABASE    0   0   5   1   UP      UPDATE  G   GRANT   django

So the user appears to have the permissions (especially select which it will later claim is not a permission this user has)

Then I run python manage.py syncdb

Syncing...
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
...

and I (sometimes) get an error like:

File "E:\python\cloudbox\.cloudbox\lib\site-packages\sqlserver_ado\dbapi.py", line 99, in standardErrorHandler
raise errorclass(errorvalue)
DatabaseError: (-2147352567, 'Exception occurred.', (0, u'Microsoft OLE DB Provider for SQL Server', u"User 'django' does not have permission to run DBCC checkconstraints for database 'DjangoDB'.", None, 0, -2147217900), None)
Command:
DBCC CHECKCONSTRAINTS
Parameters:
[]

When I look up this error, it says:

Requires membership in the sysadmin fixed server role or the db_owner fixed database role.

I can find a whole list of roles to put this user into, but none of them are sysadmin. Where is this role hidden?

If I immediately rerun syncdb without changing anything, I get a different error though:

sqlserver_ado.dbapi.DatabaseError: (-2147352567, 'Exception occurred.', (0, u'Microsoft OLE DB Provider for SQL Server', u"The SELECT permission was denied on the object 'django_content_type', database 'DjangoDB', schema 'dbo'.", None, 0, -2147217911), None)
Command:
SELECT [django_content_type].[id], [django_content_type].[name], [django_content_type].[app_label], [django_content_type].[model] FROM [django_content_type] WHERE ([django_content_type].[model] = ?  AND [django_content_type].[app_label] = ? )
Parameters:
    [Name: p0, Dir.: Input, Type: adBSTR, Size: 10, Value: "permission", Precision: 0, NumericScale: 0, Name: p1, Dir.: Input, Type: adBSTR, Size: 4, Value: "auth", Precision: 0, NumericScale: 0]

Now it says the user doesn't have the SELECT privilege? But above it shows it DOES have the select privilege?

Is there some magic to granting the select privilege?

So, now the plot thickens. I make the sql user 'django' OWN the database. Now, everything will work, everything creates, no errors, south migration works.....

But I don't want my webserver user being the "owner" of the db. I want it to be able to do things like select,insert,update,alter,delete,references. But it seems like I can't just give it a limited set of permissions so it can fulfill that role. This seems a lot like running XP as administrator, something that does NOT make sense.

What am I doing wrong on permissions? Why does the webserver db user have to OWN this db?


Solution

  • Some Answers:

    1) sysadmin is a Server Role, and not a database role like db_owner. It is much more powerful than making your user the database owner, so you definitely do not want to give it out.

    2) For reasons that are something of a mystery, object-access permissions effectively must be granted to both the database (DjangoDB) and the schema (dbo). You already did the database, now you have to do the same for the schema. Here is what these commands might be in T-SQL:

    GRANT DELETE ON SCHEMA::[dbo] TO [django]
    GRANT EXECUTE ON SCHEMA::[dbo] TO [django]
    GRANT INSERT ON SCHEMA::[dbo] TO [django]
    GRANT REFERENCES ON SCHEMA::[dbo] TO [django]
    GRANT SELECT ON SCHEMA::[dbo] TO [django]
    GRANT UPDATE ON SCHEMA::[dbo] TO [django]
    GRANT VIEW DEFINITION ON SCHEMA::[dbo] TO [django]
    

    3) As for DBCC, it is a very powerful utility command, consequently, it requires powerful permissions. You may be able to grant your user the db_owner role instead of making them the owner of the database, but really that's not much better. Ideally, either your syncdb should only be executed by an admin instead of your app's users, or you should make a stored procedure to do the DBCC authorizing the proc with EXECUTE As OWNER, then authorize the user to that stored proc (already done if they are authorized to the schema, as above), and finally have syncdb changed to call that procedure instead of doing the DBCC directly.