This is an automated email from the ASF dual-hosted git repository.
gianm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 58ccdfa1dba feat: Directly produce Resource in NamedSchema. (#20254)
58ccdfa1dba is described below
commit 58ccdfa1dba22777917bbe960f63b9d4be4a0315
Author: Gian Merlino <[email protected]>
AuthorDate: Fri Sep 4 15:16:42 2026 -0700
feat: Directly produce Resource in NamedSchema. (#20254)
This patch is a follow-up to #20075 that changes things such that
NamedSchemas directly produce the Resources for authorization, rather
than relying on consumers to construct Resources themselves. This
simplifies the code and also makes it possible for NamedSchema to be
more flexible in the kinds of Resources they return. (They don't all
need to be the same type, or have names match the table.)
---
.../druid/sql/calcite/planner/PlannerContext.java | 11 +-
.../planner/SqlResourceCollectorShuttle.java | 8 +-
.../druid/sql/calcite/schema/DruidSchema.java | 4 +-
.../sql/calcite/schema/DruidSchemaCatalog.java | 15 ++-
.../schema/DruidSchemaCatalogProviderImpl.java | 8 +-
.../sql/calcite/schema/InformationSchema.java | 15 +--
.../druid/sql/calcite/schema/NamedDruidSchema.java | 5 +-
.../sql/calcite/schema/NamedLookupSchema.java | 11 ++
.../druid/sql/calcite/schema/NamedSchema.java | 11 +-
.../sql/calcite/schema/NamedSystemSchema.java | 5 +-
.../druid/sql/calcite/schema/NamedViewSchema.java | 5 +-
.../druid/sql/calcite/schema/SchemaUtils.java | 55 +++++++---
.../druid/sql/calcite/schema/SystemSchema.java | 8 +-
.../druid/sql/calcite/schema/ViewSchema.java | 2 +-
.../calcite/planner/CalcitePlannerModuleTest.java | 7 +-
.../sql/calcite/schema/NamedSystemSchemaTest.java | 5 +-
.../druid/sql/calcite/schema/SchemaUtilsTest.java | 114 +++++++++++++++++++++
17 files changed, 229 insertions(+), 60 deletions(-)
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
index fc03979d761..e9826af5dd4 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
@@ -52,8 +52,8 @@ import org.apache.druid.segment.join.JoinableFactoryWrapper;
import org.apache.druid.server.lookup.cache.LookupLoadingSpec;
import org.apache.druid.server.security.AuthenticationResult;
import org.apache.druid.server.security.AuthorizationResult;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceAction;
-import org.apache.druid.server.security.ResourceType;
import org.apache.druid.sql.calcite.expression.SqlOperatorConversion;
import
org.apache.druid.sql.calcite.expression.builtin.QueryLookupOperatorConversion;
import org.apache.druid.sql.calcite.rel.VirtualColumnRegistry;
@@ -326,13 +326,14 @@ public class PlannerContext
}
/**
- * Returns the {@link ResourceType} string for a particular resource (e.g.
table, view) located in a
- * particular schema. If null, there is no authorization associated with the
named resource.
+ * Returns the {@link Resource} to authorize against for a particular
resource (e.g. table, view) located in a
+ * particular schema. If null, there is no authorization associated with the
named resource (all authenticated
+ * users may access it).
*/
@Nullable
- public String getSchemaResourceType(String schema, String resourceName)
+ public Resource getSchemaResource(String schema, String resourceName)
{
- return rootSchema.getResourceType(schema, resourceName);
+ return rootSchema.getResource(schema, resourceName);
}
/**
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
index e2c5739dae8..279ac7476a7 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
@@ -46,7 +46,7 @@ import java.util.Set;
* <p>First, look for {@link SqlIdentifier} which correspond to a {@link
IdentifierNamespace}, where
* {@link SqlValidatorNamespace} is calcite-speak for sources of data and
{@link IdentifierNamespace} specifically are
* namespaces which are identified by a single variable, e.g. table names.
These are translated into resources
- * using {@link PlannerContext#getSchemaResourceType}.
+ * using {@link PlannerContext#getSchemaResource}.
*
* <p>Second, look for {@link AuthorizableOperator} and call {@link
AuthorizableOperator#computeResources}.
*
@@ -100,9 +100,9 @@ public class SqlResourceCollectorShuttle extends SqlShuttle
plannerContext.addLookupToLoad(resourceName);
}
- final String resourceType =
plannerContext.getSchemaResourceType(schema, resourceName);
- if (resourceType != null) {
- resourceActions.add(new ResourceAction(new Resource(resourceName,
resourceType), Action.READ));
+ final Resource resource = plannerContext.getSchemaResource(schema,
resourceName);
+ if (resource != null) {
+ resourceActions.add(new ResourceAction(resource, Action.READ));
}
} else if (qualifiedNameParts.size() > 2) {
// Don't expect to see more than 2 names (catalog?).
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchema.java
index 6048acf043f..a76e64c68ca 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchema.java
@@ -64,7 +64,7 @@ public class DruidSchema extends AbstractTableSchema
public Table getTable(String name)
{
if (authorizeTableVisibility
- && !SchemaUtils.isTableVisible(authorizerMapper, authenticationResult,
name, _ -> ResourceType.DATASOURCE)) {
+ && !SchemaUtils.isTableVisible(authorizerMapper, authenticationResult,
name, ResourceType.DATASOURCE)) {
// Do not return tables that are not supposed to be visible in this
schema.
return null;
}
@@ -97,7 +97,7 @@ public class DruidSchema extends AbstractTableSchema
authorizerMapper,
authenticationResult,
allTableNames,
- _ -> ResourceType.DATASOURCE
+ ResourceType.DATASOURCE
);
} else {
return allTableNames;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
index 3b169b7d098..cc13c452fe9 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
@@ -21,6 +21,7 @@ package org.apache.druid.sql.calcite.schema;
import com.google.common.base.Preconditions;
import org.apache.calcite.schema.SchemaPlus;
+import org.apache.druid.error.DruidException;
import org.apache.druid.server.security.Resource;
import javax.annotation.Nullable;
@@ -83,13 +84,21 @@ public class DruidSchemaCatalog
/**
* Given the name of a {@link NamedSchema} and the name of a table or
function that belongs to that schema, return
- * the appropriate value to use for {@link Resource#getType()} during
authorization
+ * the {@link Resource} to authorize against. Null means no authorization is
needed.
*/
@Nullable
- public String getResourceType(String schema, String resourceName)
+ public Resource getResource(String schema, String resourceName)
{
final NamedSchema namedSchema = namedSchemas.get(schema);
- return namedSchema == null ? null :
namedSchema.getSchemaResourceType(resourceName);
+ if (namedSchema != null) {
+ return namedSchema.getSchemaResource(resourceName);
+ } else if (InformationSchema.INFORMATION_SCHEMA_NAME.equals(schema)) {
+ // Everyone can read INFORMATION_SCHEMA.
+ return null;
+ } else {
+ // We shouldn't need to get a Resource for a schema that doesn't exist.
+ throw DruidException.defensive("No schema named[%s]", schema);
+ }
}
@Override
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalogProviderImpl.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalogProviderImpl.java
index a88702128a1..a46813815ff 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalogProviderImpl.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalogProviderImpl.java
@@ -36,8 +36,6 @@ import java.util.TreeMap;
@LazySingleton
public class DruidSchemaCatalogProviderImpl implements
DruidSchemaCatalogProvider
{
- private static final String INFORMATION_SCHEMA_NAME = "INFORMATION_SCHEMA";
-
private final Set<NamedSchema> namedSchemas;
private final Set<SchemaProvider> schemaProviders;
private final DruidOperatorTable operatorTable;
@@ -82,8 +80,8 @@ public class DruidSchemaCatalogProviderImpl implements
DruidSchemaCatalogProvide
}
}
- if (allSchemas.containsKey(INFORMATION_SCHEMA_NAME)) {
- throw new ISE("Cannot have schema named[%s]", INFORMATION_SCHEMA_NAME);
+ if (allSchemas.containsKey(InformationSchema.INFORMATION_SCHEMA_NAME)) {
+ throw new ISE("Cannot have schema named[%s]",
InformationSchema.INFORMATION_SCHEMA_NAME);
}
// Add allSchemas to the rootSchema.
@@ -95,7 +93,7 @@ public class DruidSchemaCatalogProviderImpl implements
DruidSchemaCatalogProvide
// One more schema to add: INFORMATION_SCHEMA.
rootSchema.add(
- INFORMATION_SCHEMA_NAME,
+ InformationSchema.INFORMATION_SCHEMA_NAME,
new InformationSchema(
schemaCatalog,
operatorTable,
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
index e4109a6a4b0..dcf02d7e860 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
@@ -45,6 +45,7 @@ import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.druid.java.util.emitter.EmittingLogger;
import org.apache.druid.server.security.AuthenticationResult;
import org.apache.druid.server.security.AuthorizerMapper;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.sql.calcite.planner.Calcites;
import org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.DruidTypeSystem;
@@ -171,13 +172,13 @@ public class InformationSchema extends AbstractSchema
return tableMap;
}
- private Set<String> getVisibleNames(final Iterable<String> allNames, final
Function<String, String> resourceTypeFn)
+ private Set<String> getVisibleNames(final Iterable<String> allNames, final
Function<String, Resource> resourceFn)
{
- return SchemaUtils.filterVisibleTables(
+ return SchemaUtils.filterVisibleResources(
authorizerMapper,
authenticationResult,
allNames,
- resourceTypeFn
+ resourceFn
);
}
@@ -249,11 +250,11 @@ public class InformationSchema extends AbstractSchema
final SchemaPlus subSchema =
rootSchema.getSubSchema(schemaName);
final Set<String> tableNames = getVisibleNames(
subSchema.tables().getNames(LikePattern.any()),
- tableName ->
rootSchema.getResourceType(subSchema.getName(), tableName)
+ tableName -> rootSchema.getResource(subSchema.getName(),
tableName)
);
final Set<String> functionNames = getVisibleNames(
subSchema.getFunctionNames(),
- tableName ->
rootSchema.getResourceType(subSchema.getName(), tableName)
+ tableName -> rootSchema.getResource(subSchema.getName(),
tableName)
);
return Iterables.filter(
@@ -349,11 +350,11 @@ public class InformationSchema extends AbstractSchema
final RelDataTypeFactory typeFactory = root.getTypeFactory();
final Set<String> tableNames = getVisibleNames(
subSchema.tables().getNames(LikePattern.any()),
- tableName ->
rootSchema.getResourceType(subSchema.getName(), tableName)
+ tableName -> rootSchema.getResource(subSchema.getName(),
tableName)
);
final Set<String> functionNames = getVisibleNames(
subSchema.getFunctionNames(),
- tableName ->
rootSchema.getResourceType(subSchema.getName(), tableName)
+ tableName -> rootSchema.getResource(subSchema.getName(),
tableName)
);
return Iterables.concat(
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
index bc0a791bbd9..bc6fa67bf13 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite.schema;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
/**
@@ -43,9 +44,9 @@ public class NamedDruidSchema implements NamedSchema
}
@Override
- public String getSchemaResourceType(String resourceName)
+ public Resource getSchemaResource(String resourceName)
{
- return ResourceType.DATASOURCE;
+ return new Resource(resourceName, ResourceType.DATASOURCE);
}
@Override
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
index e99c2ffab90..120a0e67458 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
@@ -22,6 +22,9 @@ package org.apache.druid.sql.calcite.schema;
import com.google.inject.Inject;
import org.apache.calcite.schema.Schema;
import org.apache.druid.guice.LazySingleton;
+import org.apache.druid.server.security.Resource;
+
+import javax.annotation.Nullable;
/**
* The schema for Druid lookup tables to be accessible via SQL.
@@ -45,6 +48,14 @@ public class NamedLookupSchema implements NamedSchema
return NAME;
}
+ @Nullable
+ @Override
+ public Resource getSchemaResource(String resourceName)
+ {
+ // No authorization for lookups.
+ return null;
+ }
+
@Override
public Schema getSchema()
{
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
index da951aa6273..a08bf1a7242 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite.schema;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.Resource;
import javax.annotation.Nullable;
@@ -35,15 +36,11 @@ public interface NamedSchema
String getSchemaName();
/**
- * For a given name of a table, function, etc of this schema, return the
value most appropriate to use for
- * {@link org.apache.druid.server.security.Resource#getType()} for the
resource, used during authorization. If this
- * method returns null then the resource does not need any authorization.
+ * For a given name of a table, function, etc of this schema, return {@link
Resource} to use
+ * during authorization. If this method returns null then the resource does
not need any authorization.
*/
@Nullable
- default String getSchemaResourceType(String resourceName)
- {
- return null;
- }
+ Resource getSchemaResource(String resourceName);
/**
* @return The Schema that Calcite should use.
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
index be206b9caa2..cd13ffc5e53 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite.schema;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
@@ -55,10 +56,10 @@ public class NamedSystemSchema implements NamedSchema
@Nullable
@Override
- public String getSchemaResourceType(String resourceName)
+ public Resource getSchemaResource(String resourceName)
{
if (plannerConfig.isAuthorizeSystemTablesDirectly()) {
- return ResourceType.SYSTEM_TABLE;
+ return new Resource(resourceName, ResourceType.SYSTEM_TABLE);
}
return null;
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
index 826d25ec248..65b9a2e3372 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite.schema;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
public class NamedViewSchema implements NamedSchema
@@ -39,9 +40,9 @@ public class NamedViewSchema implements NamedSchema
}
@Override
- public String getSchemaResourceType(String resourceName)
+ public Resource getSchemaResource(String resourceName)
{
- return ResourceType.VIEW;
+ return new Resource(resourceName, ResourceType.VIEW);
}
@Override
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SchemaUtils.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SchemaUtils.java
index 6e8202c8b06..4af7ca744bf 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SchemaUtils.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SchemaUtils.java
@@ -19,6 +19,7 @@
package org.apache.druid.sql.calcite.schema;
+import org.apache.druid.error.DruidException;
import org.apache.druid.server.security.Action;
import org.apache.druid.server.security.AuthenticationResult;
import org.apache.druid.server.security.AuthorizationUtils;
@@ -26,8 +27,10 @@ import org.apache.druid.server.security.AuthorizerMapper;
import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceAction;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -38,45 +41,73 @@ public class SchemaUtils
// No instantiation.
}
+ /**
+ * Returns whether a given table with resource type {@code resourceType}
should be visible.
+ */
public static boolean isTableVisible(
final AuthorizerMapper authorizerMapper,
final AuthenticationResult authenticationResult,
final String tableName,
- final Function<String, String> resourceTypeFn
+ final String resourceType
)
{
- return !filterVisibleTables(authorizerMapper, authenticationResult,
Set.of(tableName), resourceTypeFn).isEmpty();
+ return !filterVisibleTables(authorizerMapper, authenticationResult,
Set.of(tableName), resourceType).isEmpty();
}
+ /**
+ * Returns the set of visible table names, given tables with resource type
{@code resourceType}.
+ */
public static Set<String> filterVisibleTables(
final AuthorizerMapper authorizerMapper,
final AuthenticationResult authenticationResult,
final Iterable<String> tableNames,
- final Function<String, String> resourceTypeFn
+ final String resourceType
+ )
+ {
+ if (resourceType == null) {
+ throw DruidException.defensive("Null resource type not expected");
+ }
+
+ return filterVisibleResources(
+ authorizerMapper,
+ authenticationResult,
+ tableNames,
+ name -> new Resource(name, resourceType)
+ );
+ }
+
+ /**
+ * Like {@link #filterVisibleTables}, but each name is mapped to the {@link
Resource} to authorize against, which
+ * need not be named after the object itself. A null resource means the name
does not need authorization.
+ */
+ public static Set<String> filterVisibleResources(
+ final AuthorizerMapper authorizerMapper,
+ final AuthenticationResult authenticationResult,
+ final Iterable<String> names,
+ final Function<String, Resource> resourceFn
)
{
final Set<String> visibleNames = new LinkedHashSet<>();
- final Set<Resource> authorizableResources = new LinkedHashSet<>();
+ final Map<Resource, Set<String>> namesByResource = new LinkedHashMap<>();
- for (final String tableName : tableNames) {
- final String resourceType = resourceTypeFn.apply(tableName);
- if (resourceType == null) {
- // No ResourceType means this name does not need authorization. It's
always visible.
- visibleNames.add(tableName);
+ for (final String name : names) {
+ final Resource resource = resourceFn.apply(name);
+ if (resource == null) {
+ visibleNames.add(name);
} else {
- authorizableResources.add(new Resource(tableName, resourceType));
+ namesByResource.computeIfAbsent(resource, _ -> new
LinkedHashSet<>()).add(name);
}
}
final Iterable<Resource> authorizedResources =
AuthorizationUtils.filterAuthorizedResources(
authenticationResult,
- authorizableResources,
+ namesByResource.keySet(),
resource -> List.of(new ResourceAction(resource, Action.READ)),
authorizerMapper
);
for (final Resource resource : authorizedResources) {
- visibleNames.add(resource.getName());
+ visibleNames.addAll(namesByResource.get(resource));
}
return visibleNames;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java
index 8ccbcf19c81..885fc1ca352 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/SystemSchema.java
@@ -345,12 +345,12 @@ public class SystemSchema extends AbstractTableSchema
@Override
public Set<String> getTableNames()
{
- if (plannerConfig.isAuthorizeTableVisibility()) {
+ if (plannerConfig.isAuthorizeTableVisibility() &&
plannerConfig.isAuthorizeSystemTablesDirectly()) {
return SchemaUtils.filterVisibleTables(
authorizerMapper,
authenticationResult,
allTableNames,
- _ -> plannerConfig.isAuthorizeSystemTablesDirectly() ?
ResourceType.SYSTEM_TABLE : null
+ ResourceType.SYSTEM_TABLE
);
} else {
// sys table authorization is not enabled, so all sys tables are visible
to all users.
@@ -366,12 +366,12 @@ public class SystemSchema extends AbstractTableSchema
if (!allTableNames.contains(sysTableName)) {
// Short circuit that hides sys.queries if it is disabled server-wide.
return false;
- } else if (plannerConfig.isAuthorizeTableVisibility()) {
+ } else if (plannerConfig.isAuthorizeTableVisibility() &&
plannerConfig.isAuthorizeSystemTablesDirectly()) {
return SchemaUtils.isTableVisible(
authorizerMapper,
authenticationResult,
sysTableName,
- _ -> plannerConfig.isAuthorizeSystemTablesDirectly() ?
ResourceType.SYSTEM_TABLE : null
+ ResourceType.SYSTEM_TABLE
);
} else {
// sys table authorization is not enabled, so all sys tables are visible
to all users.
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/ViewSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/ViewSchema.java
index 9cbf0ac8e2e..9f4d77b6299 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/ViewSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/ViewSchema.java
@@ -72,7 +72,7 @@ public class ViewSchema extends AbstractSchema
authorizerMapper,
authenticationResult,
viewsMap.keySet(),
- _ -> ResourceType.VIEW
+ ResourceType.VIEW
);
} else {
visibleViews = viewsMap.keySet();
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
index 364881135ea..3808b18d0f4 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
@@ -42,6 +42,7 @@ import org.apache.druid.math.expr.ExprMacroTable;
import org.apache.druid.segment.join.JoinableFactoryWrapper;
import org.apache.druid.server.QueryLifecycleFactory;
import org.apache.druid.server.security.AuthorizerMapper;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
import org.apache.druid.sql.SqlStatementFactory;
import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
@@ -114,8 +115,10 @@ public class CalcitePlannerModuleTest extends
CalciteTestBase
EasyMock.expect(druidSchema2.getSchema()).andStubReturn(schema2);
EasyMock.expect(druidSchema1.getSchemaName()).andStubReturn(SCHEMA_1);
EasyMock.expect(druidSchema2.getSchemaName()).andStubReturn(SCHEMA_2);
-
EasyMock.expect(druidSchema1.getSchemaResourceType(EasyMock.anyString())).andStubReturn(ResourceType.DATASOURCE);
-
EasyMock.expect(druidSchema2.getSchemaResourceType(EasyMock.anyString())).andStubReturn("test");
+ EasyMock.expect(druidSchema1.getSchemaResource(EasyMock.anyString()))
+ .andStubReturn(new Resource("resource", ResourceType.DATASOURCE));
+ EasyMock.expect(druidSchema2.getSchemaResource(EasyMock.anyString()))
+ .andStubReturn(new Resource("resource", "test"));
EasyMock.replay(druidSchema1, druidSchema2);
aggregators = ImmutableSet.of();
operatorConversions = ImmutableSet.of();
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/NamedSystemSchemaTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/NamedSystemSchemaTest.java
index 9c80ea1dd08..7e7a11e8d6a 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/NamedSystemSchemaTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/NamedSystemSchemaTest.java
@@ -19,6 +19,7 @@
package org.apache.druid.sql.calcite.schema;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
@@ -63,7 +64,7 @@ public class NamedSystemSchemaTest extends CalciteTestBase
{
EasyMock.expect(plannerConfig.isAuthorizeSystemTablesDirectly()).andReturn(false).once();
EasyMock.replay(plannerConfig);
- Assertions.assertNull(target.getSchemaResourceType("servers"));
+ Assertions.assertNull(target.getSchemaResource("servers"));
EasyMock.verify(plannerConfig);
}
@@ -72,7 +73,7 @@ public class NamedSystemSchemaTest extends CalciteTestBase
{
EasyMock.expect(plannerConfig.isAuthorizeSystemTablesDirectly()).andReturn(true).once();
EasyMock.replay(plannerConfig);
- Assertions.assertEquals(ResourceType.SYSTEM_TABLE,
target.getSchemaResourceType("servers"));
+ Assertions.assertEquals(new Resource("servers",
ResourceType.SYSTEM_TABLE), target.getSchemaResource("servers"));
EasyMock.verify(plannerConfig);
}
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/SchemaUtilsTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/SchemaUtilsTest.java
new file mode 100644
index 00000000000..19af13e5bbc
--- /dev/null
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/schema/SchemaUtilsTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.schema;
+
+import org.apache.druid.server.security.Access;
+import org.apache.druid.server.security.AuthenticationResult;
+import org.apache.druid.server.security.Authorizer;
+import org.apache.druid.server.security.AuthorizerMapper;
+import org.apache.druid.server.security.Resource;
+import org.apache.druid.server.security.ResourceType;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Set;
+
+public class SchemaUtilsTest extends CalciteTestBase
+{
+ private static final String ALLOWED = "allowed";
+ private static final AuthenticationResult AUTH_RESULT =
+ new AuthenticationResult("someone", "authorizer", null, null);
+
+ private static final AuthorizerMapper AUTHORIZER_MAPPER = new
AuthorizerMapper(null)
+ {
+ @Override
+ public Authorizer getAuthorizer(String name)
+ {
+ return (authenticationResult, resource, action) ->
+ ALLOWED.equals(resource.getName()) ? Access.OK : Access.DENIED;
+ }
+ };
+
+ @Test
+ public void testFilterVisibleResourcesMapsManyNamesToOneResource()
+ {
+ final Resource resource = new Resource(ALLOWED, ResourceType.DATASOURCE);
+ Assertions.assertEquals(
+ Set.of("a", "b", "c"),
+ SchemaUtils.filterVisibleResources(
+ AUTHORIZER_MAPPER,
+ AUTH_RESULT,
+ List.of("a", "b", "c"),
+ _ -> resource
+ )
+ );
+ }
+
+ @Test
+ public void testFilterVisibleResourcesHidesNamesBehindADeniedResource()
+ {
+ final Resource resource = new Resource("denied", ResourceType.DATASOURCE);
+ Assertions.assertEquals(
+ Set.of(),
+ SchemaUtils.filterVisibleResources(
+ AUTHORIZER_MAPPER,
+ AUTH_RESULT,
+ List.of("a", "b"),
+ _ -> resource
+ )
+ );
+ }
+
+ @Test
+ public void testFilterVisibleResourcesAlwaysShowsNamesWithNoResource()
+ {
+ Assertions.assertEquals(
+ Set.of("a", "b"),
+ SchemaUtils.filterVisibleResources(AUTHORIZER_MAPPER, AUTH_RESULT,
List.of("a", "b"), _ -> null)
+ );
+ }
+
+ @Test
+ public void testFilterVisibleTablesAuthorizesOnEachOwnName()
+ {
+ Assertions.assertEquals(
+ Set.of(ALLOWED),
+ SchemaUtils.filterVisibleTables(
+ AUTHORIZER_MAPPER,
+ AUTH_RESULT,
+ List.of(ALLOWED, "other"),
+ ResourceType.DATASOURCE
+ )
+ );
+ }
+
+ @Test
+ public void testIsTableVisible()
+ {
+ Assertions.assertTrue(
+ SchemaUtils.isTableVisible(AUTHORIZER_MAPPER, AUTH_RESULT, ALLOWED,
ResourceType.DATASOURCE)
+ );
+ Assertions.assertFalse(
+ SchemaUtils.isTableVisible(AUTHORIZER_MAPPER, AUTH_RESULT, "other",
ResourceType.DATASOURCE)
+ );
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]