Skip to content

Commit

Permalink
Support null owner for connector views when using system security
Browse files Browse the repository at this point in the history
  • Loading branch information
dain committed Nov 19, 2021
1 parent f5bff8e commit 295da15
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public MaterializedViewDefinition(
this.properties = ImmutableMap.copyOf(requireNonNull(properties, "properties is null"));
}

public MaterializedViewDefinition(ConnectorMaterializedViewDefinition view)
public MaterializedViewDefinition(ConnectorMaterializedViewDefinition view, Identity runAsIdentity)
{
super(
view.getOriginalSql(),
Expand All @@ -57,7 +57,7 @@ public MaterializedViewDefinition(ConnectorMaterializedViewDefinition view)
.map(column -> new ViewColumn(column.getName(), column.getType()))
.collect(toImmutableList()),
view.getComment(),
Optional.of(Identity.ofUser(view.getOwner())));
Optional.of(runAsIdentity));
this.storageTable = view.getStorageTable();
this.properties = ImmutableMap.copyOf(view.getProperties());
}
Expand Down Expand Up @@ -101,18 +101,4 @@ public String toString()
.add("properties", properties)
.toString();
}

@Override
public MaterializedViewDefinition withOwner(Identity owner)
{
return new MaterializedViewDefinition(
getOriginalSql(),
getCatalog(),
getSchema(),
getColumns(),
getComment(),
owner,
storageTable,
properties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1357,18 +1357,18 @@ public boolean isView(Session session, QualifiedObjectName viewName)
@Override
public Optional<ViewDefinition> getView(Session session, QualifiedObjectName viewName)
{
Optional<ViewDefinition> view = getViewInternal(session, viewName);
if (view.isEmpty() || view.get().isRunAsInvoker() || isCatalogManagedSecurity(session, viewName.getCatalogName())) {
return view;
Optional<ConnectorViewDefinition> connectorView = getViewInternal(session, viewName);
if (connectorView.isEmpty() || connectorView.get().isRunAsInvoker() || isCatalogManagedSecurity(session, viewName.getCatalogName())) {
return connectorView.map(view -> new ViewDefinition(viewName, view));
}
Optional<Identity> runAsIdentity = systemSecurityMetadata.getViewRunAsIdentity(session, viewName.asCatalogSchemaTableName());
if (runAsIdentity.isEmpty()) {
return view;
}
return view.map(v -> v.withOwner(runAsIdentity.get()));

Identity runAsIdentity = systemSecurityMetadata.getViewRunAsIdentity(session, viewName.asCatalogSchemaTableName())
.or(() -> connectorView.get().getOwner().map(Identity::ofUser))
.orElseThrow(() -> new TrinoException(NOT_SUPPORTED, "Catalog does not support run-as DEFINER views: " + viewName));
return Optional.of(new ViewDefinition(viewName, connectorView.get(), runAsIdentity));
}

private Optional<ViewDefinition> getViewInternal(Session session, QualifiedObjectName viewName)
private Optional<ConnectorViewDefinition> getViewInternal(Session session, QualifiedObjectName viewName)
{
if (viewName.getCatalogName().isEmpty() || viewName.getSchemaName().isEmpty() || viewName.getObjectName().isEmpty()) {
// View cannot exist
Expand All @@ -1382,8 +1382,7 @@ private Optional<ViewDefinition> getViewInternal(Session session, QualifiedObjec
ConnectorMetadata metadata = catalogMetadata.getMetadataFor(catalogName);

ConnectorSession connectorSession = session.toConnectorSession(catalogName);
return metadata.getView(connectorSession, viewName.asSchemaTableName())
.map(view -> new ViewDefinition(viewName, view));
return metadata.getView(connectorSession, viewName.asSchemaTableName());
}
return Optional.empty();
}
Expand Down Expand Up @@ -1551,18 +1550,18 @@ public boolean isMaterializedView(Session session, QualifiedObjectName viewName)
@Override
public Optional<MaterializedViewDefinition> getMaterializedView(Session session, QualifiedObjectName viewName)
{
Optional<MaterializedViewDefinition> view = getMaterializedViewInternal(session, viewName);
if (view.isEmpty() || isCatalogManagedSecurity(session, viewName.getCatalogName())) {
return view;
Optional<ConnectorMaterializedViewDefinition> connectorView = getMaterializedViewInternal(session, viewName);
if (connectorView.isEmpty() || isCatalogManagedSecurity(session, viewName.getCatalogName())) {
return connectorView.map(view -> new MaterializedViewDefinition(view, Identity.ofUser(view.getOwner())));
}
Optional<Identity> runAsIdentity = systemSecurityMetadata.getViewRunAsIdentity(session, viewName.asCatalogSchemaTableName());
if (runAsIdentity.isEmpty()) {
return view;
}
return view.map(v -> v.withOwner(runAsIdentity.get()));

Identity runAsIdentity = systemSecurityMetadata.getViewRunAsIdentity(session, viewName.asCatalogSchemaTableName())
.or(() -> connectorView.get().getOwner().map(Identity::ofUser))
.orElseThrow(() -> new TrinoException(NOT_SUPPORTED, "Materialized view does not have an owner: " + viewName));
return Optional.of(new MaterializedViewDefinition(connectorView.get(), runAsIdentity));
}

private Optional<MaterializedViewDefinition> getMaterializedViewInternal(Session session, QualifiedObjectName viewName)
private Optional<ConnectorMaterializedViewDefinition> getMaterializedViewInternal(Session session, QualifiedObjectName viewName)
{
if (viewName.getCatalogName().isEmpty() || viewName.getSchemaName().isEmpty() || viewName.getObjectName().isEmpty()) {
// View cannot exist
Expand All @@ -1576,8 +1575,7 @@ private Optional<MaterializedViewDefinition> getMaterializedViewInternal(Session
ConnectorMetadata metadata = catalogMetadata.getMetadataFor(catalogName);

ConnectorSession connectorSession = session.toConnectorSession(catalogName);
return metadata.getMaterializedView(connectorSession, viewName.asSchemaTableName())
.map(MaterializedViewDefinition::new);
return metadata.getMaterializedView(connectorSession, viewName.asSchemaTableName());
}
return Optional.empty();
}
Expand Down
33 changes: 17 additions & 16 deletions core/trino-main/src/main/java/io/trino/metadata/ViewDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static io.trino.spi.StandardErrorCode.INVALID_VIEW;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;

public class ViewDefinition
Expand Down Expand Up @@ -55,19 +54,32 @@ public ViewDefinition(
}

public ViewDefinition(QualifiedObjectName viewName, ConnectorViewDefinition view)
{
this(viewName, view, view.getOwner().map(Identity::ofUser));
}

public ViewDefinition(QualifiedObjectName viewName, ConnectorViewDefinition view, Identity runAsIdentityOverride)
{
this(viewName, view, Optional.of(runAsIdentityOverride));
}

private ViewDefinition(QualifiedObjectName viewName, ConnectorViewDefinition view, Optional<Identity> runAsIdentity)
{
requireNonNull(view, "view is null");
if (!view.isRunAsInvoker() && view.getOwner().isEmpty()) {
throw new TrinoException(INVALID_VIEW, format("Owner must be present in view '%s' with SECURITY DEFINER mode", viewName));
}
this.originalSql = view.getOriginalSql();
this.catalog = view.getCatalog();
this.schema = view.getSchema();
this.columns = view.getColumns().stream()
.map(column -> new ViewColumn(column.getName(), column.getType()))
.collect(toImmutableList());
this.comment = view.getComment();
this.runAsIdentity = view.getOwner().map(Identity::ofUser);
this.runAsIdentity = runAsIdentity;
if (view.isRunAsInvoker() && runAsIdentity.isPresent()) {
throw new TrinoException(INVALID_VIEW, "Run-as identity cannot be set for a run-as invoker view: " + viewName);
}
if (!view.isRunAsInvoker() && runAsIdentity.isEmpty()) {
throw new TrinoException(INVALID_VIEW, "Run-as identity must be set for a run-as definer view: " + viewName);
}
}

public String getOriginalSql()
Expand Down Expand Up @@ -131,15 +143,4 @@ public String toString()
.add("runAsIdentity", runAsIdentity.orElse(null))
.toString();
}

public ViewDefinition withOwner(Identity owner)
{
return new ViewDefinition(
originalSql,
catalog,
schema,
columns,
comment,
Optional.of(owner));
}
}

0 comments on commit 295da15

Please sign in to comment.