Author: shawkins
Date: 2010-08-09 16:13:40 -0400 (Mon, 09 Aug 2010)
New Revision: 2431
Modified:
trunk/client/src/main/java/org/teiid/adminapi/DataPolicy.java
trunk/client/src/main/java/org/teiid/adminapi/impl/DataPolicyMetadata.java
trunk/documentation/reference/src/main/docbook/en-US/content/entitlements.xml
trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
Log:
TEIID-1194 updating the docs to included more general permission information TEIID-1071
simplifying the permission checking logic
Modified: trunk/client/src/main/java/org/teiid/adminapi/DataPolicy.java
===================================================================
--- trunk/client/src/main/java/org/teiid/adminapi/DataPolicy.java 2010-08-09 17:46:28 UTC
(rev 2430)
+++ trunk/client/src/main/java/org/teiid/adminapi/DataPolicy.java 2010-08-09 20:13:40 UTC
(rev 2431)
@@ -63,24 +63,24 @@
* Is "CREATE" allowed?
* @return
*/
- boolean isAllowCreate();
+ Boolean isAllowCreate();
/**
* Is "SELECT" allowed?
* @return
*/
- boolean isAllowRead();
+ Boolean isAllowRead();
/**
* Is "INSERT/UPDATE" allowed?
* @return
*/
- boolean isAllowUpdate();
+ Boolean isAllowUpdate();
/**
* Is "DELETE" allowed?
* @return
*/
- boolean isAllowDelete();
+ Boolean isAllowDelete();
}
}
Modified: trunk/client/src/main/java/org/teiid/adminapi/impl/DataPolicyMetadata.java
===================================================================
--- trunk/client/src/main/java/org/teiid/adminapi/impl/DataPolicyMetadata.java 2010-08-09
17:46:28 UTC (rev 2430)
+++ trunk/client/src/main/java/org/teiid/adminapi/impl/DataPolicyMetadata.java 2010-08-09
20:13:40 UTC (rev 2431)
@@ -58,7 +58,7 @@
private static final long serialVersionUID = -6992984146431492449L;
@Override
public String getKey(PermissionMetaData entry) {
- return entry.getResourceName();
+ return entry.getResourceName().toLowerCase();
}
});
@@ -121,17 +121,17 @@
}
public boolean allows(String resourceName, DataPolicy.PermissionType type) {
- for(PermissionMetaData permission:this.permissions.getMap().values()) {
- if (permission.getResourceName().equalsIgnoreCase(resourceName) ) {
- return permission.allows(type);
+ resourceName = resourceName.toLowerCase();
+ while (resourceName.length() > 0) {
+ PermissionMetaData p = this.permissions.getMap().get(resourceName);
+ if (p != null) {
+ Boolean allowed = p.allows(type);
+ if (allowed != null) {
+ return allowed;
+ }
}
+ resourceName = resourceName.substring(0, Math.max(0,
resourceName.lastIndexOf('.')));
}
-
- for(PermissionMetaData permission:this.permissions.getMap().values()) {
- if (permission.allows(resourceName, type)) {
- return true;
- }
- }
return false;
}
@@ -147,15 +147,7 @@
@ManagementObject(properties=ManagementProperties.EXPLICIT)
public static class PermissionMetaData implements DataPermission, Serializable {
private static final long serialVersionUID = 7034744531663164277L;
- private static final String SEPARATOR = "."; //$NON-NLS-1$
- public static final String RECURSIVE = "*"; //$NON-NLS-1$
- private static final String ALL_NODES = RECURSIVE;
- public static final String SEPARATOR_WITH_RECURSIVE = SEPARATOR + RECURSIVE;
- // derived state
- private String canonicalName; // The resource's canonical name
- private boolean isRecursive = false; // Is this a recursive resource?
-
// XML based fields
private String resourceName;
@XmlElement(name = "allow-create")
@@ -177,15 +169,11 @@
public void setResourceName(String value) {
this.resourceName = value;
- init(this.resourceName);
}
@Override
@ManagementProperty(description="Allows Create")
- public boolean isAllowCreate() {
- if (allowCreate == null) {
- return false;
- }
+ public Boolean isAllowCreate() {
return allowCreate;
}
@@ -195,10 +183,7 @@
@Override
@ManagementProperty(description="Allows Read")
- public boolean isAllowRead() {
- if (allowRead == null) {
- return false;
- }
+ public Boolean isAllowRead() {
return allowRead;
}
@@ -208,10 +193,7 @@
@Override
@ManagementProperty(description="Allows Update")
- public boolean isAllowUpdate() {
- if (allowUpdate == null) {
- return false;
- }
+ public Boolean isAllowUpdate() {
return allowUpdate;
}
@@ -221,10 +203,7 @@
@Override
@ManagementProperty(description="Allows Delete")
- public boolean isAllowDelete() {
- if (allowDelete == null) {
- return false;
- }
+ public Boolean isAllowDelete() {
return allowDelete;
}
@@ -234,91 +213,35 @@
public String getType() {
StringBuilder sb = new StringBuilder();
- if (isAllowCreate()) {
+ if (Boolean.TRUE.equals(isAllowCreate())) {
sb.append("C");//$NON-NLS-1$
}
- if (isAllowRead()) {
+ if (Boolean.TRUE.equals(isAllowRead())) {
sb.append("R");//$NON-NLS-1$
}
- if (isAllowUpdate()) {
+ if (Boolean.TRUE.equals(isAllowUpdate())) {
sb.append("U");//$NON-NLS-1$
}
- if (isAllowDelete()) {
+ if (Boolean.TRUE.equals(isAllowDelete())) {
sb.append("D");//$NON-NLS-1$
}
return sb.toString();
}
- public boolean allows(PermissionType type) {
- boolean allowedType = false;
+ public Boolean allows(PermissionType type) {
switch (type) {
case CREATE:
- allowedType = isAllowCreate();
- break;
+ return isAllowCreate();
case READ:
- allowedType = isAllowRead();
- break;
+ return isAllowRead();
case UPDATE:
- allowedType = isAllowUpdate();
- break;
+ return isAllowUpdate();
case DELETE:
- allowedType = isAllowDelete();
- break;
+ return isAllowDelete();
}
- return allowedType;
+ throw new AssertionError();
}
- public boolean allows(String checkResource, PermissionType type) {
- boolean allowedType = allows(type);
- boolean allowed = false;
-
- if (allowedType) {
- checkResource = checkResource.toLowerCase();
- if ( isRecursive ) {
- if ( checkResource.startsWith(this.canonicalName) ) {
- allowed = true;
- }
- } else {
- allowed = this.canonicalName.equals(checkResource);
-
- if (!allowed) {
- // if this resource is a group level permission, then grant permission to
any children
- // for ex: 'foo.x.y' has permission if 'foo.x' is defined
- int lastSepIndex = checkResource.lastIndexOf(SEPARATOR);
- if ( lastSepIndex > 0 && checkResource.substring(0,
lastSepIndex).equals(this.canonicalName) ) {
- allowed = true;
- }
- }
- }
- }
- return allowed;
- }
-
- /**
- * This method is invoked by the constructors that take a string resource name,
and is
- * to strip out any recursive or wildcard characters and return simple the name
of the
- * node.
- */
- private void init( String resourceName ) {
- // If the resource name is the ALL_NODES resource ...
- if ( resourceName.equals(ALL_NODES) ) {
- this.isRecursive = true;
- this.canonicalName = ""; // resource name should be
nothing //$NON-NLS-1$
- }
-
- // If the resource name includes the recursive parameter ...
- if ( resourceName.endsWith(SEPARATOR_WITH_RECURSIVE) ) {
- isRecursive = true;
- this.canonicalName = resourceName.substring(0, resourceName.length()-2);
- } else if (resourceName.endsWith(RECURSIVE) ) {
- this.isRecursive = true;
- this.canonicalName = resourceName.substring(0, resourceName.length()-1);
- } else {
- this.canonicalName = resourceName;
- }
- this.canonicalName = this.canonicalName.toLowerCase();
- }
-
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getResourceName());
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/entitlements.xml
===================================================================
---
trunk/documentation/reference/src/main/docbook/en-US/content/entitlements.xml 2010-08-09
17:46:28 UTC (rev 2430)
+++
trunk/documentation/reference/src/main/docbook/en-US/content/entitlements.xml 2010-08-09
20:13:40 UTC (rev 2431)
@@ -10,34 +10,62 @@
<code><jboss-install>/server/<profile>/deploy/teiid/teiid-jboss-beans.xml</code>
file
in bean configuration section of <code>RuntimeEngineDeployer</code> with
property <code>useEntitlements</code>.</para>
- <para>Once data roles are enabled, the access permissions defined in a VDB will
be enforced by the Teiid Server.</para>
+ <para>Once data roles are enabled, the access permissions defined in a VDB will
be enforced by the Teiid Server.
+ </para>
+ <warning><para>Teiid uses a deny by default permission system, so all
VDBs deployed to the server will need roles granting access with this feature
enabled.</para></warning>
+
<section>
<title>Permissions</title>
+
+ <para>CREATE, READ, UPDATE, DELETE (CRUD) permissions can be set for any resource
path in a VDB.
+ A resource path can be as specific as the fully qualified name of a column or as
general a top level model (schema) name.
+ Permissions granted to a particular path apply to it and any resource paths that share
the same partial name.
+ For example, granting read to "model" will also grant read to
"model.table", "model.table.column", etc.
+ Allowing or denying a particular action is determined by searching for permissions from
the most to least specific resource paths.
+ The first permission found with a specific allow or deny will be used.
+ Thus it is possible to set very general permissions at high-level resource path names
and to override only as necessary at more specific resource paths.
+ </para>
+
+ <para>Permission grants are only needed for resources that are visible.
+ All non-visible, typically physical, models in a VDB are automatically
+ inaccessible by user level requests. Permissions are also only applied
+ to the columns and tables in the user query - not to every resource
+ accessed transitively through views and procedures.
+ It is important therefore to ensure that permission grants are applied
+ consistently across visible models that access the same resources.
+ </para>
+
<orderedlist>
- <para>To process a <code>SELECT</code> statement or a stored
procedure execution, the user account requires the following access rights:</para>
- <listitem> <para><code>READ</code> - on the Table(s)
being accessed or the procedure being called.</para></listitem>
- <listitem> <para><code>READ</code> - on every column
referenced.</para></listitem>
+ <para>To process a <emphasis>SELECT</emphasis> statement or a
stored procedure execution, the user account requires the following access
rights:</para>
+ <listitem> <para><emphasis>READ</emphasis> - on the
Table(s) being accessed or the procedure being called.</para></listitem>
+ <listitem> <para><emphasis>READ</emphasis> - on every
column referenced.</para></listitem>
</orderedlist>
<orderedlist>
- <para>To process an <code>INSERT</code> statement, the user
account requires the following access rights:</para>
- <listitem> <para><code>CREATE</code> - on the Table
being inserted into.</para></listitem>
- <listitem> <para><code>CREATE</code> - on every column
being inserted on that Table.</para></listitem>
+ <para>To process an <emphasis>INSERT</emphasis> statement, the
user account requires the following access rights:</para>
+ <listitem> <para><emphasis>CREATE</emphasis> - on the
Table being inserted into.</para></listitem>
+ <listitem> <para><emphasis>CREATE</emphasis> - on every
column being inserted on that Table.</para></listitem>
</orderedlist>
<orderedlist>
- <para>To process an <code>UPDATE</code> statement, the user
account requires the following access rights:</para>
- <listitem> <para><code>UPDATE</code> - on the Table
being updated.</para></listitem>
- <listitem> <para><code>UPDATE</code> - on every column
being updated on that Table.</para></listitem>
- <listitem> <para><code>READ</code> - on every column
referenced in the criteria.</para></listitem>
+ <para>To process an <emphasis>UPDATE</emphasis> statement, the
user account requires the following access rights:</para>
+ <listitem> <para><emphasis>UPDATE</emphasis> - on the
Table being updated.</para></listitem>
+ <listitem> <para><emphasis>UPDATE</emphasis> - on every
column being updated on that Table.</para></listitem>
+ <listitem> <para><emphasis>READ</emphasis> - on every
column referenced in the criteria.</para></listitem>
</orderedlist>
<orderedlist>
- <para>To process a <code>DELETE</code> statement, the user
account requires the following access rights:</para>
- <listitem> <para><code>DELETE</code> - on the Table
being deleted.</para></listitem>
- <listitem> <para><code>READ</code> - on every column
referenced in the criteria.</para></listitem>
- </orderedlist>
+ <para>To process a <emphasis>DELETE</emphasis> statement, the
user account requires the following access rights:</para>
+ <listitem> <para><emphasis>DELETE</emphasis> - on the
Table being deleted.</para></listitem>
+ <listitem> <para><emphasis>READ</emphasis> - on every
column referenced in the criteria.</para></listitem>
+ </orderedlist>
+
+ <orderedlist>
+ <para>To process a <emphasis>EXEC</emphasis> statement, the user
account requires the following access rights:</para>
+ <listitem> <para><emphasis>READ</emphasis> - on the
Procedure being executed.</para></listitem>
+ </orderedlist>
+
</section>
<section>
@@ -106,8 +134,7 @@
</vdb>]]></programlisting>
</example>
<para>The above XML defined two data roles, "RoleA" which allows
everything except delete on the table, "RoleC" that
- allows only read operation on the table. Since Teiid uses deny by default, there is no
explict data-policy entry needed for "RoleB". The "mapped-role-name"
defines the "role" to whom these policies are applicable. Each data-policy
- must define a "role" to be enforced by the Teiid Server.</para>
+ allows only read operation on the table. Since Teiid uses deny by default, there is no
explicit data-policy entry needed for "RoleB". The "mapped-role-name"
defines the "role" to whom these policies are applicable.</para>
<para>For assigning the roles to your users, in the JBoss AS,
check out the instructions for the selected Login Module. Check "Admin
Guide" for configuring Login Modules.</para>
@@ -115,8 +142,6 @@
<para>"vdb.xml" file is checked against the schema file
<code>vdb-deployer.xsd</code>, check the documents sections of the Teiid kit
to find a copy of the schema file.</para>
- <note><para>Currently there is no GUI tooling support in the Designer or
any other management tool to create this data roles
- permissions xml, however this is in our roadmap for future releases to
provide.</para></note>
</section>
</chapter>
\ No newline at end of file
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java 2010-08-09
17:46:28 UTC (rev 2430)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java 2010-08-09
20:13:40 UTC (rev 2431)
@@ -23,6 +23,7 @@
package org.teiid.dqp.internal.process;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -181,9 +182,7 @@
}
// Check that all elements of group being deleted have delete permission
- HashSet deleteVars = new HashSet();
- deleteVars.add(obj.getGroup());
- validateEntitlements(deleteVars, DataPolicy.PermissionType.DELETE,
Context.DELETE);
+ validateEntitlements(Arrays.asList(obj.getGroup()),
DataPolicy.PermissionType.DELETE, Context.DELETE);
}
/**
@@ -194,7 +193,7 @@
Into intoObj = obj.getInto();
if ( intoObj != null ) {
GroupSymbol intoGroup = intoObj.getGroup();
- List intoElements = null;
+ List<ElementSymbol> intoElements = null;
try {
intoElements = ResolverUtil.resolveElementsInGroup(intoGroup,
getMetadata());
} catch (QueryMetadataException err) {
@@ -224,9 +223,7 @@
* Validate query entitlements
*/
protected void validateEntitlements(StoredProcedure obj) {
- List symbols = new ArrayList(1);
- symbols.add(obj.getGroup());
- validateEntitlements(symbols, DataPolicy.PermissionType.READ,
Context.STORED_PROCEDURE);
+ validateEntitlements(Arrays.asList(obj.getGroup()),
DataPolicy.PermissionType.READ, Context.STORED_PROCEDURE);
}
private String getActionLabel(DataPolicy.PermissionType actionCode) {
@@ -246,11 +243,9 @@
* @param actionCode The actions to validate for
* @param auditContext The {@link AuthorizationService} to use when resource auditing
is done.
*/
- protected void validateEntitlements(Collection symbols, DataPolicy.PermissionType
actionCode, Context auditContext) {
- Map nameToSymbolMap = new HashMap();
- Iterator symbolIter = symbols.iterator();
- while(symbolIter.hasNext()) {
- Object symbol = symbolIter.next();
+ protected void validateEntitlements(Collection<? extends Symbol> symbols,
DataPolicy.PermissionType actionCode, Context auditContext) {
+ Map<String, Symbol> nameToSymbolMap = new HashMap<String, Symbol>();
+ for (Symbol symbol : symbols) {
try {
String fullName = null;
Object metadataID = null;
@@ -276,12 +271,10 @@
}
if (!nameToSymbolMap.isEmpty()) {
- Collection inaccessibleResources = getInaccessibleResources(actionCode,
nameToSymbolMap.keySet(), auditContext);
+ Collection<String> inaccessibleResources =
getInaccessibleResources(actionCode, nameToSymbolMap.keySet(), auditContext);
if(inaccessibleResources.size() > 0) {
- List inaccessibleSymbols = new ArrayList(inaccessibleResources.size());
- Iterator nameIter = inaccessibleResources.iterator();
- while(nameIter.hasNext()) {
- String name = (String) nameIter.next();
+ List<Symbol> inaccessibleSymbols = new
ArrayList<Symbol>(inaccessibleResources.size());
+ for (String name : inaccessibleResources) {
inaccessibleSymbols.add(nameToSymbolMap.get(name));
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java 2010-08-09
17:46:28 UTC (rev 2430)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java 2010-08-09
20:13:40 UTC (rev 2431)
@@ -226,7 +226,7 @@
Set<String> roles = new HashSet<String>();
if (getSubject() == null) {
- return Collections.EMPTY_SET;
+ return Collections.emptySet();
}
Set<Principal> principals = getSubject().getPrincipals();
@@ -234,9 +234,9 @@
// this JBoss specific, but no code level dependencies
if ((p instanceof Group) && p.getName().equals("Roles")){
//$NON-NLS-1$
Group g = (Group)p;
- Enumeration rolesPrinciples = g.members();
+ Enumeration<? extends Principal> rolesPrinciples = g.members();
while(rolesPrinciples.hasMoreElements()) {
- roles.add(((Principal)rolesPrinciples.nextElement()).getName());
+ roles.add(rolesPrinciples.nextElement().getName());
}
}
}