[ http://issues.apache.org/jira/browse/DERBY-1539?page=all ]
Mamta A. Satoor updated DERBY-1539:
-----------------------------------
Attachment: DERBY1539V4diffDropTriggerOnRevokeRequiredPrivilege.txt
DERBY1539V4statDropTriggerOnRevokeRequiredPrivilege.txt
Recently, I had submitted a patch(DERBY1539V3diffDropTriggerOnRevoke.txt) for
triggers which will drop the triggers if a revoke privilege is issued on a
table/routine used by the trigger. That patch dropped the trigger even if the
trigger didn't depend on the permission type/column on the table. And the patch
dropped the trigger if the trigger depended on the routine.
eg for current behavior on revoke table level privilege
mamta1
create table t1(c11 int, c12 int);
grant select, update, trigger on t1 to mamta2
mamta2
create a trigger on mamta1.t1 with action as select * from some other
table
-- notice that the trigger object above depends only on the trigger
privilege on mamta1.t1
mamta1
revoke select on t1 from mamta2
-- this revoke ends up dropping the trigger even though trigger doesnot
rely on select permission
eg for current behavior on revoke column level privilege
mamta1
create table t1(c11 int, c12 int);
grant trigger on t1 to mamta2
create table t2(c21 int, c22 int);
grant select(c21, c22) on t2 to mamta2
mamta2
create a trigger on mamta1.t1 with action as select c21 from mamta1.t2
-- notice that the trigger object above depends only on the trigger
privilege on mamta1.t1, and
-- select privilege on mamta1.t2.c21
mamta1
revoke select(c22) on t2 from mamta2
-- this revoke ends up dropping the trigger even though trigger doesnot
rely on select
-- permission on column c22 of table t2
eg for current behavior on revoke column level privilege
mamta1
create function f1
grant execute on f1 to mamta2
mamta2
create table t1
create trigger on t1 with action that executes mamta1.f1
mamta1
revoke execute on f1 from mamta2 RESTRICT
-- this revoke ends up dropping the trigger even though revoke execute
is supposed to have
-- RESTRICT behavior, which means that
-- if there are dependent objects, then revoke execute should fail.
Couldn't implement this in earlier -- patch because dependents didn't know
what kind of revoke was issued. All they knew was revoke
-- issued against one of the objects that the dependent
relied on.
With the idea of working in incremental steps, I submitted the earlier patch as
the first step towards implementing revoke privilege. As the next step, I am
attaching another patch
(DERBY1539V4diffDropTriggerOnRevokeRequiredPrivilege.txt ), which will fix the
problem mentioned above in the egs. This patch currently only deals with
triggers. The next steps are to implement similar behavior for views and
constraints. The svn stat -q o/p for this patch is attached as
DERBY1539V4statDropTriggerOnRevokeRequiredPrivilege.txt. Note that I have added
a new file in this patch.
The reason for implementing REVOKE EXECUTE ... RESTRICT in this patch is that
prior to this patch, there was
no way of knowing what kind of revoke privilege is issued by the user and hence
even on revoke execute, I was dropping the dependent objects. With this patch,
now we know what kind of revoke privilege has been issued and when the
dependent gets revoke execute action, it can now throw an exception.
Grant revoke tests have run fine with this patch. I fired derbyall suite couple
hrs back on my Windows XP machine with Sun'd jdk1.4 and no errors so far.
More information on the current patch's implementation details is as follows.
1)BasicDependencyManager, TriggerDescriptor
SYSTABLEPERMS has one row per table, grantee, grantor. That row has various
fields to indicate what type of permissions(insert, trigger, update etc) are
available for that key. The row is also uniquely identified by a UUID.
Currently, when an object is created and it needs a particular pemission type
on a given table, grantee, grantor, the dependency manager(DM) only tracks the
dependency using UUID and it doesn't keep track of the exact permission type
required. Because of this, currently, any permission type that gets revoked on
table, grantee, grantor, it ends up dropping the dependent object, whether or
not the dependent object really needs that permission type.
eg(copying the eg from the beginning of this comment
mamta1
create table t1(c11 int, c12 int);
grant select, update, trigger on t1 to mamta2
mamta2
create a trigger on mamta1.t1 with action as select * from some other
table
-- notice that the trigger object above depends only on the trigger
privilege on mamta1.t1
mamta1
revoke select on t1 from mamta2
-- this revoke ends up dropping the trigger even though trigger doesnot
rely on select permission
The problem also exists for column level permissions. SYSCOLPERMS has one row
per table, grantee, grantor, a permission type and a bit map for columns on
which that permission is granted. The row is also uniquely identified by a
UUID. Now, an object might need a permission on only a subset of table columns
and if a revoke is done later on columns that are not used by the object, then
we should not drop the object. Currently, Derby tracks dependency on column
level permissions using just the UUID and does not keep track of exact column
subset required by the dependent object. Because of this, any column that gets
revoked for a given UUID, DM drops all the dependents on that UUID, even if the
dependent object does not care about the column being revoked.
eg(copying the eg from the beginning of this comment
mamta1
create table t1(c11 int, c12 int);
grant trigger on t1 to mamta2
create table t2(c21 int, c22 int);
grant select(c21, c22) on t2 to mamta2
mamta2
create a trigger on mamta1.t1 with action as select c21 from mamta1.t2
-- notice that the trigger object above depends only on the trigger
privilege on mamta1.t1, and select privilege on mamta1.t2.c21
mamta1
revoke select(c22) on t2 from mamta2
-- this revoke ends up dropping the trigger even though trigger doesnot
rely on select permission on column c22 of table t2
To fix both these problems, I have enhanced the DM such that when an object is
created which needs a particular permission type on a given permission table's
UUID, DM tracks the object's dependency on the permission type and the row in
SYSTABLEPERM identified by it's UUID. Similarly, when an object is created
which needs a particular permission type on a subset of table's column, the
object's dependnecy is tracked on the column subset and the row in SYSCOLPERMS
identified by it's UUID. Both of these solutions follow the existing model that
we currently have to track view's dependency on a subset of a table's columns.
I have implemented this kind of dependency for SYSTABLEPERMS by adding a new
class called DDPrivilegeTypeDependableFinder.java which saves the permission
type part of the dependency tracking for an object. For SYSCOLPERMS, I
implemented this by modifying existing class DDColumnDependableFinder.java.
This class is currently used for tracking view's dependency on subset of a
table's columns. Now, this class will also get used to track dependency on a
subset of columns for column level privileges.
The changes so far explained covers what happens when DM saves the
dependencies. Later on, when a provider wants to notify it's dependents about
an action, DM needs to use all the information that it collected while saving
the dependencies.
To be specific, later, when a permission is revoked, the DM needs to build a
list of dependents that rely on that permission. For each of the dependents, DM
needs to find the exact permission type or column subset required by that
dependent. That information then should be saved in the provider object and we
should put the provider+dependent object pair into the list of dependents. Once
the list building is finished, each of the dependent objects will get the
revoke invalidation action. The dependent object will check the provider object
to see if the permission type or column subset being revoked is one of the
things that it depends on. If yes, then it will drop itself. If not, then it
will ignore the invalidation action.
In order to implement this, amon other changes, I had to modify the code
recently checked in by Dan for improving DM performance. Dan made changes to DM
so that we do not recreate the provider object when building the dependents
list for the provider because we already have access to the provider object.
With my changes, while building the dependents list, if the provider is
TablePermsDescriptor or ColPermsDescriptor, then for every dependent, I save
into the provider object exactly what kind of permission type/column subset the
dependent depends on. And I put the dependent and this modified Provider pair
into the dependent list.
With this change in dependency system, subsequently, when a permission type is
revoked, the TablePermsDescriptor(Provider) will have the permission type being
revoked and the permission type required by the dependent object. When the
dependent object will receive the REVOKE action at table level, it will check
the TablePermsDescriptor to see if the permission type being revoked is one of
the permissions required by it, and if yes, then the dependent object will drop
itself. Similar thing will happen for ColPermsDescriptor when it is the
Provider of an invalidation action.
2)CoreDDFinderClassInfo, DDPrivilegeTypeDependableFinder,
DDColumnDependableFinder -
We need a special finder class for COLUMNS_PERMISSION_FINDER_V01_ID because
along with the row in the SYSCOLPERMS, we also need to track the exact column
list required for a given dependent object. This is same as what Derby
currently does for views, where a view might require only a subset of columns
in a table. And hence, when tracking the view dependency, we need to know not
just the SYSTABLES row but also the subset of columns required by view. Since
similar scheme is required for COLUMNS_PERMISSION_FINDER_V01_ID, I have used
existing DDColumnDependableFinder with some modifications to support additional
format id.
For similar reasons, We need special finder class for
TABLE_PERMISSION_FINDER_V01_ID because along with the row in the SYSTABLEPERMS,
we also need to track the exact privilege type required on a table for a given
dependent object. Unlike COLUMNS_PERMISSION_FINDER_V01_ID, where I could use
the existing class, DDColumnDependableFinder, I had to add a new dependable
finder class called DDPrivilegeTypeDependableFinder to track exact required
privilege type for a given row in SYSTABLEPERMS.
3)SPSDescriptor
For now, I am having SPSDescriptor ignore all the revoke invalidation actions.
May need some work here when working on query plan invalidation for revoke
privilege.
4)ViewDescriptor, ConstraintDescriptor -
For now, ignore all the revoke invalidation actions(except
REVOKE_EXECUTE_PRIVILEGE). Derby supports only RESTRICT form of revoke execute
and that means that if there are any dependent objects on execute permission on
routine, revoke execute on that routine should fail. That is why, I have
ViewDescriptor, ConstraintDescriptor catch REVOKE_EXECUTE_PRIVILEGE and throw
exception. As for all the other revoke invalidation actions, I Will get to them
in subsequent patch for ViewDescriptor, ConstraintDescriptor.
5)PermissionsDescriptor, RoutinePermsDescriptor
Have each of the PermissionsDescriptor send appropriate revoke invalidation
action. For instance, if SELECT privilege is being revoked, then send
REVOKE_SELECT_PRIVILEGE and so on and so forth. The dependent objects can take
desired action depending on the type of privilege being revoked. In addition,
error messages will be more specific since for instance, rather than
saying revoke privilege failed, they can say revoke execute privilege failed.
6)RoutinePermsDescriptor, TablePermsDescriptor and ColPermDescriptor
Changed getObjectName method from
return "Routine Privilege on " + routineName;
to
return routineName;
This change in the method makes the error method from revoke execute more
readable. With the original method, if the user tried to revoke the execute
permission from the routine when there were dependent objects relying on that
permission, the error message would be
ERROR X0Y25: Operation 'REVOKE EXECUTE PRIVILEGE' cannot be performed on object
'Routine Privilege on SELECTFROMSPECIFICSCHEMA' because TRIGGER 'TR31T31' is
dependent on that object.
With the change in the method, user would get following message
ERROR X0Y25: Operation 'REVOKE EXECUTE PRIVILEGE' cannot be performed on object
'SELECTFROMSPECIFICSCHEMA' because TRIGGER 'TR31T31' is dependent on that
object.
7)DependencyManager - describes all the invalidation actions for revoke.
8)TablePermsDescriptor and ColPermDescriptor have changes to record speicifc
privilege requirement of the dependent. These getter, setter and resetter
methods are all called by the dependency manager to track object's dependency
on specific privilege type and subset of table's columns.
9)StatementTablePermission, StatementColumnPermission -
During the compile phase of a view, trigger, constraint, we collect what
privileges are required by these objects. The information about the required
privileges, privilege types, column list needs to be saved by dependency
manager in the execute phase. The change to these classes are for collecting
required information for dependency manager so that it can save the specific
privilege type/column subset requirements in dependency system.
10)RoutinePrivilegeInfo, TablePrivilegeInfo
Call methods on the PermissionDescriptors so that they can send specific revoke
invalidation actions
9)New Tests
1)revoke execute should fail if there are dependent objects on it
2)revoke will drop a trigger only if trigger depends on that specific privilege
type.
3)create trigger which depends on the privileges on objects from different
schemas. Revoke on any one those objects should drop the trigger.
4)create trigger which depends on both table and column level privileges. The
trigger should get dropped only if the privileges gets revoked on specific
columns required by the trigger or if privileges gets revoked on specific
privilege type required by the trigger on a table. If not, then trigger should
stay untouched.
3)I couldn't add any testing for trigger action as update on tables owned by a
different schema. This is because Derby runs into a NPE. The Jira entry for
this specific problem is DERBY-1583. Once that bug is fixed, we should add
tests like
set connection mamta3
create trigger tr11t11 after insert on mamta1.t11TriggerRevokeTest for each
statement mode db2sql
update mamta2.t21TriggerRevokeTest set c212 = 99;
and then revoke update privileges on mamta2.t21TriggerRevokeTest from mamta3.
I will appreciate if someone can review, commit this patch for me.
> As per the functional spec attached to DERBY-1330, a trigger should be
> dropped when a privilege required by the trigger is revoked.
> -----------------------------------------------------------------------------------------------------------------------------------
>
> Key: DERBY-1539
> URL: http://issues.apache.org/jira/browse/DERBY-1539
> Project: Derby
> Issue Type: New Feature
> Components: SQL
> Affects Versions: 10.2.0.0
> Reporter: Mamta A. Satoor
> Assigned To: Mamta A. Satoor
> Fix For: 10.2.0.0
>
> Attachments: DERBY1539V1hashCodeEqualsDiff.txt,
> DERBY1539V1hashCodeEqualsStat.txt, DERBY1539V2diffDropTriggerOnRevoke.txt,
> DERBY1539V2statDropTriggerOnRevoke.txt,
> DERBY1539V3diffDropTriggerOnRevoke.txt,
> DERBY1539V3statDropTriggerOnRevoke.txt,
> DERBY1539V4diffDropTriggerOnRevoke.txt,
> DERBY1539V4diffDropTriggerOnRevokeRequiredPrivilege.txt,
> DERBY1539V4statDropTriggerOnRevokeRequiredPrivilege.txt
>
>
> A trigger tracks its privileges requirements using Derby's Dependency
> Manager. If any one of those required privileges are revoked, the trigger
> should be dropped automatically.
> I am just creating a new jira entry here so it is easier to track sub items
> of DERBY-1330. Will link this Jira entry to DERBY-1330.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira