Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check catalog & schema access in USE statement #14209

Merged
merged 1 commit into from
Nov 17, 2022

Conversation

huberty89
Copy link
Contributor

@huberty89 huberty89 commented Sep 20, 2022

Description

This PR add checks if user has an access to catalog and schema in USE statement.

Related issues, pull requests, and links

Non-technical explanation

There was a lack of check in USE statement if user has an access to catalog or schema.

Release notes

( ) This is not user-visible or 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:

# Security
* Check access to catalog and schema during execution of USE statement. ({issue}`14208`)

Copy link
Member

@kokosing kokosing left a comment

Choose a reason for hiding this comment

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

Add tests

throw new TrinoException(NOT_FOUND, "Catalog does not exist: " + catalog);
}

String schema = statement.getSchema().getValue().toLowerCase(ENGLISH);

CatalogSchemaName name = new CatalogSchemaName(catalog, schema);
if (!metadata.schemaExists(session, name)) {
if (hasSchemaAccess(securityContext, catalog, schema) ||
!metadata.schemaExists(session, name)) {
throw new TrinoException(NOT_FOUND, "Schema does not exist: " + name);
Copy link
Member

Choose a reason for hiding this comment

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

I think the error message has to be different and so the error code should be different between not existing case or access denied case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO error message needs to be unambiguous. With different error messages there will be no difference what we have today.

Copy link
Member

Choose a reason for hiding this comment

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

That is the way Trino works today. For example see io.trino.sql.analyzer.StatementAnalyzer.Visitor#visitUpdate if you use not existing table you will get different error than when using a table without an access.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I check if catalog/schema exists first, then I check if user has an access to those

Copy link
Contributor

@ksobolew ksobolew left a comment

Choose a reason for hiding this comment

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

Commit message needs a rationale for this change. AFAIR it's to prevent surprises when someone switches to a schema they don't have access to and then all queries are denied, right?

@Test
public void testUseStatementAccessControl()
{
executeExclusively(() -> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I have a feeling that executeExclusively is overused in this class. If we're using entities with random names, and make sure that the deny rules in the TestingAccessControlManager only reference these random names, then they should be able to run concurrently. That's out of scope for this change, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here I also change the behavior via TestingAccessControlManager so this executeExclusively prevent to break other tests

Comment on lines +631 to +722
assertThatThrownBy(() -> getQueryRunner().execute("USE not_exists_catalog.tiny"))
.hasMessageMatching("Catalog does not exist: not_exists_catalog");
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need a test where we deny access to a not existing catalog/schema and see that the message is "catalog/schema does not exist" instead of "access denied"? Is this part of the contract or just a consistency thing? @kokosing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +637 to +737
getQueryRunner().getAccessControl().denyCatalogs(catalog -> !catalog.equals("tpch"));
assertThatThrownBy(() -> getQueryRunner().execute("USE tpch.tiny"))
.hasMessageMatching("Access Denied: Cannot access catalog tpch");
assertThatThrownBy(() -> getQueryRunner().execute("USE tpch.not_exists_schema"))
.hasMessageMatching("Access Denied: Cannot access catalog tpch");
Copy link
Contributor

Choose a reason for hiding this comment

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

There also needs to be a test that allows access to catalog but denies access to a schema

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to add such a test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

@@ -617,4 +617,32 @@ public void testSetViewAuthorizationWithSecurityInvoker()
{
assertQuerySucceeds("ALTER VIEW mock.default.test_view_invoker SET AUTHORIZATION some_other_user");
}

@Test
public void testUseStatementAccessControl()
Copy link
Member

Choose a reason for hiding this comment

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

nit: We can divide this test method into few smaller ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Spitted into 3 test methods

@huberty89
Copy link
Contributor Author

@ksobolew @kokosing Updated, please take a look

@kokosing kokosing merged commit 120299e into trinodb:master Nov 17, 2022
@kokosing
Copy link
Member

Merged, thanks!

@github-actions github-actions bot added this to the 404 milestone Nov 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

USE statement leaks names of catalogs and schemas that the user has no access to
3 participants