Pentaho metadata security
The easiest way to implement multi-tenancy is to use a global security constraint in the data model. The advantage to this approach is that there is no code to maintain, making it simple for non-developers to implement. However, there are several disadvantages to this approach, such as that complex constraints can be difficult to model and not all constraints can be modeled. This approach also applies to all queries which may result in unnecessary joins. Finally, each model has to be constrained, whereas the SQL Generator can be applied to all models with one piece of code.
Set the global constraint
To set the global constraint:
Edit the data model.
Set a constraint on the business model to be constrained using available formulas.
[BT_EMPLOYEES_EMPLOYEES].[BC_EMPLOYEES_OFFICECODE]="SESSION("officeCode")"
See the Pentaho Metadata Editor document for details.
Repeat for all tables and models as necessary.
See Edit the properties file for Metadata Editor in the Install Pentaho Data Integration and Analytics document for more information on setting Pentaho metadata security.
SQL generator
The SQL Generator is a special class that is called when Pentaho metadata queries the database. There are two methods that can be overwritten: preprocessQueryModel()
and processGeneratedSql()
.
preprocessQueryModel()
The recommended method to overwrite. It is called before the SQL is generated. To overwrite, add an
AND
condition to the query to restrict data.processGeneratedSql()
The method called after the SQL is generated. While it is possible to modify this query, it would involve parsing and modifying the string query.
The following example shows the preprocessQueryModel()
for a class that extends the SqlGenerator
class. The first loop gathers all of the columns to see which ones need to be constrained to avoid duplicate checks. The second loop adds a WHERE
clause to the query. Only AND
conditions can be used. Because you cannot add parentheses, using AND
conditions can cause problems if the model already has an OR
condition in the WHERE
clause.
@Override
protected void preprocessQueryModel(SQLQueryModel query, List<Selection> selections, Map<LogicalTable, String> tableAliases, DatabaseMeta databaseMeta) {
Set<LogicalTable> selectedLogicalTables = new HashSet<LogicalTable>();
// Get the users productline from the session
IPentahoSession session = PentahoSessionHolder.getSession();
String productline = (String)session.getAttribute("productline");
//Object territory = "NA" ;
// Figure out and gather up the selected logical tables. We need to
// know if the CUSTOMER_W_TER table is included in the
// query...
if(selections!=null && !selections.isEmpty()) {
for(Selection selection:selections) {
LogicalColumn column = selection.getLogicalColumn();
LogicalTable table = column.getLogicalTable();
selectedLogicalTables.add(table);
}
}
// We now find the column to constrain, and add our where
// clause, using a dialect specific where clause...
for(LogicalTable table:selectedLogicalTables) {
List<LogicalColumn> logicalColumns=table.getLogicalColumns();
for(LogicalColumn logicalColumn:logicalColumns) {
if(logicalColumn.getId().equalsIgnoreCase("BC_PRODUCTS_PRODUCTLINE")) {
String tableAlias = tableAliases.get(table);
String columnName = (String) logicalColumn.getPhysicalColumn().
getProperty("target_column");
query.addWhereFormula(tableAlias + "." +
columnName + " = '" + productline + "', AND");
}
}
}
}
Once the code has been compiled and placed in a JAR file, it should be deployed to webapps/pentaho/WEB-INF/lib
. Then two files need to be modified:
pentaho-solutions/system/pentahoObjects.spring.xml
should be modified to change the class defined for the
sqlGenerator
bean. The following shows an example of the bean mapping:<bean id="sqlGenerator" class="org.myorganization.MySqlGenerator" scope="prototype"/>
webapps/pentaho/WEB-INF/classes/classic-engine.properties
should be modified by defining a new parameter:
org.pentaho.reporting.engine.classic.extensions.datasources.pmd.SqlGeneratorClass=org.myorganization.MySqlGenerator
One way to debug SQLGenerator
functionality is to view the generated SQL statements. A common method is to use logging statements within processGeneratedSql
and increase the log level of SQLGenerator
in log4j.xml
file under webapps/pentaho/WEB-INF/classes
.
<category name="org.pentaho.metadata.query.impl.sql.SqlGenerator">
<priority value="DEBUG"/>
</category>
<category name="org.myorganization.MySqlGenerator">
<priority value="DEBUG"/>
</category>
Reference
SQLGenerator JavaDoc: https://github.com/pentaho/pentaho-metadata/blob/10.2.0.0-218/src/main/java/org/pentaho/metadata/query/impl/sql/SqlGenerator.java
Last updated
Was this helpful?