diff --git a/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java b/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java index 2842d2cae0b7..c87f58150e22 100644 --- a/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java +++ b/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java @@ -26,6 +26,7 @@ import io.trino.metadata.ViewPropertyManager; import io.trino.security.AccessControl; import io.trino.spi.security.Identity; +import io.trino.spi.security.ViewSecurity; import io.trino.sql.PlannerContext; import io.trino.sql.analyzer.Analysis; import io.trino.sql.analyzer.AnalyzerFactory; @@ -92,8 +93,9 @@ public ListenableFuture execute( Session session = stateMachine.getSession(); QualifiedObjectName name = createQualifiedObjectName(session, statement, statement.getName()); + Optional security = statement.getSecurity().map(sec -> ViewSecurity.valueOf(sec.name())); - accessControl.checkCanCreateView(session.toSecurityContext(), name); + accessControl.checkCanCreateView(session.toSecurityContext(), name, security); if (metadata.isMaterializedView(session, name)) { throw semanticException(TABLE_ALREADY_EXISTS, statement, "Materialized view already exists: '%s'", name); diff --git a/core/trino-main/src/main/java/io/trino/security/AccessControl.java b/core/trino-main/src/main/java/io/trino/security/AccessControl.java index 5a902e389fb9..5cf9c70e227c 100644 --- a/core/trino-main/src/main/java/io/trino/security/AccessControl.java +++ b/core/trino-main/src/main/java/io/trino/security/AccessControl.java @@ -29,6 +29,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -313,7 +314,7 @@ public interface AccessControl * * @throws AccessDeniedException if not allowed */ - void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName); + void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security); /** * Check if identity is allowed to rename the specified view. diff --git a/core/trino-main/src/main/java/io/trino/security/AccessControlManager.java b/core/trino-main/src/main/java/io/trino/security/AccessControlManager.java index 32e39b710602..5e4e4cec2016 100644 --- a/core/trino-main/src/main/java/io/trino/security/AccessControlManager.java +++ b/core/trino-main/src/main/java/io/trino/security/AccessControlManager.java @@ -57,6 +57,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.transaction.TransactionId; import io.trino.transaction.TransactionManager; import jakarta.annotation.PreDestroy; @@ -771,16 +772,16 @@ public void checkCanUpdateTableColumns(SecurityContext securityContext, Qualifie } @Override - public void checkCanCreateView(SecurityContext securityContext, QualifiedObjectName viewName) + public void checkCanCreateView(SecurityContext securityContext, QualifiedObjectName viewName, Optional security) { requireNonNull(securityContext, "securityContext is null"); requireNonNull(viewName, "viewName is null"); checkCanAccessCatalog(securityContext, viewName.catalogName()); - systemAuthorizationCheck(control -> control.checkCanCreateView(securityContext.toSystemSecurityContext(), viewName.asCatalogSchemaTableName())); + systemAuthorizationCheck(control -> control.checkCanCreateView(securityContext.toSystemSecurityContext(), viewName.asCatalogSchemaTableName(), security)); - catalogAuthorizationCheck(viewName.catalogName(), securityContext, (control, context) -> control.checkCanCreateView(context, viewName.asSchemaTableName())); + catalogAuthorizationCheck(viewName.catalogName(), securityContext, (control, context) -> control.checkCanCreateView(context, viewName.asSchemaTableName(), security)); } @Override diff --git a/core/trino-main/src/main/java/io/trino/security/AllowAllAccessControl.java b/core/trino-main/src/main/java/io/trino/security/AllowAllAccessControl.java index d9475955683c..6a72c4b0e455 100644 --- a/core/trino-main/src/main/java/io/trino/security/AllowAllAccessControl.java +++ b/core/trino-main/src/main/java/io/trino/security/AllowAllAccessControl.java @@ -24,6 +24,7 @@ import io.trino.spi.security.Identity; import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -161,7 +162,7 @@ public void checkCanTruncateTable(SecurityContext context, QualifiedObjectName t public void checkCanUpdateTableColumns(SecurityContext context, QualifiedObjectName tableName, Set updatedColumnNames) {} @Override - public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName) {} + public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security) {} @Override public void checkCanRenameView(SecurityContext context, QualifiedObjectName viewName, QualifiedObjectName newViewName) {} diff --git a/core/trino-main/src/main/java/io/trino/security/DenyAllAccessControl.java b/core/trino-main/src/main/java/io/trino/security/DenyAllAccessControl.java index 662a5799c39f..de29e9df0a44 100644 --- a/core/trino-main/src/main/java/io/trino/security/DenyAllAccessControl.java +++ b/core/trino-main/src/main/java/io/trino/security/DenyAllAccessControl.java @@ -27,6 +27,7 @@ import io.trino.spi.security.Identity; import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -337,7 +338,7 @@ public void checkCanUpdateTableColumns(SecurityContext context, QualifiedObjectN } @Override - public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName) + public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security) { denyCreateView(viewName.toString()); } diff --git a/core/trino-main/src/main/java/io/trino/security/ForwardingAccessControl.java b/core/trino-main/src/main/java/io/trino/security/ForwardingAccessControl.java index ae0f98665fdf..9135f147c2d2 100644 --- a/core/trino-main/src/main/java/io/trino/security/ForwardingAccessControl.java +++ b/core/trino-main/src/main/java/io/trino/security/ForwardingAccessControl.java @@ -26,6 +26,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -279,9 +280,9 @@ public void checkCanUpdateTableColumns(SecurityContext context, QualifiedObjectN } @Override - public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName) + public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security) { - delegate().checkCanCreateView(context, viewName); + delegate().checkCanCreateView(context, viewName, security); } @Override diff --git a/core/trino-main/src/main/java/io/trino/security/InjectedConnectorAccessControl.java b/core/trino-main/src/main/java/io/trino/security/InjectedConnectorAccessControl.java index c5c8ccc5ec9f..fe3f97c78e37 100644 --- a/core/trino-main/src/main/java/io/trino/security/InjectedConnectorAccessControl.java +++ b/core/trino-main/src/main/java/io/trino/security/InjectedConnectorAccessControl.java @@ -29,6 +29,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -259,10 +260,10 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { checkArgument(context == null, "context must be null"); - accessControl.checkCanCreateView(securityContext, getQualifiedObjectName(viewName)); + accessControl.checkCanCreateView(securityContext, getQualifiedObjectName(viewName), security); } @Override diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java index 4138196025c8..3279690fa868 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java @@ -92,6 +92,7 @@ import io.trino.spi.security.GroupProvider; import io.trino.spi.security.Identity; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.ArrayType; import io.trino.spi.type.CharType; import io.trino.spi.type.DateType; @@ -1056,6 +1057,7 @@ protected Scope visitCreateTableAsSelect(CreateTableAsSelect node, Optional scope) { QualifiedObjectName viewName = createQualifiedObjectName(session, node, node.getName()); + Optional viewSecurity = node.getSecurity().map(security -> ViewSecurity.valueOf(security.name())); node.getQuery().getFunctions().stream().findFirst().ifPresent(function -> { throw semanticException(NOT_SUPPORTED, function, "Views cannot contain inline functions"); @@ -1066,7 +1068,7 @@ protected Scope visitCreateView(CreateView node, Optional scope) Scope queryScope = analyzer.analyze(node.getQuery()); - accessControl.checkCanCreateView(session.toSecurityContext(), viewName); + accessControl.checkCanCreateView(session.toSecurityContext(), viewName, viewSecurity); validateColumns(node, queryScope.getRelationType()); diff --git a/core/trino-main/src/main/java/io/trino/testing/TestingAccessControlManager.java b/core/trino-main/src/main/java/io/trino/testing/TestingAccessControlManager.java index 85775ebf8513..1cd37119c89a 100644 --- a/core/trino-main/src/main/java/io/trino/testing/TestingAccessControlManager.java +++ b/core/trino-main/src/main/java/io/trino/testing/TestingAccessControlManager.java @@ -31,6 +31,7 @@ import io.trino.spi.connector.SchemaTableName; import io.trino.spi.security.Identity; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.transaction.TransactionManager; import java.security.Principal; @@ -538,13 +539,13 @@ public void checkCanUpdateTableColumns(SecurityContext context, QualifiedObjectN } @Override - public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName) + public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security) { if (shouldDenyPrivilege(context.getIdentity().getUser(), viewName.objectName(), CREATE_VIEW)) { denyCreateView(viewName.toString()); } if (denyPrivileges.isEmpty()) { - super.checkCanCreateView(context, viewName); + super.checkCanCreateView(context, viewName, security); } } diff --git a/core/trino-main/src/main/java/io/trino/tracing/TracingAccessControl.java b/core/trino-main/src/main/java/io/trino/tracing/TracingAccessControl.java index 092072c754ad..fa34e9fcaef7 100644 --- a/core/trino-main/src/main/java/io/trino/tracing/TracingAccessControl.java +++ b/core/trino-main/src/main/java/io/trino/tracing/TracingAccessControl.java @@ -32,6 +32,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -396,11 +397,11 @@ public void checkCanUpdateTableColumns(SecurityContext context, QualifiedObjectN } @Override - public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName) + public void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional security) { Span span = startSpan("checkCanCreateView"); try (var _ = scopedSpan(span)) { - delegate.checkCanCreateView(context, viewName); + delegate.checkCanCreateView(context, viewName, security); } } diff --git a/core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java b/core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java index a051103f6331..c88b109a51af 100644 --- a/core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java +++ b/core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java @@ -555,7 +555,7 @@ public void testViewOperations() SecurityContext bobContext = new SecurityContext(transactionId, bob, queryId, queryStart); SecurityContext nonAsciiContext = new SecurityContext(transactionId, nonAsciiUser, queryId, queryStart); - accessControlManager.checkCanCreateView(aliceContext, aliceView); + accessControlManager.checkCanCreateView(aliceContext, aliceView, Optional.empty()); accessControlManager.checkCanDropView(aliceContext, aliceView); accessControlManager.checkCanSelectFromColumns(aliceContext, aliceView, ImmutableSet.of()); accessControlManager.checkCanCreateViewWithSelectFromColumns(aliceContext, aliceTable, ImmutableSet.of()); @@ -564,7 +564,7 @@ public void testViewOperations() accessControlManager.checkCanGrantTablePrivilege(aliceContext, SELECT, aliceTable, new TrinoPrincipal(USER, "grantee"), true); accessControlManager.checkCanRevokeTablePrivilege(aliceContext, SELECT, aliceTable, new TrinoPrincipal(USER, "revokee"), true); - accessControlManager.checkCanCreateView(aliceContext, staffView); + accessControlManager.checkCanCreateView(aliceContext, staffView, Optional.empty()); accessControlManager.checkCanDropView(aliceContext, staffView); accessControlManager.checkCanSelectFromColumns(aliceContext, staffView, ImmutableSet.of()); accessControlManager.checkCanCreateViewWithSelectFromColumns(aliceContext, staffTable, ImmutableSet.of()); @@ -573,7 +573,7 @@ public void testViewOperations() accessControlManager.checkCanGrantTablePrivilege(aliceContext, SELECT, staffTable, new TrinoPrincipal(USER, "grantee"), true); accessControlManager.checkCanRevokeTablePrivilege(aliceContext, SELECT, staffTable, new TrinoPrincipal(USER, "revokee"), true); - assertThatThrownBy(() -> accessControlManager.checkCanCreateView(bobContext, aliceView)) + assertThatThrownBy(() -> accessControlManager.checkCanCreateView(bobContext, aliceView, Optional.empty())) .isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog alice-catalog"); assertThatThrownBy(() -> accessControlManager.checkCanDropView(bobContext, aliceView)) @@ -598,7 +598,7 @@ public void testViewOperations() .isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog alice-catalog"); - accessControlManager.checkCanCreateView(bobContext, staffView); + accessControlManager.checkCanCreateView(bobContext, staffView, Optional.empty()); accessControlManager.checkCanDropView(bobContext, staffView); accessControlManager.checkCanSelectFromColumns(bobContext, staffView, ImmutableSet.of()); accessControlManager.checkCanCreateViewWithSelectFromColumns(bobContext, staffTable, ImmutableSet.of()); @@ -607,7 +607,7 @@ public void testViewOperations() accessControlManager.checkCanGrantTablePrivilege(bobContext, SELECT, staffTable, new TrinoPrincipal(USER, "grantee"), true); accessControlManager.checkCanRevokeTablePrivilege(bobContext, SELECT, staffTable, new TrinoPrincipal(USER, "revokee"), true); - assertThatThrownBy(() -> accessControlManager.checkCanCreateView(nonAsciiContext, aliceView)) + assertThatThrownBy(() -> accessControlManager.checkCanCreateView(nonAsciiContext, aliceView, Optional.empty())) .isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog alice-catalog"); assertThatThrownBy(() -> accessControlManager.checkCanDropView(nonAsciiContext, aliceView)) @@ -632,7 +632,7 @@ public void testViewOperations() .isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog alice-catalog"); - assertThatThrownBy(() -> accessControlManager.checkCanCreateView(nonAsciiContext, staffView)) + assertThatThrownBy(() -> accessControlManager.checkCanCreateView(nonAsciiContext, staffView, Optional.empty())) .isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog staff-catalog"); assertThatThrownBy(() -> accessControlManager.checkCanDropView(nonAsciiContext, staffView)) @@ -675,7 +675,7 @@ public void testViewOperationsReadOnly() }); assertThatThrownBy(() -> transaction(transactionManager, metadata, accessControlManager).execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); })).isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot create view alice-catalog.schema.view"); @@ -695,7 +695,7 @@ public void testViewOperationsReadOnly() .hasMessage("Access Denied: Cannot revoke privilege SELECT on table alice-catalog.schema.table"); assertThatThrownBy(() -> transaction(transactionManager, metadata, accessControlManager).execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, bob, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, bob, queryId, queryStart), aliceView, Optional.empty()); })).isInstanceOf(AccessDeniedException.class) .hasMessage("Access Denied: Cannot access catalog alice-catalog"); } @@ -834,9 +834,9 @@ public void testRefreshing(@TempDir Path tempDir) transaction(transactionManager, metadata, accessControlManager) .execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); }); Files.copy(getResourcePath("security-config-file-with-unknown-rules.json"), configFile, REPLACE_EXISTING); @@ -844,14 +844,14 @@ public void testRefreshing(@TempDir Path tempDir) assertThatThrownBy(() -> transaction(transactionManager, metadata, accessControlManager) .execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); })) .isInstanceOf(UncheckedIOException.class) .hasMessageStartingWith("Failed to convert JSON tree node"); // test if file based cached control was not cached somewhere assertThatThrownBy(() -> transaction(transactionManager, metadata, accessControlManager) .execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); })) .isInstanceOf(UncheckedIOException.class) .hasMessageStartingWith("Failed to convert JSON tree node"); @@ -861,7 +861,7 @@ public void testRefreshing(@TempDir Path tempDir) transaction(transactionManager, metadata, accessControlManager) .execute(transactionId -> { - accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView); + accessControlManager.checkCanCreateView(new SecurityContext(transactionId, alice, queryId, queryStart), aliceView, Optional.empty()); }); } diff --git a/core/trino-spi/pom.xml b/core/trino-spi/pom.xml index 56a634fc7bf6..7ee4572e0fed 100644 --- a/core/trino-spi/pom.xml +++ b/core/trino-spi/pom.xml @@ -319,6 +319,18 @@ method long[] io.trino.spi.PageSorter::sort(java.util.List<io.trino.spi.type.Type>, java.util.List<io.trino.spi.Page>, java.util.List<java.lang.Integer>, java.util.List<io.trino.spi.connector.SortOrder>, int) method java.util.Iterator<io.trino.spi.Page> io.trino.spi.PageSorter::sort(java.util.List<io.trino.spi.type.Type>, java.util.List<io.trino.spi.Page>, java.util.List<java.lang.Integer>, java.util.List<io.trino.spi.connector.SortOrder>, int) + + java.method.numberOfParametersChanged + method void io.trino.spi.security.SystemAccessControl::checkCanCreateView(io.trino.spi.security.SystemSecurityContext, io.trino.spi.connector.CatalogSchemaTableName) + method void io.trino.spi.security.SystemAccessControl::checkCanCreateView(io.trino.spi.security.SystemSecurityContext, io.trino.spi.connector.CatalogSchemaTableName, java.util.Optional<io.trino.spi.security.ViewSecurity>) + We need to additionally pass the view security for more granular authorization + + + java.method.numberOfParametersChanged + method void io.trino.spi.connector.ConnectorAccessControl::checkCanCreateView(io.trino.spi.connector.ConnectorSecurityContext, io.trino.spi.connector.SchemaTableName) + method void io.trino.spi.connector.ConnectorAccessControl::checkCanCreateView(io.trino.spi.connector.ConnectorSecurityContext, io.trino.spi.connector.SchemaTableName, java.util.Optional<io.trino.spi.security.ViewSecurity>) + We need to additionally pass the view security for more granular authorization + diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorAccessControl.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorAccessControl.java index cdf149cb12cf..9b0f00245163 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorAccessControl.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorAccessControl.java @@ -18,6 +18,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -399,7 +400,7 @@ default void checkCanUpdateTableColumns(ConnectorSecurityContext context, Schema * * @throws io.trino.spi.security.AccessDeniedException if not allowed */ - default void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + default void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { denyCreateView(viewName.toString()); } diff --git a/core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java b/core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java index 342d90add4db..1f0f96b550a3 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java +++ b/core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java @@ -567,7 +567,7 @@ default void checkCanUpdateTableColumns(SystemSecurityContext securityContext, C * * @throws AccessDeniedException if not allowed */ - default void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) + default void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) { denyCreateView(view.toString()); } diff --git a/core/trino-spi/src/main/java/io/trino/spi/security/ViewSecurity.java b/core/trino-spi/src/main/java/io/trino/spi/security/ViewSecurity.java new file mode 100644 index 000000000000..cdc2708ea147 --- /dev/null +++ b/core/trino-spi/src/main/java/io/trino/spi/security/ViewSecurity.java @@ -0,0 +1,18 @@ +/* + * Licensed 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 io.trino.spi.security; + +public enum ViewSecurity { + INVOKER, DEFINER +} diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorAccessControl.java index e38b048da9ef..4edbb5dfbe38 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorAccessControl.java @@ -24,6 +24,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -279,10 +280,10 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { try (ThreadContextClassLoader _ = new ThreadContextClassLoader(classLoader)) { - delegate.checkCanCreateView(context, viewName); + delegate.checkCanCreateView(context, viewName, security); } } diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllAccessControl.java index 31c894511961..6dfce96cacab 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllAccessControl.java @@ -24,6 +24,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -131,7 +132,7 @@ public void checkCanTruncateTable(ConnectorSecurityContext context, SchemaTableN public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaTableName tableName, Set updatedColumnNames) {} @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) {} + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) {} @Override public void checkCanRenameView(ConnectorSecurityContext context, SchemaTableName viewName, SchemaTableName newViewName) {} diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java index 1626aab7069a..bc8222f7c176 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java @@ -32,6 +32,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.security.Principal; @@ -219,7 +220,7 @@ public void checkCanTruncateTable(SystemSecurityContext context, CatalogSchemaTa public void checkCanUpdateTableColumns(SystemSecurityContext securityContext, CatalogSchemaTableName table, Set updatedColumnNames) {} @Override - public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) {} + public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) {} @Override public void checkCanRenameView(SystemSecurityContext context, CatalogSchemaTableName view, CatalogSchemaTableName newView) {} diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedAccessControl.java index 7756876a0d7c..6d820cbee95f 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedAccessControl.java @@ -30,6 +30,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -436,7 +437,7 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { // check if user will be an owner of the view after creation if (!checkTablePermission(context, viewName, OWNERSHIP)) { diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedSystemAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedSystemAccessControl.java index c6ac33b94726..d0e9d37a70d9 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedSystemAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedSystemAccessControl.java @@ -39,6 +39,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.security.Principal; @@ -703,7 +704,7 @@ public void checkCanUpdateTableColumns(SystemSecurityContext context, CatalogSch } @Override - public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) + public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) { // check if user will be an owner of the view after creation if (!checkTablePermission(context, view, OWNERSHIP)) { diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingConnectorAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingConnectorAccessControl.java index 61e59f1c5ea4..76bac4085078 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingConnectorAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingConnectorAccessControl.java @@ -22,6 +22,7 @@ import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -225,9 +226,9 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { - delegate().checkCanCreateView(context, viewName); + delegate().checkCanCreateView(context, viewName, security); } @Override diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingSystemAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingSystemAccessControl.java index 0e72b1e8cf1a..d9cd76a77eca 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingSystemAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingSystemAccessControl.java @@ -29,6 +29,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.security.Principal; @@ -318,9 +319,9 @@ public void checkCanUpdateTableColumns(SystemSecurityContext context, CatalogSch } @Override - public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) + public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) { - delegate().checkCanCreateView(context, view); + delegate().checkCanCreateView(context, view, security); } @Override diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ReadOnlyAccessControl.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ReadOnlyAccessControl.java index 999570110eab..53a664e2e41e 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ReadOnlyAccessControl.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ReadOnlyAccessControl.java @@ -19,6 +19,7 @@ import io.trino.spi.function.SchemaFunctionName; import io.trino.spi.security.Privilege; import io.trino.spi.security.TrinoPrincipal; +import io.trino.spi.security.ViewSecurity; import java.util.Map; import java.util.Optional; @@ -172,7 +173,7 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { denyCreateView(viewName.toString()); } diff --git a/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/security/BaseFileBasedSystemAccessControlTest.java b/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/security/BaseFileBasedSystemAccessControlTest.java index 201c9d3ab804..1979fb735f72 100644 --- a/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/security/BaseFileBasedSystemAccessControlTest.java +++ b/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/security/BaseFileBasedSystemAccessControlTest.java @@ -151,24 +151,24 @@ public void testRefreshing(@TempDir Path tempDir) "security.refresh-period", "1ms")); SystemSecurityContext alice = new SystemSecurityContext(BaseFileBasedSystemAccessControlTest.alice, queryId, queryStart); - accessControl.checkCanCreateView(alice, aliceView); - accessControl.checkCanCreateView(alice, aliceView); - accessControl.checkCanCreateView(alice, aliceView); + accessControl.checkCanCreateView(alice, aliceView, Optional.empty()); + accessControl.checkCanCreateView(alice, aliceView, Optional.empty()); + accessControl.checkCanCreateView(alice, aliceView, Optional.empty()); Files.copy(getResourcePath("file-based-system-security-config-file-with-unknown-rules.json"), configFile, REPLACE_EXISTING); sleep(2); - assertThatThrownBy(() -> accessControl.checkCanCreateView(alice, aliceView)) + assertThatThrownBy(() -> accessControl.checkCanCreateView(alice, aliceView, Optional.empty())) .hasMessageContaining("Failed to convert JSON tree node"); // test if file based cached control was not cached somewhere - assertThatThrownBy(() -> accessControl.checkCanCreateView(alice, aliceView)) + assertThatThrownBy(() -> accessControl.checkCanCreateView(alice, aliceView, Optional.empty())) .hasMessageContaining("Failed to convert JSON tree node"); Files.copy(getResourcePath("file-based-system-catalog.json"), configFile, REPLACE_EXISTING); sleep(2); - accessControl.checkCanCreateView(alice, aliceView); + accessControl.checkCanCreateView(alice, aliceView, Optional.empty()); } @Test diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/security/SqlStandardAccessControl.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/security/SqlStandardAccessControl.java index 290fd373e1b6..ed4753ee5604 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/security/SqlStandardAccessControl.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/security/SqlStandardAccessControl.java @@ -36,6 +36,7 @@ import io.trino.spi.security.RoleGrant; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import java.util.List; @@ -373,7 +374,7 @@ public void checkCanUpdateTableColumns(ConnectorSecurityContext context, SchemaT } @Override - public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName) + public void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional security) { if (!isDatabaseOwner(context, viewName.getSchemaName())) { denyCreateView(viewName.toString()); diff --git a/plugin/trino-opa/src/main/java/io/trino/plugin/opa/OpaAccessControl.java b/plugin/trino-opa/src/main/java/io/trino/plugin/opa/OpaAccessControl.java index 046a812c2c8c..8e969c2a1096 100644 --- a/plugin/trino-opa/src/main/java/io/trino/plugin/opa/OpaAccessControl.java +++ b/plugin/trino-opa/src/main/java/io/trino/plugin/opa/OpaAccessControl.java @@ -45,6 +45,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import java.security.Principal; import java.util.Collection; @@ -465,9 +466,9 @@ public void checkCanUpdateTableColumns(SystemSecurityContext securityContext, Ca } @Override - public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) + public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) { - checkTableOperation(context, "CreateView", view, AccessDeniedException::denyCreateView); + checkViewOperation(context, "CreateView", view, security, AccessDeniedException::denyCreateView); } @Override @@ -779,6 +780,17 @@ private void checkTableAndColumnsOperation(SystemSecurityContext context, String OpaQueryInputResource.builder().table(new TrinoTable(table).withColumns(columns)).build()); } + private void checkViewOperation(SystemSecurityContext context, String actionName, CatalogSchemaTableName view, Optional security, Consumer deny) + { + OpaQueryInputResource.Builder opaQueryInputResourceBuilder = OpaQueryInputResource.builder().table(new TrinoTable(view)); + security.ifPresent(opaQueryInputResourceBuilder::security); + opaHighLevelClient.queryAndEnforce( + buildQueryContext(context), + actionName, + () -> deny.accept(view.toString()), + opaQueryInputResourceBuilder.build()); + } + private void enforcePermissionManagementOperation(Consumer deny, T arg) { if (!allowPermissionManagementOperations) { diff --git a/plugin/trino-opa/src/main/java/io/trino/plugin/opa/schema/OpaQueryInputResource.java b/plugin/trino-opa/src/main/java/io/trino/plugin/opa/schema/OpaQueryInputResource.java index a4bc45525003..36a602573269 100644 --- a/plugin/trino-opa/src/main/java/io/trino/plugin/opa/schema/OpaQueryInputResource.java +++ b/plugin/trino-opa/src/main/java/io/trino/plugin/opa/schema/OpaQueryInputResource.java @@ -14,6 +14,7 @@ package io.trino.plugin.opa.schema; import com.fasterxml.jackson.annotation.JsonInclude; +import io.trino.spi.security.ViewSecurity; import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; import static java.util.Objects.requireNonNull; @@ -27,7 +28,8 @@ public record OpaQueryInputResource( NamedEntity catalog, TrinoSchema schema, TrinoTable table, - TrinoColumn column) + TrinoColumn column, + ViewSecurity security) { public record NamedEntity(String name) { @@ -52,6 +54,7 @@ public static class Builder private TrinoTable table; private TrinoFunction function; private TrinoColumn column; + private ViewSecurity security; private Builder() {} @@ -109,6 +112,12 @@ public Builder column(TrinoColumn column) return this; } + public Builder security(ViewSecurity security) + { + this.security = security; + return this; + } + public OpaQueryInputResource build() { return new OpaQueryInputResource( @@ -119,7 +128,8 @@ public OpaQueryInputResource build() this.catalog, this.schema, this.table, - this.column); + this.column, + this.security); } } } diff --git a/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java b/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java index e2c795b4a92d..d19a381dffbf 100644 --- a/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java +++ b/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java @@ -35,6 +35,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.VarcharType; import org.junit.jupiter.api.Test; @@ -135,7 +136,6 @@ void testTableResourceActions() testTableResourceActions("InsertIntoTable", OpaAccessControl::checkCanInsertIntoTable); testTableResourceActions("DeleteFromTable", OpaAccessControl::checkCanDeleteFromTable); testTableResourceActions("TruncateTable", OpaAccessControl::checkCanTruncateTable); - testTableResourceActions("CreateView", OpaAccessControl::checkCanCreateView); testTableResourceActions("DropView", OpaAccessControl::checkCanDropView); testTableResourceActions("RefreshMaterializedView", OpaAccessControl::checkCanRefreshMaterializedView); testTableResourceActions("DropMaterializedView", OpaAccessControl::checkCanDropMaterializedView); @@ -210,6 +210,59 @@ private void testTableWithPropertiesActions( assertAccessControlMethodBehaviour(wrappedMethod, ImmutableSet.of(expectedRequest)); } + @Test + public void testCreateViewWithoutSecurity() + { + CatalogSchemaTableName viewName = new CatalogSchemaTableName("my_catalog", "my_schema", "my_view"); + ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper( + accessControl -> accessControl.checkCanCreateView(TEST_SECURITY_CONTEXT, viewName, Optional.empty())); + String expectedRequest = + """ + { + "operation": "CreateView", + "resource": { + "table": { + "catalogName": "%s", + "schemaName": "%s", + "tableName": "%s" + } + } + } + """.formatted( + viewName.getCatalogName(), + viewName.getSchemaTableName().getSchemaName(), + viewName.getSchemaTableName().getTableName()); + assertAccessControlMethodBehaviour(wrappedMethod, ImmutableSet.of(expectedRequest)); + } + + @Test + public void testCreateViewWithInvokerSecurity() + { + CatalogSchemaTableName viewName = new CatalogSchemaTableName("my_catalog", "my_schema", "my_view"); + Optional security = Optional.of(ViewSecurity.INVOKER); + ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper( + accessControl -> accessControl.checkCanCreateView(TEST_SECURITY_CONTEXT, viewName, security)); + String expectedRequest = + """ + { + "operation": "CreateView", + "resource": { + "table": { + "catalogName": "%s", + "schemaName": "%s", + "tableName": "%s" + }, + "security": "%s" + } + } + """.formatted( + viewName.getCatalogName(), + viewName.getSchemaTableName().getSchemaName(), + viewName.getSchemaTableName().getTableName(), + security.get()); + assertAccessControlMethodBehaviour(wrappedMethod, ImmutableSet.of(expectedRequest)); + } + @Test void testIdentityResourceActions() { diff --git a/plugin/trino-ranger/src/main/java/io/trino/plugin/ranger/RangerSystemAccessControl.java b/plugin/trino-ranger/src/main/java/io/trino/plugin/ranger/RangerSystemAccessControl.java index 8be22e9fa8b4..d79c1dbbd1c3 100644 --- a/plugin/trino-ranger/src/main/java/io/trino/plugin/ranger/RangerSystemAccessControl.java +++ b/plugin/trino-ranger/src/main/java/io/trino/plugin/ranger/RangerSystemAccessControl.java @@ -31,6 +31,7 @@ import io.trino.spi.security.SystemSecurityContext; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.security.ViewExpression; +import io.trino.spi.security.ViewSecurity; import io.trino.spi.type.Type; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; @@ -558,7 +559,7 @@ public Set filterColumns(SystemSecurityContext context, CatalogSchemaTab } @Override - public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view) + public void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional security) { if (!hasPermission(createTableResource(view), context, CREATE, "CreateView")) { denyCreateView(view.getSchemaTableName().getTableName()); diff --git a/plugin/trino-ranger/src/test/java/io/trino/plugin/ranger/TestRangerSystemAccessControl.java b/plugin/trino-ranger/src/test/java/io/trino/plugin/ranger/TestRangerSystemAccessControl.java index 220020a5130f..ed12ead3b613 100644 --- a/plugin/trino-ranger/src/test/java/io/trino/plugin/ranger/TestRangerSystemAccessControl.java +++ b/plugin/trino-ranger/src/test/java/io/trino/plugin/ranger/TestRangerSystemAccessControl.java @@ -231,7 +231,7 @@ void testViewOperations() { CatalogSchemaTableName newViewName = new CatalogSchemaTableName(VIEW_ALICE_SCH1_VW1.getCatalogName(), VIEW_ALICE_SCH1_VW1.getSchemaTableName().getSchemaName(), "new-view"); - accessControlManager.checkCanCreateView(context(ALICE), VIEW_ALICE_SCH1_VW1); + accessControlManager.checkCanCreateView(context(ALICE), VIEW_ALICE_SCH1_VW1, Optional.empty()); accessControlManager.checkCanDropView(context(ALICE), VIEW_ALICE_SCH1_VW1); accessControlManager.checkCanRenameView(context(ALICE), VIEW_ALICE_SCH1_VW1, newViewName); accessControlManager.checkCanSetViewAuthorization(context(ALICE), VIEW_ALICE_SCH1_VW1, new TrinoPrincipal(USER, "user")); @@ -239,7 +239,7 @@ void testViewOperations() accessControlManager.checkCanSetViewAuthorization(context(ALICE), VIEW_ALICE_SCH1_VW1, new TrinoPrincipal(USER, "user")); accessControlManager.checkCanSetViewComment(context(ALICE), VIEW_ALICE_SCH1_VW1); - assertThatThrownBy(() -> accessControlManager.checkCanCreateView(context(BOB), VIEW_ALICE_SCH1_VW1)).isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> accessControlManager.checkCanCreateView(context(BOB), VIEW_ALICE_SCH1_VW1, Optional.empty())).isInstanceOf(AccessDeniedException.class); assertThatThrownBy(() -> accessControlManager.checkCanDropView(context(BOB), VIEW_ALICE_SCH1_VW1)).isInstanceOf(AccessDeniedException.class); assertThatThrownBy(() -> accessControlManager.checkCanRenameView(context(BOB), VIEW_ALICE_SCH1_VW1, newViewName)).isInstanceOf(AccessDeniedException.class); assertThatThrownBy(() -> accessControlManager.checkCanSetViewAuthorization(context(BOB), VIEW_ALICE_SCH1_VW1, new TrinoPrincipal(USER, "user"))).isInstanceOf(AccessDeniedException.class);