diff --git a/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html b/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html index 4171e6013c..8819971a7e 100644 --- a/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html +++ b/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html @@ -26,11 +26,11 @@

Overview

Highlights

Compatibility Issues

diff --git a/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java b/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java index f0d5690853..a044a3f632 100644 --- a/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java +++ b/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java @@ -40,6 +40,7 @@ import org.teiid.logging.MessageLevel; import org.teiid.query.QueryPlugin; import org.teiid.query.function.FunctionLibrary; +import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.metadata.TempMetadataID; import org.teiid.query.resolver.util.ResolverUtil; import org.teiid.query.sql.LanguageObject; @@ -295,7 +296,7 @@ protected void validateEntitlements(Collection symbols if (metadataID instanceof TempMetadataID) { if (group.isProcedure()) { Map procMap = new LinkedHashMap(); - addToNameMap(((TempMetadataID)metadataID).getOriginalMetadataID(), symbol, procMap); + addToNameMap(((TempMetadataID)metadataID).getOriginalMetadataID(), symbol, procMap, getMetadata()); validateEntitlements(PermissionType.EXECUTE, auditContext, procMap); } else if (group.isTempTable() && group.isImplicitTempGroupSymbol()) { validateTemp(actionCode, group.getNonCorrelationName(), false, group, auditContext); @@ -303,7 +304,7 @@ protected void validateEntitlements(Collection symbols continue; } } - addToNameMap(metadataID, symbol, nameToSymbolMap); + addToNameMap(metadataID, symbol, nameToSymbolMap, getMetadata()); } catch(QueryMetadataException e) { handleException(e); } catch(TeiidComponentException e) { @@ -314,16 +315,16 @@ protected void validateEntitlements(Collection symbols validateEntitlements(actionCode, auditContext, nameToSymbolMap); } - private void addToNameMap(Object metadataID, LanguageObject symbol, Map nameToSymbolMap) throws QueryMetadataException, TeiidComponentException { - String fullName = getMetadata().getFullName(metadataID); - Object modelId = getMetadata().getModelID(metadataID); - String modelName = getMetadata().getFullName(modelId); + static void addToNameMap(Object metadataID, LanguageObject symbol, Map nameToSymbolMap, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { + String fullName = metadata.getFullName(metadataID); + Object modelId = metadata.getModelID(metadataID); + String modelName = metadata.getFullName(modelId); if (!isSystemSchema(modelName)) { nameToSymbolMap.put(fullName, symbol); } } - private boolean isSystemSchema(String modelName) { + static private boolean isSystemSchema(String modelName) { return CoreConstants.SYSTEM_MODEL.equalsIgnoreCase(modelName) || CoreConstants.ODBC_MODEL.equalsIgnoreCase(modelName); } diff --git a/engine/src/main/java/org/teiid/dqp/internal/process/DefaultAuthorizationValidator.java b/engine/src/main/java/org/teiid/dqp/internal/process/DefaultAuthorizationValidator.java index eb0d0394fe..46d89fae43 100644 --- a/engine/src/main/java/org/teiid/dqp/internal/process/DefaultAuthorizationValidator.java +++ b/engine/src/main/java/org/teiid/dqp/internal/process/DefaultAuthorizationValidator.java @@ -22,11 +22,28 @@ package org.teiid.dqp.internal.process; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + import org.teiid.PolicyDecider; +import org.teiid.adminapi.DataPolicy.Context; +import org.teiid.adminapi.DataPolicy.PermissionType; import org.teiid.api.exception.query.QueryValidatorException; import org.teiid.core.TeiidComponentException; +import org.teiid.core.types.DataTypeManager; +import org.teiid.core.types.TransformationException; +import org.teiid.core.util.PropertiesUtils; +import org.teiid.dqp.internal.process.multisource.MultiSourceElement; +import org.teiid.query.QueryPlugin; import org.teiid.query.metadata.QueryMetadataInterface; +import org.teiid.query.metadata.TempMetadataID; +import org.teiid.query.sql.LanguageObject; import org.teiid.query.sql.lang.Command; +import org.teiid.query.sql.lang.Query; +import org.teiid.query.sql.symbol.ElementSymbol; +import org.teiid.query.sql.symbol.Expression; +import org.teiid.query.sql.symbol.MultipleElementSymbol; import org.teiid.query.util.CommandContext; /** @@ -34,7 +51,9 @@ */ public class DefaultAuthorizationValidator implements AuthorizationValidator { + public static final String IGNORE_UNAUTHORIZED_ASTERISK = "ignore_unauthorized_asterisk"; //$NON-NLS-1$ private PolicyDecider policyDecider; + private boolean ignoreUnauthorizedAsteriskDefault = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.ignoreUnauthorizedAsterisk", false); //$NON-NLS-1$ public DefaultAuthorizationValidator() { } @@ -44,10 +63,61 @@ public boolean validate(String[] originalSql, Command command, QueryMetadataInterface metadata, CommandContext commandContext, CommandType commandType) throws QueryValidatorException, TeiidComponentException { + boolean modified = false; if (policyDecider != null && policyDecider.validateCommand(commandContext)) { + if (ignoreUnathorizedInAsterisk(command, commandContext)) { + Query query = (Query)command; + HashMap map = null; + for (Expression ex : query.getSelect().getSymbols()) { + if (ex instanceof MultipleElementSymbol) { + MultipleElementSymbol mes = (MultipleElementSymbol)ex; + if (map == null) { + map = new HashMap(); + } + for (Iterator iter = mes.getElementSymbols().iterator(); iter.hasNext();) { + ElementSymbol es = iter.next(); + Object metadataObject = es.getMetadataID(); + if (metadataObject instanceof MultiSourceElement || metadataObject instanceof TempMetadataID) { + continue; + } + map.clear(); + AuthorizationValidationVisitor.addToNameMap(metadataObject, es, map, commandContext.getMetadata()); + Set results = this.policyDecider.getInaccessibleResources(PermissionType.READ, map.keySet(), Context.QUERY, commandContext); + if (!results.isEmpty()) { + iter.remove(); //remove from the select + modified = true; + } + } + } + } + if (query.getProjectedSymbols().isEmpty()) { + throw new QueryValidatorException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31151)); + } + } AuthorizationValidationVisitor visitor = new AuthorizationValidationVisitor(this.policyDecider, commandContext); Request.validateWithVisitor(visitor, metadata, command); } + return modified; + } + + private boolean ignoreUnathorizedInAsterisk(Command command, CommandContext commandContext) { + if (!(command instanceof Query)) { + return false; + } + Query query = (Query)command; + if (query.getIsXML() || query.getInto() != null) { + return false; + } + if (ignoreUnauthorizedAsteriskDefault) { + return true; + } + Object value = commandContext.getSessionVariable(IGNORE_UNAUTHORIZED_ASTERISK); + if (value != null) { + try { + return Boolean.TRUE.equals(DataTypeManager.transformValue(value, DataTypeManager.DefaultDataClasses.BOOLEAN)); + } catch (TransformationException e) { + } + } return false; } diff --git a/engine/src/main/java/org/teiid/query/QueryPlugin.java b/engine/src/main/java/org/teiid/query/QueryPlugin.java index 7e6eaec601..7cb32bf595 100644 --- a/engine/src/main/java/org/teiid/query/QueryPlugin.java +++ b/engine/src/main/java/org/teiid/query/QueryPlugin.java @@ -562,6 +562,7 @@ public static enum Event implements BundleUtil.Event{ TEIID31147, TEIID31148, TEIID31149, - TEIID31150 + TEIID31150, + TEIID31151 } } diff --git a/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java b/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java index 88278c5207..062e55c4f8 100644 --- a/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java +++ b/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java @@ -170,7 +170,6 @@ private static GroupSymbol resolveAllInGroup(MultipleElementSymbol allInGroupSym qre.addUnresolvedSymbol(new UnresolvedSymbolDescription(allInGroupSymbol.toString(), msg)); throw qre; } - GroupSymbol gs = allInGroupSymbol.getGroup(); allInGroupSymbol.setGroup(groupSymbols.get(0).clone()); return groupSymbols.get(0); } diff --git a/engine/src/main/resources/org/teiid/query/i18n.properties b/engine/src/main/resources/org/teiid/query/i18n.properties index 2bdbc9dca0..726a07d9c7 100644 --- a/engine/src/main/resources/org/teiid/query/i18n.properties +++ b/engine/src/main/resources/org/teiid/query/i18n.properties @@ -1119,4 +1119,6 @@ TEIID31146=Translator {2} not found for vdb {0} {1} TEIID31144=One or more of required properties for materialization management is missing. Required properties are teiid_rel:MATVIEW_STATUS_TABLE, teiid_rel:MATVIEW_BEFORE_LOAD_SCRIPT, teiid_rel:MATVIEW_AFTER_LOAD_SCRIPT, teiid_rel:MATVIEW_LOAD_SCRIPT, teiid_rel:MATERIALIZED_STAGE_TABLE TEIID31147=The materialized view {0}.{1} materialization table is currently not in valid state. TEIID31148=Invalid virtual model {0} specified in conformed sources for {1}. -TEIID31149=No columns are specified on key {1} for table {0}. \ No newline at end of file +TEIID31149=No columns are specified on key {1} for table {0}. + +TEIID31151=After removing unauthorized columns from asterisk in select, no valid columns remain selected. \ No newline at end of file diff --git a/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java b/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java index ef798b9809..789dcd90a0 100644 --- a/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java +++ b/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java @@ -24,6 +24,7 @@ import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -36,11 +37,12 @@ import org.teiid.adminapi.DataPolicy.PermissionType; import org.teiid.adminapi.impl.DataPolicyMetadata; import org.teiid.adminapi.impl.DataPolicyMetadata.PermissionMetaData; -import org.teiid.adminapi.impl.SessionMetadata; import org.teiid.adminapi.impl.VDBMetaData; import org.teiid.api.exception.query.QueryParserException; import org.teiid.api.exception.query.QueryResolverException; +import org.teiid.api.exception.query.QueryValidatorException; import org.teiid.core.TeiidComponentException; +import org.teiid.dqp.internal.process.AuthorizationValidator.CommandType; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.parser.QueryParser; import org.teiid.query.resolver.QueryResolver; @@ -63,8 +65,8 @@ public class TestAuthorizationValidationVisitor { @Before public void setup() { context = new CommandContext(); - context.setSession(new SessionMetadata()); context.setDQPWorkContext(new DQPWorkContext()); + context.setSession(context.getDQPWorkContext().getSession()); } @BeforeClass static public void oneTimeSetup() { @@ -189,15 +191,7 @@ private void helpTest(String sql, QueryMetadataInterface metadata, String[] expe Command command = parser.parseCommand(sql); QueryResolver.resolveCommand(command, metadata); - vdb.addAttchment(QueryMetadataInterface.class, metadata); - - HashMap policies = new HashMap(); - for (DataPolicyMetadata dataPolicyMetadata : roles) { - policies.put(dataPolicyMetadata.getName(), dataPolicyMetadata); - } - this.context.getDQPWorkContext().setPolicies(policies); - DataRolePolicyDecider dataRolePolicyDecider = new DataRolePolicyDecider(); - dataRolePolicyDecider.setAllowFunctionCallsByDefault(false); + DataRolePolicyDecider dataRolePolicyDecider = createPolicyDecider(metadata, vdb, roles); AuthorizationValidationVisitor visitor = new AuthorizationValidationVisitor(dataRolePolicyDecider, context); //$NON-NLS-1$ ValidatorReport report = Validator.validate(command, metadata, visitor); if(report.hasItems()) { @@ -219,6 +213,24 @@ private void helpTest(String sql, QueryMetadataInterface metadata, String[] expe fail("Expected inaccessible objects, but got none."); //$NON-NLS-1$ } } + + private DataRolePolicyDecider createPolicyDecider( + QueryMetadataInterface metadata, VDBMetaData vdb, + DataPolicyMetadata... roles) { + vdb.addAttchment(QueryMetadataInterface.class, metadata); + + HashMap policies = new HashMap(); + for (DataPolicyMetadata dataPolicyMetadata : roles) { + policies.put(dataPolicyMetadata.getName(), dataPolicyMetadata); + } + vdb.setDataPolicies(new ArrayList(policies.values())); + this.context.getDQPWorkContext().setPolicies(policies); + this.context.getSession().setVdb(vdb); + this.context.setMetadata(metadata); + DataRolePolicyDecider dataRolePolicyDecider = new DataRolePolicyDecider(); + dataRolePolicyDecider.setAllowFunctionCallsByDefault(false); + return dataRolePolicyDecider; + } @Test public void testProcRelational() throws Exception { helpTest("select * from sp1", RealMetadataFactory.example1Cached(), new String[] {}, RealMetadataFactory.example1VDB(), exampleAuthSvc1); //$NON-NLS-1$ @@ -393,4 +405,50 @@ private void helpTest(String sql, QueryMetadataInterface metadata, String[] expe helpTest("create foreign temporary table x (id string) on bqt1", RealMetadataFactory.exampleBQTCached(), new String[] {}, RealMetadataFactory.exampleBQTVDB(), svc); //$NON-NLS-1$ //$NON-NLS-2$ helpTest("select * from xmltest.doc1", RealMetadataFactory.example1Cached(), new String[] {}, RealMetadataFactory.example1VDB(), svc); //$NON-NLS-1$ //$NON-NLS-2$ } + + @Test public void testPruneSelectAll() throws Exception { + String sql = "select * from pm1.g1"; + QueryMetadataInterface metadata = RealMetadataFactory.example1Cached(); + + DataPolicyMetadata svc = new DataPolicyMetadata(); + svc.setName("test"); //$NON-NLS-1$ + + svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm1")); //$NON-NLS-1$ + PermissionMetaData p = addResource(DataPolicy.PermissionType.READ, "pm1.g1.e1"); + p.setAllowRead(false); + svc.addPermission(p); //$NON-NLS-1$ + + DataRolePolicyDecider dataRolePolicyDecider = createPolicyDecider(metadata, RealMetadataFactory.example1VDB(), svc); + + DefaultAuthorizationValidator dav = new DefaultAuthorizationValidator(); + dav.setPolicyDecider(dataRolePolicyDecider); + this.context.setSessionVariable(DefaultAuthorizationValidator.IGNORE_UNAUTHORIZED_ASTERISK, "true"); + + QueryParser parser = QueryParser.getQueryParser(); + Command command = parser.parseCommand(sql); + QueryResolver.resolveCommand(command, metadata); + + assertEquals(4, command.getProjectedSymbols().size()); + + boolean modified = dav.validate(new String[] {}, command, metadata, this.context, CommandType.USER); + assertTrue(modified); + + assertEquals(3, command.getProjectedSymbols().size()); + + p = addResource(DataPolicy.PermissionType.READ, "pm1.g1"); + p.setAllowRead(false); + svc.addPermission(p); //$NON-NLS-1$ + + command = parser.parseCommand(sql); + QueryResolver.resolveCommand(command, metadata); + + assertEquals(4, command.getProjectedSymbols().size()); + + try { + dav.validate(new String[] {}, command, metadata, this.context, CommandType.USER); + fail(); + } catch (QueryValidatorException e) { + + } + } }