trino
Add generic SET AUTHORIZATION
#21794
Merged

Add generic SET AUTHORIZATION #21794

djsstarburst
djsstarburst351 days ago

This commit adds machinery to set the owner of arbitrary entities, by extending the syntax of
ALTER (SCHEMA | TABLE | VIEW) qualifiedName SET AUTHORIZATION to support arbitrary owningKinds in place of SCHEMA, TABLE or VIEW. Checks that a specific SET AUTHORIZATION is legal is done by AccessControl.checkCanSetEntityAuthorization, also defined by SystemAccessControl. Setting the owner is done by Metadata.setEntityAuthorization and
SystemSecurityMetadata.setEntityAuthorization.

Description

Additional context and related issues

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.
( ) Release notes are required, with the following suggested text:

# Section
* Fix some things. ({issue}`issuenumber`)
cla-bot cla-bot added cla-signed
djsstarburst djsstarburst force pushed 350 days ago
lozbrown
lozbrown345 days ago

Would that help with this issue?

#21450

djsstarburst
djsstarburst345 days ago

Would that help with this issue?

#21450

No, I don't think this change will help. Materialized views must have owners when they are created. Perhaps you could post to the Trino #troubleshooting Slack channel about this.

djsstarburst djsstarburst force pushed 345 days ago
lozbrown
lozbrown345 days ago (edited 345 days ago)

I did that some time ago but got no response

https://trinodb.slack.com/archives/CGB0QHWSW/p1712241258245569

djsstarburst djsstarburst force pushed 333 days ago
djsstarburst djsstarburst requested a review from martint martint 332 days ago
djsstarburst djsstarburst marked this pull request as ready for review 332 days ago
djsstarburst djsstarburst force pushed 317 days ago
github-actions
github-actions296 days ago

This pull request has gone a while without any activity. Tagging the Trino developer relations team: @bitsondatadev @colebow @mosabua

github-actions github-actions added stale
mosabua mosabua removed stale
mosabua mosabua added stale-ignore
mosabua
mosabua296 days ago

I assume you are still working on this @djsstarburst

djsstarburst
djsstarburst296 days ago

I assume you are still working on this @djsstarburst

Yes, @mosabua.

djsstarburst djsstarburst force pushed 256 days ago
djsstarburst djsstarburst force pushed 189 days ago
djsstarburst
djsstarburst189 days ago

Hi @martint. We discussed this PR, and you took a quick look at it last spring. I just brought it up-to-date with tip master.

Could you please take another look and see if it can be approved? Thanks!

dain dain added syntax-needs-review
dain
dain requested changes on 2024-10-18
dain181 days ago

I would like to take a different approach to this PR. Instead of retaining the existing set*Authorization we remove them entirelly. Then in the SPI we have default implementation of setEntityAuthorization we switch over the entities and call the exisitng methods. Then we mark the existing 3 methods as deprecated for removal. We would do the same thing for the security checks.

The main, notable, difference with the existing code would be that we no longer perform an existance check before doing the authorization assignment. I think that is ok. If we decide we want that later we can add a generic entitiy exists mehtod.

Conversation is marked as resolved
Show resolved
core/trino-grammar/src/main/antlr4/io/trino/grammar/sql/SqlBase.g4
dain181 days ago

I think we need MATERIALIZED VIEW in this list. I think we will also need to remove the MV version from the grammar (it is new)

djsstarburst147 days ago

Added.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/execution/SetAuthorizationTask.java
57 @Override
58 public String getName()
59 {
60
return "SET SCHEMA AUTHORIZATION";
dain150 days ago
Suggested change
return "SET SCHEMA AUTHORIZATION";
return "SET AUTHORIZATION";
djsstarburst147 days ago

Changed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/execution/SetAuthorizationTask.java
72 TrinoPrincipal principal = createPrincipal(statement.getPrincipal());
73
74 switch (statement.getOwnedEntityKind()) {
75
case "SCHEMA":
dain150 days ago

Split each case out to a separate method. This will help readability and it will improve stacktraces.

djsstarburst147 days ago

I've done so.

Conversation is marked as resolved
Show resolved
core/trino-parser/src/test/java/io/trino/sql/parser/TestSqlParser.java
3331 new SetViewAuthorization(
3330 new SetAuthorizationStatement(
33323331 location(1, 1),
3332
"TABLE",
dain150 days ago
Suggested change
"TABLE",
"VIEW",
dain150 days ago

Same for all of the calls in this method

djsstarburst147 days ago

Changed for all calls.

djsstarburst djsstarburst force pushed 147 days ago
djsstarburst djsstarburst force pushed to a39beacf 147 days ago
djsstarburst
djsstarburst147 days ago

I would like to take a different approach to this PR.

@dain - - I've tried to do what you suggested, and I've pushed out the result. But I'm not certain I've gotten the details right. Please take another quick look.

dain
dain dismissed these changes on 2024-12-09
dain129 days ago

You are getting there. In all modules other than SPI, we should simply remove the methods. In the SPI we leave the methods, but mark them @Deprecated(forRemoval=ture). This means the nothing else in Trino is allowed to call this method. The new method will have a default implementation that calls through to the old deprecated implementations (likely needs the deprecation check suppressed for that method). This way existing implementations should still work, but it forces them to update. Then in a few months we remove the deprecated methods entirelly.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/metadata/Metadata.java
dain129 days ago

Remove all other set*Authorization methods from this interface and implementations.

djsstarburst120 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java
dain129 days ago

Remove all other set*Authorization methods from this interface and implementations.

djsstarburst120 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/metadata/SystemSecurityMetadata.java
171 * @deprecated {Use {@link #setEntityOwner(Session, String, List, TrinoPrincipal)}
164172 */
173 @Deprecated
165174
void setSchemaOwner(Session session, CatalogSchemaName schema, TrinoPrincipal principal);
dain129 days ago

Sinces this is in the main module, we can remove these methods instead of deprecating them. The only place we would leave the existing methods is in the trino-spi module.

djsstarburst120 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/metadata/SystemSecurityMetadata.java
239254 */
240255 void columnNotNullConstraintDropped(Session session, CatalogSchemaTableName table, String column);
256
257
default void setEntityOwner(Session session, String ownedKind, List<String> name, TrinoPrincipal principal)
dain129 days ago

This should just be an interface method

djsstarburst120 days ago

Changed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/security/AccessControl.java
154 * @deprecated use {@link #checkCanSetEntityAuthorization}
150155 */
156 @Deprecated
151157
void checkCanSetSchemaAuthorization(SecurityContext context, CatalogSchemaName schemaName, TrinoPrincipal principal);
dain129 days ago

These can be removed leaving only the new generic entity version

djsstarburst120 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/security/AccessControlManager.java
14431444 }
14441445
1446 @Override
1447
public void checkCanSetEntityAuthorization(SecurityContext context, String ownedKind, List<String> name, TrinoPrincipal principal)
dain129 days ago

Remove all other checkCanSet*Authorization methods from this interface and implementations.

djsstarburst120 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java
278 *
279 * @deprecated {Use {@link #checkCanSetEntityAuthorization}
274280 */
281
@Deprecated
dain129 days ago

These should all be @Deprecated(forRemoval = true)

djsstarburst120 days ago

Added.

Conversation is marked as resolved
Show resolved
core/trino-spi/src/main/java/io/trino/spi/security/SystemAccessControl.java
281 @Deprecated
275282 default void checkCanSetSchemaAuthorization(SystemSecurityContext context, CatalogSchemaName schema, TrinoPrincipal principal)
276283 {
277284
denySetSchemaAuthorization(schema.toString(), principal);
dain129 days ago

Let's switch all of these to denySetEntityAuthorization

djsstarburst120 days ago

Switched.

Conversation is marked as resolved
Show resolved
core/trino-spi/src/main/java/io/trino/spi/security/AccessDeniedException.java
746748 throw new AccessDeniedException(format("Cannot show create function for %s%s", functionName, formatExtraInfo(extraInfo)));
747749 }
748750
751
public static void denySetEntityAuthorization(String ownedKind, List<String> name)
dain129 days ago

Let's mark all of the old denySet*Authorization @Deprecated(forRemoval = true)

djsstarburst120 days ago

Marked.

Conversation is marked as resolved
Show resolved
lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/security/AllowAllSystemAccessControl.java
360360 }
361361
362 @Override
363
public void checkCanSetEntityAuthorization(SystemSecurityContext context, String ownedKind, List<String> name, TrinoPrincipal principal) {}
dain129 days ago

We can remove the other checkCanSet*Authorization methods from this impleentation and all others, since the engine can never call the other versions (because they are marked for removal)

djsstarburst46 days ago

Removed.

djsstarburst djsstarburst force pushed from a39beacf to f1a9e92b 122 days ago
djsstarburst djsstarburst force pushed from f1a9e92b to 7374ecca 120 days ago
djsstarburst djsstarburst force pushed from 7374ecca to 35814ce9 120 days ago
djsstarburst djsstarburst force pushed from 35814ce9 to 7b964542 59 days ago
djsstarburst
djsstarburst50 days ago

@homar raised the question of whether there should be a way in SQL to see the owner of an entity. AIUI that would require some new syntax, maybe something like:

SHOW AUTHORIZATION ON ownedEntityKind qualifiedName BY principal

@martint and @dain - - Do you think it's worthwhile to extend this PR to add something like that? If we think it's worth doing, we would have to decide on the visibility rules for owners of entities.

ksobolew
ksobolew49 days ago

@djsstarburst see #10593, there are some (other) options there

djsstarburst
djsstarburst49 days ago

@djsstarburst see #10593, there are some (other) options there

Good point; maybe exposing ownership as columns in the information_schema makes sense. I don't really have an opinion, but I'll be @martint does.

dain
dain commented on 2025-02-28
Conversation is marked as resolved
Show resolved
core/trino-grammar/src/main/antlr4/io/trino/grammar/sql/SqlBase.g4
941939 ;
942940
941ownedEntityKind
942
: MATERIALIZED? basicEntityKind
dain48 days ago

This allows for any identifier to carry the materialized word, but I don't think applies to anything except views. For not, let's just make this:

Suggested change
: MATERIALIZED? basicEntityKind
: TABLE | SCHEMA | VIEW |MATERIALIZED VIEW | identifier

and get rid of the rule below

djsstarburst46 days ago

Replaced.

Conversation is marked as resolved
Show resolved
core/trino-main/src/main/java/io/trino/security/AccessControlManager.java
1405 checkArgument(!name.isEmpty(), "name is empty");
1406 requireNonNull(principal, "principal is null");
1407
1408
switch (ownedKind) {
1409
case "SCHEMA" -> {
1410
checkCanAccessCatalog(securityContext, name.get(0));
1411
catalogAuthorizationCheck(
1412
name.get(0),
1413
securityContext,
1414
(control, context) -> control.checkCanSetSchemaAuthorization(context, name.get(1), principal));
1415
}
1416
case "TABLE" -> {
1417
checkCanAccessCatalog(securityContext, name.get(0));
1418
catalogAuthorizationCheck(
1419
name.get(0),
1420
securityContext,
1421
(control, context) -> control.checkCanSetTableAuthorization(context, new SchemaTableName(name.get(1), name.get(2)), principal));
1422
}
1423
case "VIEW" -> {
1424
checkCanAccessCatalog(securityContext, name.get(0));
1425
catalogAuthorizationCheck(
1426
name.get(0),
1427
securityContext,
1428
(control, context) -> control.checkCanSetViewAuthorization(context, new SchemaTableName(name.get(1), name.get(2)), principal));
1429
}
dain48 days ago

I don't think this is needed. The default method on SystemAccessControl splits out the checks just like this, so we just need the default path.

djsstarburst46 days ago

Removed.

Conversation is marked as resolved
Show resolved
core/trino-parser/src/main/java/io/trino/sql/parser/AstBuilder.java
513 if (materialized && !"VIEW".equalsIgnoreCase(entityKind)) {
514 throw parseError("Unknown owned entity kind MATERIALIZED " + entityKind, context.ownedEntityKind());
515 }
516
// No special checks are needed for a materialized view owner change.
517
// It's just a view, identified by name.
dain48 days ago

I'm not sure what this comment means. There are no special checks for any of the cases.

djsstarburst46 days ago

Removed the comment.

Conversation is marked as resolved
Show resolved
core/trino-spi/src/main/java/io/trino/spi/security/AccessDeniedException.java
177 /**
178 * @deprecated Use {@link #denySetEntityAuthorization(String, List, TrinoPrincipal)}
179 */
180
@Deprecated
dain48 days ago

All of the deprecations should be marked with forRemoval=true

djsstarburst46 days ago

forRemoval = true added

core/trino-spi/src/test/java/io/trino/spi/testing/InterfaceTestUtils.java
4950 if (method.getDeclaringClass() == Object.class) {
5051 continue;
5152 }
53
if (Arrays.stream(method.getAnnotations()).anyMatch(annotation -> annotation instanceof Deprecated deprecated && deprecated.forRemoval())) {
dain48 days ago

@electrum what do you think about this change?

djsstarburst37 days ago

FTR, I removed this line, and will add any dependency methods that are found to be missing.

dain dain dismissed their stale review 48 days ago
Changes implemented
djsstarburst djsstarburst force pushed from 7b964542 to 4f454b02 46 days ago
dain
dain commented on 2025-03-02
dain46 days ago

Other than the build failure, and the outstanding question for @electrum, this looks good to me

djsstarburst djsstarburst force pushed from 4f454b02 to a5154d6b 45 days ago
djsstarburst djsstarburst force pushed from a5154d6b to d85e9532 37 days ago
djsstarburst djsstarburst force pushed from d85e9532 to 3a0a10c2 36 days ago
djsstarburst djsstarburst force pushed from 3a0a10c2 to 47f13839 36 days ago
kokosing
kokosing31 days ago

@electrum can you please take a look? It looks this PR waits on your feedback only (see #21794 (review)).

electrum
electrum28 days ago👍 1❤ 1

The comment for me was addressed. This can proceed.

kokosing
kokosing commented on 2025-03-21
core/trino-grammar/src/main/antlr4/io/trino/grammar/sql/SqlBase.g4
945943 ;
946944
945ownedEntityKind
946
: TABLE | SCHEMA | VIEW | MATERIALIZED VIEW | identifier
kokosing27 days ago

MATERIALIZED VIEW was not supported before. I think it would be nice to add it in separate commit, or at least mention this in the commit message that it is something it is now possible to set owner for materialized view.

EDIT: I see that it is missing in the implementation so let's simply remove it from the grammar.

kokosing27 days ago

What is the use case for identifier? Does it mean that user is able to pass anything, syntax will be fine, but we will fail to execute that?

Also I have some hard time to understand why identifier is something for that. Usually identifier is a name of the thing not a type of the thing.

I would prefer to remove this from this PR.

djsstarburst22 days ago

The reason for the identifier is that this is an extension mechanism, and therefore Trino can't know what entity kinds will be used.

This can't be removed from the PR - - the extension mechanism is the entire reason for the PR.

ksobolew22 days ago

We already support arbitrary entity kinds in GRANT, REVOKE and DENY, so it perfectly makes sense to have it here as well.

core/trino-main/src/main/java/io/trino/execution/SetAuthorizationTask.java
kokosing27 days ago

MATERIALIZED VIEW is missing here, maybe we should simply remove it from the grammar?

djsstarburst22 days ago

No, it's not missing. MATERIALIZED VIEW is treated as a VIEW. See line 512 of AstBuilder.

kokosing22 days ago

Please correct me if I am wrong. Previously we were also able to set an owner for MATERIALIZED view because it was just had it for the view. Now we do the same but we change the syntax that MATERIALIZED keyword can be added but it is not necessary.

So my question is why are you adding MATERIALIZED keyword? Why not to keep existing behaviour?

djsstarburst22 days ago

Oh! You are absolutely right - - using the MATERIALIZED keyword in the SET AUTHORIZATION grammar is a bug.

Fixed in the grammar and in AstBuilder.visitSetAuthorization.

core/trino-main/src/main/java/io/trino/metadata/DisabledSystemSecurityMetadata.java
235217 public void columnNotNullConstraintDropped(Session session, CatalogSchemaTableName table, String column) {}
236218
219 @Override
220
public void setEntityOwner(Session session, String ownedKind, List<String> name, TrinoPrincipal principal)
kokosing27 days ago

Can we enum for ownedKind. I would prefer the name entityType. Or let's use the name from the grammar OwnedEntityKind.

Notice that using enum will help us to do static code analysis to make sure we cover all the cases by using the switch statement. It will be useful when one would like to add new entries.

djsstarburst22 days ago👎 1

As mentioned we cannot use an enum, because this is an extension mechanism, and Trino itself can't know all the entity kinds used by all extension uses.

core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java
kokosing27 days ago

Materialized view is also missing here.

djsstarburst22 days ago

No, it's not missing. MATERIALIZED VIEW is treated as a VIEW. See line 512 of AstBuilder.

core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java
180180public final class MetadataManager
181181 implements Metadata
182182{
183
private static final Set<String> ENTITY_KINDS_WITH_CATALOG = ImmutableSet.of("SCHEMA", "TABLE", "VIEW");
kokosing27 days ago

Are there any entities that are not catalog related?

djsstarburst22 days ago

Clients of the extension mechanism can define entity kinds that not contained in catalogs. For example, the extension mechanism can be used to support ownership of roles, which are not contained in catalogs.

core/trino-main/src/main/java/io/trino/security/AccessControlManager.java
14431398 }
14441399
1400 @Override
1401
public void checkCanSetEntityAuthorization(SecurityContext securityContext, String ownedKind, List<String> name, TrinoPrincipal principal)
kokosing27 days ago

Can we use io.trino.metadata.QualifiedObjectName instead of List<String>?

djsstarburst22 days ago

No, we can't use QualifiedObjectName because it is based on the assumption that all ownable entity kinds are contained in a catalog and schema.

ksobolew22 days ago

See also io.trino.spi.connector.EntityKindAndName, which is a pair of String entityKind and List<String> name. BTW, perhaps we could use it here as well.

djsstarburst22 days ago (edited 22 days ago)

This is a reasonable suggestion, and is consistent with checkCanGrantEntityPrivilege.

I made this change everywhere except denySetEntityAuthorization. I didn't make it there because there are quite a few of calls.

[Later]

I ended up making the change for denySetEntityAuthorization as well, since that is more consistent.

djsstarburst djsstarburst force pushed from 47f13839 to 93ffec9c 22 days ago
djsstarburst Add generic SET AUTHORIZATION
d8c55871
djsstarburst djsstarburst force pushed from 93ffec9c to d8c55871 22 days ago
kokosing
kokosing approved these changes on 2025-03-27
kokosing kokosing merged 1a81b69e into master 21 days ago
kokosing
kokosing21 days ago

@djsstarburst Thank you! Merged.

github-actions github-actions added this to the 475 milestone 21 days ago
djsstarburst
djsstarburst21 days ago

Thank you! Merged.

Thank YOU @kokosing for your review!

Login to write a write a comment.

Login via GitHub

Assignees
No one assigned
Labels
Milestone