Skip to content

Conversation

sbernauer
Copy link
Member

@sbernauer sbernauer commented Oct 21, 2025

Description

When creating views you can define two security modes: Invoker and definer, see the docs

We only want to allow views with invoker security using OPA authorization.
For that to work we need to pass the information of the view security to OPA, what exactly is what this PR does.
Going forward other authorizers (e.g. file based or Ranger) can also profit from this information.

Additional context and related issues

First commit does the SPI change.
Second commit uses the new attribute in the OPA authorizer.

Release notes

( ) This is not user-visible or is docs only, and no release notes are required.
( ) Release notes are required. Please propose a release note for me.
(x) Release notes are required, with the following suggested text:

# Open Policy Agent access control
* Add support for OPA `CreateView` authorization based on the view security mode

# SPI
* Add additional view security argument to `AccessControl.checkCanCreateView`

This is a breaking change for third-party plugins that implement the AccessControl interfaces. I guess we need to also mention that?

Summary by Sourcery

Extend view creation authorization to carry and enforce the SQL SECURITY mode by introducing a new ViewSecurity SPI parameter, propagating it through the engine and plugins, and integrating it into the OPA policy checks

New Features:

  • Introduce ViewSecurity enum to represent INVOKER and DEFINER modes
  • Extend AccessControl SPI checkCanCreateView to accept an Optional parameter
  • Capture and propagate view security mode in CreateViewTask and StatementAnalyzer

Enhancements:

  • Update OPA authorizer to include view security in policy queries and enforce invoker-security for CreateView
  • Propagate the new view security parameter through all forwarding and connector access control implementations
  • Make file-based and Ranger system access controls aware of the view security mode

Tests:

  • Add OPA plugin tests to verify CreateView requests with and without security mode

@cla-bot cla-bot bot added the cla-signed label Oct 21, 2025
Copy link

sourcery-ai bot commented Oct 21, 2025

Reviewer's Guide

This PR extends the view‐creation authorization API to include the view security mode, propagates that optional ViewSecurity parameter from the SQL analyzer through execution into the AccessControlManager, updates all forwarding/delegating and plugin‐toolkit access control implementations to accept and pass it along, integrates it into the OPA authorizer (including query builders and enforcement), and updates existing file‐based and Ranger tests to use the new signature.

ER diagram for OpaQueryInputResource including ViewSecurity

erDiagram
    OpaQueryInputResource {
        string catalog
        string schema
        string table
        string column
        enum security
    }
    ViewSecurity {
        enum INVOKER
        enum DEFINER
    }
    OpaQueryInputResource ||--o| ViewSecurity : has
Loading

Class diagram for updated AccessControl and related interfaces

classDiagram
    class AccessControl {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class ForwardingAccessControl {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class InjectedConnectorAccessControl {
        +void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional<ViewSecurity> security)
    }
    class TracingAccessControl {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class AllowAllAccessControl {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class DenyAllAccessControl {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class TestingAccessControlManager {
        +void checkCanCreateView(SecurityContext context, QualifiedObjectName viewName, Optional<ViewSecurity> security)
    }
    class ConnectorAccessControl {
        +void checkCanCreateView(ConnectorSecurityContext context, SchemaTableName viewName, Optional<ViewSecurity> security)
    }
    class SystemAccessControl {
        +void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional<ViewSecurity> security)
    }
    class ViewSecurity {
        <<enum>>
        INVOKER
        DEFINER
    }
    AccessControl <|.. ForwardingAccessControl
    AccessControl <|.. InjectedConnectorAccessControl
    AccessControl <|.. TracingAccessControl
    AccessControl <|.. AllowAllAccessControl
    AccessControl <|.. DenyAllAccessControl
    AccessControl <|.. TestingAccessControlManager
    ConnectorAccessControl <|.. SystemAccessControl
    AccessControl o-- ViewSecurity
    ConnectorAccessControl o-- ViewSecurity
    SystemAccessControl o-- ViewSecurity
Loading

Class diagram for OpaAccessControl and OpaQueryInputResource changes

classDiagram
    class OpaAccessControl {
        +void checkCanCreateView(SystemSecurityContext context, CatalogSchemaTableName view, Optional<ViewSecurity> security)
        -void checkViewOperation(SystemSecurityContext context, String actionName, CatalogSchemaTableName view, Optional<ViewSecurity> security, Consumer<String> deny)
    }
    class OpaQueryInputResource {
        +NamedEntity catalog
        +TrinoSchema schema
        +TrinoTable table
        +TrinoColumn column
        +ViewSecurity security
    }
    class Builder {
        +Builder security(ViewSecurity security)
        +OpaQueryInputResource build()
    }
    OpaAccessControl o-- OpaQueryInputResource
    OpaQueryInputResource o-- ViewSecurity
    OpaQueryInputResource o-- Builder
Loading

File-Level Changes

Change Details Files
Introduce ViewSecurity enum and extend SPI/AccessControl interfaces
  • Add ViewSecurity enum to spi
  • Change AccessControl.checkCanCreateView signature to accept Optional
  • Update SystemAccessControl default methods to include new parameter
core/trino-spi/src/main/java/io/trino/spi/security/ViewSecurity.java
core/trino-main/src/main/java/io/trino/security/AccessControl.java
core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java
Propagate view security from AST to execution
  • Extract Optional from CreateView AST in StatementAnalyzer
  • Pass security parameter to accessControl.checkCanCreateView in CreateViewTask
core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java
core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java
Forward view security in AccessControlManager
  • Modify AccessControlManager.checkCanCreateView to pass Optional to systemAuthorizationCheck
  • Extend catalogAuthorizationCheck calls to include security parameter
core/trino-main/src/main/java/io/trino/security/AccessControlManager.java
Update forwarding/delegating and toolkit access controls
  • Add Optional argument to all forwarding AccessControl and ConnectorAccessControl methods
  • Propagate security parameter in testing, tracing, classloader‐safe, and toolkit implementations
core/trino-main/src/main/java/io/trino/security/ForwardingAccessControl.java
core/trino-main/src/main/java/io/trino/security/InjectedConnectorAccessControl.java
core/trino-main/src/main/java/io/trino/testing/TestingAccessControlManager.java
core/trino-main/src/main/java/io/trino/tracing/TracingAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingConnectorAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ForwardingSystemAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/FileBasedSystemAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/ReadOnlyAccessControl.java
Integrate view security into OPA authorizer and tests
  • Implement checkViewOperation with security in OpaAccessControl
  • Extend OpaQueryInputResource builder to include security
  • Update checkCanCreateView to call new method
  • Add unit tests for CreateView with and without security parameter
plugin/trino-opa/src/main/java/io/trino/plugin/opa/OpaAccessControl.java
plugin/trino-opa/src/main/java/io/trino/plugin/opa/schema/OpaQueryInputResource.java
plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java
Update file-based and Ranger tests to new signature
  • Add Optional.empty() to all checkCanCreateView calls in tests
  • Adjust TestFileBasedSystemAccessControl and BaseFileBasedSystemAccessControlTest
  • Adjust TestRangerSystemAccessControl
core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java
lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/security/BaseFileBasedSystemAccessControlTest.java
plugin/trino-ranger/src/test/java/io/trino/plugin/ranger/TestRangerSystemAccessControl.java

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions github-actions bot added the hive Hive connector label Oct 21, 2025
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Add a test case covering the DEFINER security mode to ensure that OPA correctly rejects or handles views defined with DEFINER security as intended.
  • Since you’ve updated the AccessControl SPI signature, make sure to bump the SPI version and verify that existing connectors still compile and run against the new default method overload.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Add a test case covering the DEFINER security mode to ensure that OPA correctly rejects or handles views defined with DEFINER security as intended.
- Since you’ve updated the AccessControl SPI signature, make sure to bump the SPI version and verify that existing connectors still compile and run against the new default method overload.

## Individual Comments

### Comment 1
<location> `plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControl.java:239` </location>
<code_context>
+    }
+
+    @Test
+    public void testCreateViewWithInvokerSecurity()
+    {
+        CatalogSchemaTableName viewName = new CatalogSchemaTableName("my_catalog", "my_schema", "my_view");
</code_context>

<issue_to_address>
**suggestion (testing):** Missing test for CreateView with DEFINER security mode.

Please add a test for CreateView with DEFINER security to verify OPA authorizer behavior for both modes.

Suggested implementation:

```java
    @Test
    public void testCreateViewWithDefinerSecurity()
    {
        CatalogSchemaTableName viewName = new CatalogSchemaTableName("my_catalog", "my_schema", "my_view");
        ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper(
                accessControl -> accessControl.checkCanCreateViewWithSecurityMode(
                        TEST_SECURITY_CONTEXT, viewName, Optional.empty(), SecurityMode.DEFINER));
        String expectedRequest =
                """
                {
                    "operation": "CreateView",
                    "resource": {
                        "table": {
                            "catalogName": "%s",
                            "schemaName": "%s",
                            "tableName": "%s"
                        }
                    },
                    "securityMode": "DEFINER"
                }
                """.formatted(
                        viewName.getCatalogName(),
                        viewName.getSchemaTableName().getSchemaName(),
                        viewName.getSchemaTableName().getTableName());
        assertAccessControlMethodBehaviour(wrappedMethod, ImmutableSet.of(expectedRequest));
    }

    @Test

        ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper(
                accessControl -> accessControl.checkCanCreateView(TEST_SECURITY_CONTEXT, viewName, Optional.empty()));
        String expectedRequest =
                """
                {
                    "operation": "CreateView",
                    "resource": {
                        "table": {
                            "catalogName": "%s",
                            "schemaName": "%s",

```

1. If `checkCanCreateViewWithSecurityMode` or `SecurityMode.DEFINER` do not exist, you will need to implement or import them accordingly.
2. If the OPA authorizer expects a different field for security mode, adjust the `"securityMode": "DEFINER"` part of the expected request.
3. Ensure that the INVOKER test also includes `"securityMode": "INVOKER"` in its expected request for consistency.
</issue_to_address>

### Comment 2
<location> `core/trino-main/src/test/java/io/trino/security/TestFileBasedSystemAccessControl.java:558` </location>
<code_context>
                     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());
</code_context>

<issue_to_address>
**suggestion (testing):** Missing test coverage for CreateView with non-empty security mode.

Please add tests for CreateView using Optional.of(ViewSecurity.INVOKER) and Optional.of(ViewSecurity.DEFINER) to ensure correct behavior for both security modes.

Suggested implementation:

```java
                    accessControlManager.checkCanCreateView(aliceContext, aliceView, Optional.empty());
                    accessControlManager.checkCanCreateView(aliceContext, aliceView, Optional.of(ViewSecurity.INVOKER));
                    accessControlManager.checkCanCreateView(aliceContext, aliceView, Optional.of(ViewSecurity.DEFINER));

```

```java
                    accessControlManager.checkCanCreateView(aliceContext, staffView, Optional.empty());
                    accessControlManager.checkCanCreateView(aliceContext, staffView, Optional.of(ViewSecurity.INVOKER));
                    accessControlManager.checkCanCreateView(aliceContext, staffView, Optional.of(ViewSecurity.DEFINER));

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

}

@Test
public void testCreateViewWithInvokerSecurity()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Missing test for CreateView with DEFINER security mode.

Please add a test for CreateView with DEFINER security to verify OPA authorizer behavior for both modes.

Suggested implementation:

    @Test
    public void testCreateViewWithDefinerSecurity()
    {
        CatalogSchemaTableName viewName = new CatalogSchemaTableName("my_catalog", "my_schema", "my_view");
        ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper(
                accessControl -> accessControl.checkCanCreateViewWithSecurityMode(
                        TEST_SECURITY_CONTEXT, viewName, Optional.empty(), SecurityMode.DEFINER));
        String expectedRequest =
                """
                {
                    "operation": "CreateView",
                    "resource": {
                        "table": {
                            "catalogName": "%s",
                            "schemaName": "%s",
                            "tableName": "%s"
                        }
                    },
                    "securityMode": "DEFINER"
                }
                """.formatted(
                        viewName.getCatalogName(),
                        viewName.getSchemaTableName().getSchemaName(),
                        viewName.getSchemaTableName().getTableName());
        assertAccessControlMethodBehaviour(wrappedMethod, ImmutableSet.of(expectedRequest));
    }

    @Test

        ThrowingMethodWrapper wrappedMethod = new ThrowingMethodWrapper(
                accessControl -> accessControl.checkCanCreateView(TEST_SECURITY_CONTEXT, viewName, Optional.empty()));
        String expectedRequest =
                """
                {
                    "operation": "CreateView",
                    "resource": {
                        "table": {
                            "catalogName": "%s",
                            "schemaName": "%s",
  1. If checkCanCreateViewWithSecurityMode or SecurityMode.DEFINER do not exist, you will need to implement or import them accordingly.
  2. If the OPA authorizer expects a different field for security mode, adjust the "securityMode": "DEFINER" part of the expected request.
  3. Ensure that the INVOKER test also includes "securityMode": "INVOKER" in its expected request for consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed hive Hive connector

Development

Successfully merging this pull request may close these issues.

1 participant