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
-<<<<<<< HEAD
- TEIID-1070 Amazon SimpleDB support has been contributed by Radim Hopp. See the Admin and Reference Guides for more.
- TEIID-2761 Security Enhancements added support for a grant-all attribute on a role. Also added the ability to specify the security domain for a VDB. See the reference guide for more.
- TEIID-2780 Apache Solr Translator has been added. See the Admin and Reference Guides for more.
-
- TEIID-2809 Pattern based system property substitution has been added to VDB.XML files. Only supported if the DVB is being deployed JBoss EAP.
+
- TEIID-2809 Pattern based system property substitution has been added to VDB.XML files. Only supported if the DVB is being deployed JBoss EAP.
+
- TEIID-2844 Removsl og unauthorized columns from SELECT * can be enabled via the session property ignore_unauthorized_asterisk. See the Reference for more.
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 extends LanguageObject> 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 extends LanguageObject> 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 extends LanguageObject> 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) {
+
+ }
+ }
}