freesinger opened a new issue, #11190: URL: https://github.com/apache/gravitino/issues/11190
### Version
main branch
### Describe what's wrong
When Iceberg REST authorization is enabled with
`skipAuthorizationForRestBackend`,
`IcebergMetadataAuthorizationMethodInterceptor.shouldSkipAuthorization()` tries
to load the Iceberg catalog wrapper to determine whether the request should
skip local authorization.
The current code calls:
```java
IcebergCatalogWrapper catalogWrapper =
wrapperManager.getCatalogWrapper(catalogId.name());
return catalogWrapper.isRESTCatalog();
```
at
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/server/web/filter/IcebergMetadataAuthorizationMethodInterceptor.java:162.
If the requested catalog does not exist,
wrapperManager.getCatalogWrapper(...) throws NoSuchCatalogException. This
exception is thrown while only checking whether authorization should be
skipped.
The exception then propagates to
BaseMetadataAuthorizationMethodInterceptor.invoke() and is wrapped as:
Authorization failed due to system internal error
at
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/server/web/filter/BaseMetadataAuthorizationMethodInterceptor.java:135.
This makes a normal "catalog not found" user/request error look like an
authorization system internal error.
The skip-authorization check should be best-effort. If the catalog wrapper
cannot be loaded because the catalog does not exist, shouldSkipAuthorization()
should return false and allow the normal request path to produce the correct
catalog-not-found response.
### Error message and/or stacktrace
Server log:
```text
org.apache.gravitino.exceptions.NoSuchCatalogException: Couldn't find
Iceberg configuration for catalog lancecatalog
at
org.apache.gravitino.iceberg.service.IcebergCatalogWrapperManager.createCatalogWrapper(IcebergCatalogWrapperManager.java:120)
at
org.apache.gravitino.iceberg.service.IcebergCatalogWrapperManager.lambda$getCatalogWrapper$2(IcebergCatalogWrapperManager.java:102)
at
org.apache.gravitino.iceberg.service.IcebergCatalogWrapperManager.getCatalogWrapper(IcebergCatalogWrapperManager.java:102)
at
org.apache.gravitino.server.web.filter.IcebergMetadataAuthorizationMethodInterceptor.shouldSkipAuthorization(IcebergMetadataAuthorizationMethodInterceptor.java:162)
at
org.apache.gravitino.server.web.filter.BaseMetadataAuthorizationMethodInterceptor.invoke(BaseMetadataAuthorizationMethodInterceptor.java:135)
...
```
The client receives an internal authorization error instead of a normal
catalog-not-found response:
java.lang.RuntimeException: Authorization failed due to system internal
error, User: 'normal', Operation: 'createTable'
Caused by: org.apache.gravitino.exceptions.NoSuchCatalogException:
Couldn't find Iceberg configuration for catalog lancecatalog
The same issue can happen for other Iceberg REST operations such as
createNamespace, because the failure occurs before the actual REST operation
proceeds.
### How to reproduce
1. Start Gravitino from the main branch with Iceberg REST auxiliary service
enabled.
2. Enable authorization and configure the Iceberg REST server so that
`skipAuthorizationForRestBackend` is enabled.
3. Do not create a Gravitino catalog named `lancecatalog`.
4. Send an Iceberg REST request to the missing catalog, for example:
```bash
curl -X POST \
-H "Content-Type: application/json" \
-H "<auth header>" \
-d '{
"namespace": ["ns1"]
}' \
"http://localhost:<iceberg-rest-port>/iceberg/v1/lancecatalog/namespaces"
or create a table under the missing catalog:
curl -X POST \
-H "Content-Type: application/json" \
-H "<auth header>" \
-d '{
"name": "tbl1",
"schema": {
"type": "struct",
"schema-id": 0,
"fields": []
}
}' \
"http://localhost:<iceberg-rest-port>/iceberg/v1/lancecatalog/namespaces/ns1/tables"
```
Actual result:
The server returns an internal authorization error:
Authorization failed due to system internal error, User: '<user>',
Operation: '<operation>'
Expected result:
The authorization skip check should not fail the request. If the catalog
does not exist, shouldSkipAuthorization() should return false, and the request
should continue to the normal path that reports a catalog-not-found error.
### Additional context
The problematic code path is:
```text
BaseMetadataAuthorizationMethodInterceptor.invoke()
->
IcebergMetadataAuthorizationMethodInterceptor.shouldSkipAuthorization()
-> IcebergCatalogWrapperManager.getCatalogWrapper()
-> DynamicIcebergConfigProvider.getIcebergCatalogConfig()
-> NoSuchCatalogException
```
shouldSkipAuthorization() is only intended to decide whether local
authorization can be skipped for a Gravitino-backed remote REST catalog.
Failure to load the catalog wrapper due to a missing catalog should not be
treated as an authorization infrastructure failure.
A possible fix is to catch NoSuchCatalogException around
wrapperManager.getCatalogWrapper(catalogId.name()) and return false:
```java
try {
IcebergCatalogWrapper catalogWrapper =
wrapperManager.getCatalogWrapper(catalogId.name());
return catalogWrapper.isRESTCatalog();
} catch (NoSuchCatalogException e) {
return false;
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
