GRANT … AS: Using GRANT … WITH GRANT OPTION for Roles

2014-01-26 - General, Security

Introduction

Yesterday we discussed how to enable users and logins to pass on their permissions. That works great in most cases. However there is a small complication:

Does GRANT ... WITH GRANT OPTION not work on roles?

We know that server roles and database roles can significantly simplify the management of permissions. We also just discovered the ability to delegate permission management. Armed with that information let's try out to combine these two options. First we need to create two logins and two users; we also need a database role to put one of the users in:

[sql] CREATE LOGIN TestLogin1 WITH PASSWORD='********', CHECK_POLICY = OFF;
CREATE LOGIN TestLogin2 WITH PASSWORD='********', CHECK_POLICY = OFF;

CREATE USER TestUser1 FOR LOGIN TestLogin1;
CREATE USER TestUser2 FOR LOGIN TestLogin2;

CREATE ROLE TestRole1;
ALTER ROLE TestRole1 ADD MEMBER TestUser1;
[/sql]

Now we can use the GRANT ... WITH GRANT OPTION statement to give all members in TestRole1 the ability to pass on the permission:

[sql] GRANT SELECT ON OBJECT::dbo.tst TO TestRole1 WITH GRANT OPTION;
[/sql]

That executes without problems:

using WITH GRANT OPTION on a database role.

So we should expect that TestUser1 will now be able to use the GRANT statement to pass the permission on:

[sql] GRANT SELECT ON OBJECT::dbo.tst TO TestUser2;
[/sql]

However, when we actually try it out, we get a different result:

GRANT fails for role member.

Unsurprisingly, the permission was also not granted:

causing a SELECT by TestUser2 to fail.

Let's review what we did. We know that any permission granted to a role automatically extends to all its members. We also know that GRANT ... WITH GRANT OPTION allows the grantee to pass that permission on. In our case the grantee of the WITH GRANT OPTION is the TestRole1 role, so we expect that the ability to pass on this permission applies to all role members. Finally, we know that TestUser1 is a member of that role. So, we did everything right. What went wrong?

GRANT ... AS

It turns out that the permission to delegation does not automatically transfer from a role to its members like other permission do. However, as a member of a role you can request it from that role, on a case by case basis. The syntax looks like this:

[sql] GRANT SELECT ON OBJECT::dbo.tst TO TestUser2 AS TestRole1;
[/sql]

It uses the additional AS clause at the end to specify the role that is supplying the right to use the GRANT statement. If the executing principal is a member of that role, the statement does not fail when executed:

The GRANT...AS statement in action.

Instead it successfully passes the SELECT permission on to TestUser2 as desired:

Successfully passing on the SELECT permission.

Summary

The ability to grant a specific permission does not automatically get passed down to members of a role. Instead it has to be explicitly requested by the role member executing the GRANT. For that the GRANT...AS statement can be used, specifying the role that has the delegation permission.

Categories: General, Security
Tags: , , , , , , , ,

Leave a Reply