From 3a882e9d7a05497b8164845fc030f34e651ffc84 Mon Sep 17 00:00:00 2001 From: Konrad Dziedzic Date: Fri, 9 Feb 2024 18:10:43 +0100 Subject: [PATCH] Prevent view owner from being set when system security is used --- .../catalog/glue/TrinoGlueCatalog.java | 2 +- .../catalog/glue/TestTrinoGlueCatalog.java | 71 +++++++++++++++++-- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java index 419fd4da3968..4101b4af946b 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java @@ -1151,7 +1151,7 @@ public void createMaterializedView( TableInput materializedViewTableInput = getMaterializedViewTableInput( viewName.getTableName(), encodeMaterializedViewData(fromConnectorMaterializedViewDefinition(definition)), - session.getUser(), + isUsingSystemSecurity ? null : session.getUser(), createMaterializedViewProperties(session, storageMetadataLocation)); if (existing.isPresent()) { updateTable(viewName.getSchemaName(), materializedViewTableInput); diff --git a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/glue/TestTrinoGlueCatalog.java b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/glue/TestTrinoGlueCatalog.java index 7ed0bedca63e..55ab9868a14d 100644 --- a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/glue/TestTrinoGlueCatalog.java +++ b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/catalog/glue/TestTrinoGlueCatalog.java @@ -18,6 +18,7 @@ import com.amazonaws.services.glue.model.CreateDatabaseRequest; import com.amazonaws.services.glue.model.DatabaseInput; import com.amazonaws.services.glue.model.DeleteDatabaseRequest; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.airlift.log.Logger; import io.trino.filesystem.TrinoFileSystemFactory; @@ -31,7 +32,9 @@ import io.trino.plugin.iceberg.catalog.BaseTrinoCatalogTest; import io.trino.plugin.iceberg.catalog.TrinoCatalog; import io.trino.spi.connector.CatalogHandle; +import io.trino.spi.connector.ConnectorMaterializedViewDefinition; import io.trino.spi.connector.ConnectorMetadata; +import io.trino.spi.connector.MaterializedViewNotFoundException; import io.trino.spi.connector.SchemaTableName; import io.trino.spi.security.PrincipalType; import io.trino.spi.security.TrinoPrincipal; @@ -42,10 +45,17 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; +import java.util.Map; import java.util.Optional; import static io.airlift.json.JsonCodec.jsonCodec; import static io.trino.plugin.hive.HiveTestUtils.HDFS_FILE_SYSTEM_FACTORY; +import static io.trino.plugin.iceberg.IcebergFileFormat.PARQUET; +import static io.trino.plugin.iceberg.IcebergSchemaProperties.LOCATION_PROPERTY; +import static io.trino.plugin.iceberg.IcebergTableProperties.FILE_FORMAT_PROPERTY; +import static io.trino.plugin.iceberg.IcebergTableProperties.FORMAT_VERSION_PROPERTY; +import static io.trino.spi.type.IntegerType.INTEGER; import static io.trino.sql.planner.TestingPlannerContext.PLANNER_CONTEXT; import static io.trino.testing.TestingConnectorSession.SESSION; import static io.trino.testing.TestingNames.randomNameSuffix; @@ -61,24 +71,28 @@ public class TestTrinoGlueCatalog @Override protected TrinoCatalog createTrinoCatalog(boolean useUniqueTableLocations) { - TrinoFileSystemFactory fileSystemFactory = HDFS_FILE_SYSTEM_FACTORY; + return createGlueTrinoCatalog(useUniqueTableLocations, false); + } + + private TrinoCatalog createGlueTrinoCatalog(boolean useUniqueTableLocations, boolean useSystemSecurity) + { AWSGlueAsync glueClient = AWSGlueAsyncClientBuilder.defaultClient(); IcebergGlueCatalogConfig catalogConfig = new IcebergGlueCatalogConfig(); return new TrinoGlueCatalog( new CatalogName("catalog_name"), - fileSystemFactory, + HDFS_FILE_SYSTEM_FACTORY, new TestingTypeManager(), catalogConfig.isCacheTableMetadata(), new GlueIcebergTableOperationsProvider( TESTING_TYPE_MANAGER, catalogConfig, - fileSystemFactory, + HDFS_FILE_SYSTEM_FACTORY, new GlueMetastoreStats(), glueClient), "test", glueClient, new GlueMetastoreStats(), - false, + useSystemSecurity, Optional.empty(), useUniqueTableLocations, new IcebergConfig().isHideMaterializedViewStorageTable()); @@ -134,6 +148,55 @@ public void testNonLowercaseGlueDatabase() } } + @Test + public void testCreateMaterializedViewWithSystemSecurity() + { + TrinoCatalog glueTrinoCatalog = createGlueTrinoCatalog(false, true); + String namespace = "test_create_mv_" + randomNameSuffix(); + String table = "materialized_view_name"; + SchemaTableName viewName = new SchemaTableName(namespace, table); + Map properties = ImmutableMap.of(LOCATION_PROPERTY, "file:///tmp/a/path/"); + try { + glueTrinoCatalog.createNamespace(SESSION, namespace, properties, new TrinoPrincipal(PrincipalType.USER, SESSION.getUser())); + glueTrinoCatalog.createMaterializedView( + SESSION, + viewName, + new ConnectorMaterializedViewDefinition( + "CREATE * FROM tpch.tiny.nations", + Optional.empty(), + Optional.of("catalog_name"), + Optional.of("schema_name"), + ImmutableList.of(new ConnectorMaterializedViewDefinition.Column("col1", INTEGER.getTypeId(), Optional.empty())), + Optional.empty(), + Optional.empty(), + Optional.of("test_owner"), + ImmutableList.of()), + ImmutableMap.of(FILE_FORMAT_PROPERTY, PARQUET, FORMAT_VERSION_PROPERTY, 1), + false, + false); + List materializedViews = glueTrinoCatalog.listMaterializedViews(SESSION, Optional.of(namespace)); + assertThat(materializedViews.size()).isEqualTo(1); + assertThat(materializedViews.get(0).getTableName()).isEqualTo(table); + Optional returned = glueTrinoCatalog.getMaterializedView(SESSION, materializedViews.get(0)); + assertThat(returned).isPresent(); + assertThat(returned.get().getOwner()).isEmpty(); + } + finally { + try { + glueTrinoCatalog.dropMaterializedView(SESSION, viewName); + } + catch (MaterializedViewNotFoundException e) { + LOG.warn("Failed to clean up view: %s", viewName); + } + try { + glueTrinoCatalog.dropNamespace(SESSION, namespace); + } + catch (Exception e) { + LOG.warn("Failed to clean up namespace: %s", namespace); + } + } + } + @Test public void testDefaultLocation() throws IOException