Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
*/
package org.eclipse.daanse.sql.guard.api;

import java.util.List;

import org.eclipse.daanse.sql.guard.api.elements.DatabaseCatalog;

public interface SqlGuardFactory {

SqlGuard create(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog);
SqlGuard create(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog, List<String> whitelistFunctionsPatterns);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@

package org.eclipse.daanse.sql.guard.jsqltranspiler;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.daanse.sql.guard.api.SqlGuard;
import org.eclipse.daanse.sql.guard.api.elements.DatabaseCatalog;
Expand Down Expand Up @@ -51,11 +53,13 @@ public class TranspilerSqlGuard implements SqlGuard {
private static final String UPDATE_IS_NOT_PERMITTED = "UPDATE is not permitted.";
private static final String INSERT_IS_NOT_PERMITTED = "INSERT is not permitted.";
private static final String NOTHING_WAS_SELECTED = "Nothing was selected.";
private static final String QUERY_HAS_DISAllOWED_FUNCTIONS = "Query has disallowed functions.";
private static final Logger LOGGER = LoggerFactory.getLogger(TranspilerSqlGuard.class);
private JdbcMetaData jdbcMetaDataToCopy;
private List<String> whitelistFunctionsPatterns = new ArrayList<String>();

public TranspilerSqlGuard(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog) {

public TranspilerSqlGuard(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog, List<String> whitelistFunctionsPatterns) {
this.whitelistFunctionsPatterns = whitelistFunctionsPatterns;
jdbcMetaDataToCopy = calculateMetaData(currentCatalogName, currentSchemaName, databaseCatalog);

}
Expand Down Expand Up @@ -114,6 +118,28 @@ public String guard(String sqlStr) throws GuardException {
final List<Expression> functions = resolver.getFunctions();
final Set<String> functionNames = resolver.getFlatFunctionNames();

List<String> allowedFunctions = new ArrayList<>();
List<String> disallowedFunctions = new ArrayList<>();

for (String function : functionNames) {
boolean isAllowed = false;
for (String pattern : whitelistFunctionsPatterns) {
if (Pattern.matches(pattern, function)) {
isAllowed = true;
break;
}
}
if (isAllowed) {
allowedFunctions.add(function);
} else {
disallowedFunctions.add(function);
}
}
if (!disallowedFunctions.isEmpty()) {
LOGGER.atInfo().log(QUERY_HAS_DISAllOWED_FUNCTIONS);
throw new GuardException(QUERY_HAS_DISAllOWED_FUNCTIONS);
}

// we can finally resolve for the actually returned columns
JSQLColumResolver columResolver = new JSQLColumResolver(jdbcMetaDataToCopy);
columResolver.setErrorMode(JdbcMetaData.ErrorMode.STRICT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
*/
package org.eclipse.daanse.sql.guard.jsqltranspiler;

import java.util.List;

import org.eclipse.daanse.sql.guard.api.SqlGuard;
import org.eclipse.daanse.sql.guard.api.SqlGuardFactory;
import org.eclipse.daanse.sql.guard.api.elements.DatabaseCatalog;
Expand All @@ -23,8 +25,8 @@
public class TranspilerSqlGuardFactory implements SqlGuardFactory {

@Override
public SqlGuard create(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog) {
return new TranspilerSqlGuard(currentCatalogName, currentSchemaName, databaseCatalog);
public SqlGuard create(String currentCatalogName, String currentSchemaName, DatabaseCatalog databaseCatalog, List<String> whitelistFunctionsPatterns) {
return new TranspilerSqlGuard(currentCatalogName, currentSchemaName, databaseCatalog, whitelistFunctionsPatterns);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import org.eclipse.daanse.sql.guard.api.elements.DatabaseColumn;
import org.eclipse.daanse.sql.guard.api.elements.DatabaseSchema;
import org.eclipse.daanse.sql.guard.api.elements.DatabaseTable;
import org.eclipse.daanse.sql.guard.api.exception.GuardException;
import org.eclipse.daanse.sql.guard.api.exception.UnresolvableObjectsGuardException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.osgi.test.common.annotation.InjectService;

Expand All @@ -52,8 +52,20 @@ public class SqlGuardTest {

private static final String SQL_WITH_FUNCTION = "select trim(foo.name) from foo";

private static final String SQL_WITH_ALLOWED_FUNCTION = "select %s(foo.name) from foo";

private static final String SQL_WITH_ALLOWED_FUNCTION_IN_WHERE = "select foo.name from foo where %s(foo.name) = 1";

private static final String SQL_WITH_ALLOWED_FUNCTION_IN_HAVING = "select foo.name from foo group by foo.name HAVING %s(foo.id) > 5";

private static final String SQL_WITH_FUNCTION_EXPECTED = "SELECT Trim( foo.name ) FROM sch.foo";

private static final String SQL_WITH_ALLOWED_FUNCTION_EXPECTED = "SELECT %s(foo.name) FROM sch.foo";

private static final String SQL_WITH_ALLOWED_FUNCTION__IN_WHERE_EXPECTED = "SELECT foo.name FROM sch.foo WHERE %s(foo.name) = 1";

private static final String SQL_WITH_ALLOWED_FUNCTION__IN_HAVING_EXPECTED = "SELECT foo.name FROM sch.foo GROUP BY foo.name HAVING %s(foo.id) > 5";

private static final String SQL_WITH_HAVING_WRONG_COLUMN = """
select %s(foo.id) from foo group by foo.name having foo.name1 = 'tets'""";

Expand Down Expand Up @@ -140,11 +152,15 @@ public class SqlGuardTest {

private static final List<String> AGGREGATIONS = List.of("sum", "count", "distinctcount", "avg");

private static final List<String> ALLOWED_FUNCTIONS = List.of("DeleteAll", "InsertAll", "UpdateAll", "Modify", "deleteAll", "insertAll", "updateAll", "modify");

private static final List<String> NOT_ALLOWED_FUNCTIONS = List.of("NotDeleteAll", "NotInsertAll", "NotUpdateAll", "NotModify", "notDeleteAll", "notInsertAll", "notUpdateAll", "notModify");

@Test
void testName(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SELECT_FROM_FOO);

Expand All @@ -155,7 +171,7 @@ void testName(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
void testInnerJoin(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SELECT_INNER_JOIN);
assertEquals(SELECT_INNER_JOIN_EXPECTED, result);
Expand All @@ -165,7 +181,7 @@ void testInnerJoin(@InjectService SqlGuardFactory sqlGuardFactory) throws Except
void testInnerJoin1(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SELECT_INNER_JOIN_C_D);

Expand All @@ -176,7 +192,7 @@ void testInnerJoin1(@InjectService SqlGuardFactory sqlGuardFactory) throws Excep
void testInnerJoin2(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SELECT_INNER_JOIN_D);

Expand All @@ -187,7 +203,7 @@ void testInnerJoin2(@InjectService SqlGuardFactory sqlGuardFactory) throws Excep
void testTripleSelect(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(TRIPLE_SELECT_SQL);

Expand All @@ -198,7 +214,7 @@ void testTripleSelect(@InjectService SqlGuardFactory sqlGuardFactory) throws Exc
void testWhere(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SQL_WITH_IN);

Expand All @@ -209,7 +225,7 @@ void testWhere(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception
void testAdditionalColumn(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SQL_WITH_CUSTOM_COLUMN);

Expand All @@ -220,7 +236,7 @@ void testAdditionalColumn(@InjectService SqlGuardFactory sqlGuardFactory) throws
void testUndefinedTable(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {

DatabaseCatalog databaseCatalog = schemaWithTwoTableTwoCol();
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

assertThrows(UnresolvableObjectsGuardException.class, () -> guard.guard(SQL_WITH_WRONG_TABLE));

Expand All @@ -230,7 +246,7 @@ void testUndefinedTable(@InjectService SqlGuardFactory sqlGuardFactory) throws E
void test(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {
DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

RuntimeException thrown = assertThrows(RuntimeException.class, () -> guard.guard(SIMPLE_SQL_WITH_WRONG_TABLE));
assertEquals(TABLE_FOO1_DOES_NOT_EXIST_IN_THE_GIVEN_SCHEMA_SCH, thrown.getMessage());
Expand All @@ -241,7 +257,7 @@ void testGroup(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception

DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SQL_WITH_GROUP);

Expand All @@ -253,7 +269,8 @@ void testGroupAggregation(@InjectService SqlGuardFactory sqlGuardFactory) throws

DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, AGGREGATIONS);


for (String agg : AGGREGATIONS) {
String result = guard.guard(String.format(SQL_WITH_AGG, agg));
Expand Down Expand Up @@ -281,12 +298,102 @@ void testGroupAggregation(@InjectService SqlGuardFactory sqlGuardFactory) throws
}
}

@Test
void testAllowedFunctions(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {

DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, ALLOWED_FUNCTIONS);
for (String fun : ALLOWED_FUNCTIONS) {
String result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_WHERE_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_HAVING_EXPECTED, fun), result);
}
//allowed all
guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of(".*"));
for (String fun : ALLOWED_FUNCTIONS) {
String result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_WHERE_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_HAVING_EXPECTED, fun), result);
}
guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of("Delete.*", "Insert.*", "UpdateAll", "Modify.*", "delete.*", "insert.*", "update.*", "modify"));
for (String fun : ALLOWED_FUNCTIONS) {
String result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_WHERE_EXPECTED, fun), result);

result = guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_HAVING_EXPECTED, fun), result);
}
}

@Test
void testDeleteAllFunctionsNotAllowed(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {

DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();
//all function not allowed
final SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());
for (String fun : ALLOWED_FUNCTIONS) {
assertThrows(GuardException.class, () -> guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun)));
assertThrows(GuardException.class, () -> guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun)));
assertThrows(GuardException.class, () -> guard.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun)));
}
//all functions with wrong names are allowed only . all good functions are not allowed
final SqlGuard guard1 = sqlGuardFactory.create("", SCH, databaseCatalog, List.of("Dalete.*", "Iinsert.*", "UupdateAll", "Moodify.*", "ddelete.*", "insertt.*", "uppdate.*", "moodify"));
for (String fun : ALLOWED_FUNCTIONS) {
assertThrows(GuardException.class, () -> guard1.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun)));
assertThrows(GuardException.class, () -> guard1.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun)));
assertThrows(GuardException.class, () -> guard1.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun)));
}
//all functions with wrong names are allowed only . all good functions are not allowed
final SqlGuard guard2 = sqlGuardFactory.create("", SCH, databaseCatalog, ALLOWED_FUNCTIONS);
for (String fun : NOT_ALLOWED_FUNCTIONS) {
assertThrows(GuardException.class, () -> guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun)));
assertThrows(GuardException.class, () -> guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun)));
assertThrows(GuardException.class, () -> guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun)));
}
for (String fun : ALLOWED_FUNCTIONS) {
String result = guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION_EXPECTED, fun), result);

result = guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_WHERE, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_WHERE_EXPECTED, fun), result);

result = guard2.guard(String.format(SQL_WITH_ALLOWED_FUNCTION_IN_HAVING, fun));

assertEquals(String.format(SQL_WITH_ALLOWED_FUNCTION__IN_HAVING_EXPECTED, fun), result);
}
}

@Test
void testFunctions(@InjectService SqlGuardFactory sqlGuardFactory) throws Exception {

DatabaseCatalog databaseCatalog = schemaWithOneTable2Col();

SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog);
SqlGuard guard = sqlGuardFactory.create("", SCH, databaseCatalog, List.of());

String result = guard.guard(SQL_WITH_FUNCTION);

Expand Down
Loading