[ http://issues.apache.org/jira/browse/DERBY-1330?page=all ]

Mamta A. Satoor updated DERBY-1330:
-----------------------------------

    Attachment: Derby1330PrivilegeCollectionV2diff.txt
                Derby1330PrivilegeCollectionV2stat.txt

I am attaching an updated patch(Derby1330ViewPrivilegeCollectionV2diff.txt) 
which includes privilege collection for views, constraints and triggers. The 
earlier patch (Derby1330ViewPrivilegeCollectionV1diff.txt) had privilege 
collection changes for views only. The new patch is a superset of the earlier 
patch and hence, if anyone has spent time reviewing the earlier patch, that 
time spent won't be a waste. I have
also changed comments around the method and field definition into java doc 
comments. Additionally, I have changed the method name 
isExecutingWithInvokerPrivileges to isPrivilegeCollectionRequired. Both these 
changes are based on Dan's feedback on the first review package.

During view, trigger and constraint creation, in SQL Authorization mode, we 
need to collect all the privileges that are required by those objects. Using 
the Dependency Manager, these dependencies need to be saved in SYSDEPENDS 
table. If any of those privileges are later revoked by a revoke statement, then 
all the dependent objects(views, triggers and constraints) should get dropped. 

The patch has 4 majors components to it. 
1)If the query for create view/create trigger is accessing view/s, then Derby 
engine flattens all those view/s. Once the view flattening is finished, Derby 
engine goes through all the columns for the flattened parent sql and it starts 
building the privilege requirement for those columns. But since views are 
always accessed with definer's privileges (which means that as long as a user 
has privilege to access 
a view, the user can select from the view. This works even if the user does not 
have direct privileges to the objects accessed by the view.), When collecting 
privilege requirement for a given sql, Derby engine should not collect 
privilege requirements for objects accessed by views. In order to implement 
this behavior, I have added a flag to QueryTreeNode which will be set to false 
if the object is going to be accessed with definer's privileges. During view 
flattening, the objects accessed by view will be marked with definer 
privileges. Later, when the Derby enging goes through all the columns to 
collect the privilege requirements, it will check if a column is marked with 
definer's privilege and if so, then do not look for privilege requirement for 
that column. 
2)Once the privileges have been collected for the create view/create 
trigger/create constraint in the bind phase, they need to be recorded in 
SYSDEPENDS table during the execution phase of the create view/create 
trigger/create constraint sql. SYSDEPENDS will add one row for every privilege 
requirement for the view/trigger/constraint. The DEPENDENTID will be 
view/trigger/constraint descriptor and PROVIDERID has to be a unique id to 
identify permission descriptor's uniquely. In order to do this, 
PermissionsDescriptor needs to implement interface Provider and it needs to 
have a UUID associated with it. This required addition of a UUID column in 
SYSTABLEPERMS, SYSCOLPERMS and 
SYSROUTINEPERMS. This UUID is required by the DependencyManager to uniquely 
identify a row for a given PROVIDERID. 
3)Privilege collection during trigger creation is handled in a similar fashion 
as item 1. ie no privilege collection is required for objects that are accessed 
by objects running with definer privileges. For all the other objects, 
appropriate privilege is required by the trigger creator and those privilege 
requirements will be saved in SYSDEPENDS using the dependency manager. In 
addition, the trigger
creator will need TRIGGER privilege on the table on which the trigger is 
getting defined. The dependency of the trigger on this TRIGGER privilege will 
be saved in SYSDEPENDS too.
4)Among the different kinds of constraints, foreign key constraint is the only 
constraint in Derby that can access other objects in the database. And, 
anytime, an object accesses another object, appropriate privileges need to be 
in place. For foreign key constraints, we need to record these privilege 
dependencies in the system. This is so that when one of those privileges is 
revoked, the constraint
should get dropped. The peculiar thing about constraint creation compared to 
views and triggers is one can define multiple foreign key constraints for a 
given table within a single sql statement. Derby collects all the privileges 
required for such a sql statement but foreign key constraint does not 
necessarily depend on all those privileges. eg
create table t31ConstraintTest (c311 int references mamta1.t11ConstraintTest, 
c312 int references mamta2.t21ConstraintTest);
For the above sql, Derby will collect REFERENCES privilege requirements for 
mamta1.t11ConstraintTest and mamta2.t21ConstraintTest. But the foreign key 
constraint on c311 depends only on REFERENCES privilege requirement for 
mamta1.t11ConstraintTest and foreign key constraint on c132 depenly only on 
REFERENCES privilege requirements for mamta2.t21ConstraintTest. I have made 
changes to CreateConstraintConstantAction.executeConstantAction such that only 
the necessary privileges get recorded for each foreign key constraint in 
SYSDEPENDS table. 

Following classes are impacted by this change. Compared to the first patch, 
there are 2 additional classes that got changed in Derby engine, when I added 
privilege collection for triggers and constraints. In addition, I added more 
tests to grantRevokeDDL.sql and to ProcedureTest.java The 2 additional classes 
that changed in Derby enginge compared to first patch are
java/engine/org/apache/derby/impl/sql/execute/CreateTriggerConstantAction.java
java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java

I have put some comment for all the classes that got changed/added below in 
this patch
java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java
     Has method to mark this node to run with definer privileges (this could 
happen if the node is being accessed by an object(view/trigger/constraint) 
running with definer's privileges. This method also marks the result column 
list as running with definer privileges. 

java/engine/org/apache/derby/impl/sql/compile/DDLStatementNode.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java 
     Has method to mark this node to run with definer privileges (this could 
happen if the node is being accessed by an object (view/trigger/constraint) 
running with definer's privileges. This method also marks the subquery 
underneath it as running with definer privileges. 

java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
     Has method to mark this node to run with definer privileges (this could 
happen if the node is being accessed by an object (view/trigger/constraint) 
running with definer's privileges. This method also marks it's fromTableList as 
running with definer privileges.

java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
     This is the super class that keeps the flag which determines if the object 
is getting accessed with invoker's or definer's privileges. It has methods to 
setter and getter methods on the flag. 

java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges. In addition, it has method to mark 
this node to run with definer privileges (this could happen if the node is 
being accessed by an object(view/trigger/constraint) running with definer's 
privileges. This method also marks the expression underneath it as running with 
definer privileges. 

java/engine/org/apache/derby/impl/sql/compile/PrivilegeNode.java
    Grant was activated only on base tables in this class. I changed the code 
to allow grant on views along with the base tables.

java/engine/org/apache/derby/impl/sql/compile/CreateTriggerNode.java 
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/DeleteNode.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges. 

java/engine/org/apache/derby/impl/sql/compile/CreateSchemaNode.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java 
     Has method to mark this node to run with definer privileges (this could 
happen if the node is being accessed by an object (view/trigger/constraint) 
running with definer's privileges. This method also marks it's javaNode as 
running with definer privileges. 

java/engine/org/apache/derby/impl/sql/compile/FromList.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/FKConstraintDefinitionNode.java 
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
     If we are dealing with a view, we need to mark the query underneath it to 
run with definer privileges. This will make sure that we do not collect 
privilege requirements for that query. 

java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java 
     Has method to mark this node to run with definer privileges (this could 
happen if the node is being accessed by an object (view/trigger/constraint) 
running with definer's privileges. This method also marks all the result 
columns in it as running with definer privileges. 

java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
     Need to add a privilege requirement for the object access, only if the 
object is running with invoker's privileges.

java/engine/org/apache/derby/impl/sql/execute/CreateViewConstantAction.java 
     Add rows in SYSDEPENDS to keep track of view's dependency on various 
privileges. If any of those privileges are later revoked, the view will be 
dropped automatically. If the view is getting created by the dba, then no 
privilege dependency is created because dba has access to all the objects in 
the database. If view is accessing an object that is owned by the view creator, 
then no need to put any privilege dependencies on such objects. If object 
accessed is not user owned, then check if there exists a privilege on that 
object  for this user. If yes, then save that privilege in SYSDEPENDS table as 
one of the privileges required by the view. If user does not have the privilege 
on the object, then there has to exist a PUBLIC level privilege  on that 
object. If that was not true, authorization checking for all the objects 
accessed by the views at the beginning of the execution phase would have 
failed. Column level privileges have a distinct behavior. For a given table, a 
user can have access to some of the columns via the privileges granted to the 
user explicitly. For the same table, the user may have access to some of the 
volumns via the privileged granted to the PUBLIC. an eg 
 user1
 create table t11(c11 int, c12 int);
 grant select(c11) on t1 to user2;
 grant select(c12) on t1 to PUBLIC;
 user2
 create view v1 as select c11 from user1.t11 where c12=2;
 For the view above, there are 2 column level privilege depencies, one for 
column c11 which exists directly for user2 and one for column c12 which exists 
at PUBLIC level. 
java/engine/org/apache/derby/impl/sql/execute/CreateTriggerConstantAction.java 
(explanation for this node is same as for CreateViewConstantAction)

java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java
  Derby allows multiple foreign key creation within a single sql statement. The 
privileges collected for such a sql may end up having a superset of privileges 
required for individual foreign key constraints. eg
  create table t31ConstraintTest (c311 int references mamta1.t11ConstraintTest, 
c312 int references mamta2.t21ConstraintTest);
  For the above sql, Derby will collect REFERENCES privilege requirements for 
mamta1.t11ConstraintTest and mamta2.t21ConstraintTest. But the foreign key 
constraint on c311 depends only on REFERENCES privilege requirement for 
mamta1.t11ConstraintTest and foreign key constraint on c132 depenly only on 
REFERENCES privilege requirements for mamta2.t21ConstraintTest. The changes in 
the class above makes sure that right REFERENCES privilege gets picked up for 
each foreign key constraint. The logic for this went into executeConstantAction 
method.

java/engine/org/apache/derby/impl/sql/catalog/SYSCOLPERMSRowFactory.java
 Added a column, uuid, (similar to one in SYSCONSTRAINTS). This column will be 
used as PROVIDERID in SYSDEPENDS table to keep track of 
view/triiger/constraint's dependency on column level constraints. 

java/engine/org/apache/derby/impl/sql/catalog/SYSROUTINEPERMSRowFactory.java
 Added a column, uuid, (similar to one in SYSCONSTRAINTS). This column will be 
used as PROVIDERID in SYSDEPENDS table to keep track of 
view/triiger/constraint's dependency on routine level constraints. 

java/engine/org/apache/derby/impl/sql/catalog/SYSTABLEPERMSRowFactory.java
 Added a column, uuid, (similar to one in SYSCONSTRAINTS). This column will be 
used as PROVIDERID in SYSDEPENDS table to keep track of 
view/triiger/constraint's dependency on table level constraints. 

java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
     Add a new method getColumnPermissions which is similar to another method 
by the same name in the class. But the new method accepts column privilege type 
in String format. This new method is called by 
ColPermsDescriptor.getDependableFinder and ColPermsDescriptor keeps privilege 
type in String format.

java/engine/org/apache/derby/impl/sql/catalog/DDColumnPermissionsDependableFinder.java
     Need to add a new class because a Column Permission Descriptor needs a 
tableuuid and the column privilege type. The generic DDdependableFinder class 
can only deal with uuid and hence need a new subclass of DDdependableFinder. 
This new class is similar in nature to existing DDColumnDependableFinder 

java/engine/org/apache/derby/impl/sql/catalog/DDdependableFinder.java
java/engine/org/apache/derby/impl/sql/catalog/CoreDDFinderClassInfo.java
java/engine/org/apache/derby/catalog/Dependable.java
java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java 
java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
     Above few classes do the ground work for 3 permission descriptors so they 
can be used by the existing dependency system(to populate SYSDEPENDS table) to 
record view/triiger/constraint's dependency on them. 

java/engine/org/apache/derby/iapi/sql/dictionary/PermissionsDescriptor.java
 Permission Descriptor can now be the PROVIDER in SYSDEPENDS. ie a 
view/triiger/constraint might be dependent on an object level privilege. In 
order to allow this, PermissionsDescriptor implements Provider interface. Some 
of the methods of the interface are implemented by subclasses on 
PermissionsDescriptor. Also, each of the 3 Permission Descriptors now have a 
unique uuid. Added that uuid to PermissionsDescriptor and provided 
getter/setter on it. This uuid will be used as the PROVIDERID in SYSDEPENDS 
table. In 
addition, there is a method called checkOwner in PermissionsDescriptor which 
checks if the passed authorization id is same as the owner of the object on 
which the permission is defined. This gets called by create 
view/triiger/constraint while storing view/triiger/constraint's dependency on 
various permissions in SYSDEPENDS table. If the view/triiger/constraint and 
object being accessed 
is owned by the same authorization id, then no need to save 
view/triiger/constraint's dependency on object privilege in SYSDEPENDS table. 

java/engine/org/apache/derby/iapi/sql/dictionary/TablePermsDescriptor.java
 This class is modified to implement some of the PROVIDER interface methods. 
Another modification to this class was addition of checkOwner method (described 
under PermissionDescriptor class) 

java/engine/org/apache/derby/iapi/sql/dictionary/RoutinePermsDescriptor.java
 This class is modified to implement some of the PROVIDER interface methods. 
Another modification to this class was addition of checkOwner method (described 
under PermissionDescriptor class) 

java/engine/org/apache/derby/iapi/sql/dictionary/ColPermsDescriptor.java
 This class is modified to implement some of the PROVIDER interface methods. 
Another modification to this class was addition of checkOwner method (described 
under PermissionDescriptor class) 

java/engine/org/apache/derby/iapi/sql/dictionary/DataDescriptorGenerator.java
 Three methods in this class are modified to throw StandardException in their 
signature because they call constructor's of PermissionDescriptor subclasses 
and those constructors can throw StandardException. 

java/engine/org/apache/derby/iapi/sql/dictionary/StatementPermission.java
java/engine/org/apache/derby/iapi/sql/dictionary/StatementTablePermission.java
java/engine/org/apache/derby/iapi/sql/dictionary/StatementRoutinePermission.java
 
java/engine/org/apache/derby/iapi/sql/dictionary/StatementSchemaPermission.java
java/engine/org/apache/derby/iapi/sql/dictionary/StatementColumnPermission.java
     In the classes above, added a method called getPermissionDescriptor which 
will return the PermissionDescriptor for the passed authorization id for the 
StatementPermission object. This method gets during the execution phase of 
create view/trigger/constraint to track view/trigger/constraint's dependency on 
various permissions. getPermissionDescriptor for StatementSchemaPermission 
always returns null because views/triggers/constraints do not need to keep 
track of schema level privileges. They only need table, column and routine 
privileges as part of view/trigger/constraint dependency. They do need to have 
create permission is the schema, but once the view/trigger/constraint is 
created in that schema, there is no need to keep that schema permission in 
SYSDEPENDS. Special code is required to track column level privileges. It is 
possible that some column level privileges are available to the passed 
authorizer id but the rest required column level privileges are available at 
PUBLIC level. In order to record 
view/trigger/constraint dependency on user level and public level column 
privileges, I needed to add method getPUBLIClevelColPermsDescriptor to 
StatementColumnPermission. 

Test changes in following files
java/testing/org/apache/derbyTesting/functionTests/tests/lang/grantRevokeDDL.sql
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/syscat.out
java/testing/org/apache/derbyTesting/functionTests/master/grantRevokeDDL.out 
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/syscat.out
java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/jdk14/syscat.out
java/testing/org/apache/derbyTesting/functionTests/master/syscat.out 
java/testing/org/apache/derbyTesting/functionTests/util/ProcedureTest.java 

I have attached the svn stat -q(Derby1330PrivilegeCollectionV2stat.txt) and svn 
diff(Derby1330PrivilegeCollectionV2diff.txt) output to DERBY-1330.

As always, any feedback highly appreciated.


> Provide runtime privilege checking for grant/revoke functionality
> -----------------------------------------------------------------
>
>          Key: DERBY-1330
>          URL: http://issues.apache.org/jira/browse/DERBY-1330
>      Project: Derby
>         Type: Sub-task

>   Components: SQL
>     Versions: 10.2.0.0
>     Reporter: Mamta A. Satoor
>     Assignee: Mamta A. Satoor
>  Attachments: AuthorizationModelForDerbySQLStandardAuthorization.html, 
> AuthorizationModelForDerbySQLStandardAuthorizationV2.html, 
> Derby1330PrivilegeCollectionV2diff.txt, 
> Derby1330PrivilegeCollectionV2stat.txt, 
> Derby1330ViewPrivilegeCollectionV1diff.txt, 
> Derby1330ViewPrivilegeCollectionV1stat.txt
>
> Additional work needs to be done for grant/revoke to make sure that only 
> users with required privileges can access various database objects. In order 
> to do that, first we need to collect the privilege requirements for various 
> database objects and store them in SYS.SYSREQUIREDPERM. Once we have this 
> information then when a user tries to access an object, the required 
> SYS.SYSREQUIREDPERM privileges for the object will be checked against the 
> user privileges in SYS.SYSTABLEPERMS, SYS.SYSCOLPERMS and 
> SYS.SYSROUTINEPERMS. The database object access will succeed only if the user 
> has the necessary privileges.
> SYS.SYSTABLEPERMS, SYS.SYSCOLPERMS and SYS.SYSROUTINEPERMS are already 
> populated by Satheesh's work on DERBY-464. But SYS.SYSREQUIREDPERM doesn't 
> have any information in it at this point and hence no runtime privilege 
> checking is getting done at this point.

-- 
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

Reply via email to