You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@polaris.apache.org by "adutra (via GitHub)" <gi...@apache.org> on 2026/02/10 20:04:24 UTC
[PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
adutra opened a new pull request, #3734:
URL: https://github.com/apache/polaris/pull/3734
This PR introduces support for access delegation in the `registerTable` endpoint.
Two new authorizable operations are introduced:
- `REGISTER_TABLE_WITH_READ_DELEGATION`: requires `TABLE_CREATE` + `TABLE_READ_DATA`
- `REGISTER_TABLE_WITH_WRITE_DELEGATION`: requires `TABLE_CREATE` + `TABLE_WRITE_DATA`
The implementation is inspired by the `loadTable` endpoint; the authorization checks are very similar.
<!--
π Describe what changes you're proposing, especially breaking or user-facing changes.
π See https://github.com/apache/polaris/blob/main/CONTRIBUTING.md for more.
-->
## Checklist
- [ ] π‘οΈ Don't disclose security issues! (contact security@apache.org)
- [ ] π Clearly explained why the changes are needed, or linked related issues: Fixes #
- [ ] π§ͺ Added/updated tests with good coverage, or manually tested (and explained how)
- [ ] π‘ Added comments for complex logic
- [ ] π§Ύ Updated `CHANGELOG.md` (if needed)
- [ ] π Updated documentation in `site/content/in-dev/unreleased` (if needed)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4426798957
This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4605543605
Heads up: this is finally ready for review.
@flyrain
@sririshindra
@sneethiraj
@dimas-b
@sungwy
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3343319705
##########
extensions/auth/ranger/impl/src/test/resources/logback-test.xml:
##########
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<configuration debug="false">
Review Comment:
This was missing and logs were being printed at DEBUG level.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4006766523
Now it's running π
π€·ββοΈ
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3343315275
##########
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:
##########
@@ -708,15 +708,101 @@ public void testCreateTableWithOverriddenBaseLocationMustResideInNsDirectory() {
.isInstanceOf(ForbiddenException.class);
}
+ /**
+ * Create an INTERNAL catalog. Register a table WITH access delegation and verify that the
+ * registerTable response contains vended credentials (when supported by the storage type).
+ */
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegation() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ catalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = catalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
+ /**
+ * Create an EXTERNAL catalog with credential vending enabled. Register a table WITH access
+ * delegation and verify that the registerTable response contains vended credentials (when
+ * supported by the storage type).
+ */
+ @CatalogConfig(
+ value = Catalog.TypeEnum.EXTERNAL,
+ properties = {"polaris.config.enable.credential.vending", "true"})
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegationForExternalCatalog() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ externalCatalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = externalCatalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
/**
* Create an EXTERNAL catalog. The test configuration, by default, disables access delegation for
- * EXTERNAL catalogs, so register a table and try to load it with the REST client configured to
- * try to fetch vended credentials. Expect a ForbiddenException.
+ * EXTERNAL catalogs, so try to register a table with the REST client configured to try to fetch
+ * vended credentials. Expect a ForbiddenException.
*/
@CatalogConfig(Catalog.TypeEnum.EXTERNAL)
@RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
@Test
- public void testLoadTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
+ public void testRegisterTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
Review Comment:
Update: I was able to keep this test by using the raw `CatalogApi` client.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3228874220
##########
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:
##########
@@ -708,15 +708,101 @@ public void testCreateTableWithOverriddenBaseLocationMustResideInNsDirectory() {
.isInstanceOf(ForbiddenException.class);
}
+ /**
+ * Create an INTERNAL catalog. Register a table WITH access delegation and verify that the
+ * registerTable response contains vended credentials (when supported by the storage type).
+ */
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegation() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ catalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = catalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
+ /**
+ * Create an EXTERNAL catalog with credential vending enabled. Register a table WITH access
+ * delegation and verify that the registerTable response contains vended credentials (when
+ * supported by the storage type).
+ */
+ @CatalogConfig(
+ value = Catalog.TypeEnum.EXTERNAL,
+ properties = {"polaris.config.enable.credential.vending", "true"})
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegationForExternalCatalog() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ externalCatalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = externalCatalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
/**
* Create an EXTERNAL catalog. The test configuration, by default, disables access delegation for
- * EXTERNAL catalogs, so register a table and try to load it with the REST client configured to
- * try to fetch vended credentials. Expect a ForbiddenException.
+ * EXTERNAL catalogs, so try to register a table with the REST client configured to try to fetch
+ * vended credentials. Expect a ForbiddenException.
*/
@CatalogConfig(Catalog.TypeEnum.EXTERNAL)
@RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
@Test
- public void testLoadTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
+ public void testRegisterTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
Review Comment:
This rename means the loadTable + delegation-header + external + config-disabled scenario no longer has a dedicated test. `testLoadTableWithoutAccessDelegationForExternalCatalogWithConfigDisabled` (no header) doesn't cover it. Consider keeping a loadTable variant alongside the new register one.
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -600,26 +600,50 @@ public LoadTableResponse createTableStaged(
*
* @param namespace The namespace to register the table in
* @param request the register table request
+ * @param delegationModes the access delegation modes to use
+ * @param refreshCredentialsEndpoint the refresh credentials endpoint to use
* @return ETagged {@link LoadTableResponse} to uniquely identify the table metadata
*/
- public LoadTableResponse registerTable(Namespace namespace, RegisterTableRequest request) {
+ public LoadTableResponse registerTable(
+ Namespace namespace,
+ RegisterTableRequest request,
+ EnumSet<AccessDelegationMode> delegationModes,
+ Optional<String> refreshCredentialsEndpoint) {
+
+ request.validate();
TableIdentifier identifier = TableIdentifier.of(namespace, request.name());
boolean overwrite = request.overwrite();
+ Set<PolarisStorageActions> actionsRequested =
+ authorizeRegisterTable(identifier, delegationModes, overwrite);
+
if (overwrite) {
- authorizeCreateTableLikeUnderNamespaceOperationOrThrow(
- PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE, identifier);
- return registerTableWithOverwrite(identifier, request);
+ return registerTableWithOverwrite(
+ identifier, request, delegationModes, actionsRequested, refreshCredentialsEndpoint);
}
- // Creating new table requires REGISTER_TABLE privilege
- PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REGISTER_TABLE;
- authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, identifier);
- return catalogHandlerUtils().registerTable(baseCatalog, namespace, request);
+ Table table = baseCatalog.registerTable(identifier, request.metadataLocation());
+
+ if (table instanceof BaseTable baseTable) {
+ TableMetadata tableMetadata = baseTable.operations().current();
+ return buildLoadTableResponseWithDelegationCredentials(
+ identifier,
+ tableMetadata,
+ delegationModes,
+ actionsRequested,
+ refreshCredentialsEndpoint)
+ .build();
+ }
+
+ throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
Review Comment:
This message is confusing, how about the following:
```
throw new IllegalStateException(
"Expected a BaseTable object from registerTable() for %s, got: %s"
.formatted(identifier, table.getClass().getName()));
```
It'd be nice to fix in this PR, but not a blocker since this PR follows the previous pattern.
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -631,7 +655,9 @@ private LoadTableResponse registerTableWithOverwrite(
Table table = icebergCatalog.registerTable(identifier, request.metadataLocation(), true);
if (table instanceof BaseTable baseTable) {
TableMetadata metadata = baseTable.operations().current();
- return LoadTableResponse.builder().withTableMetadata(metadata).build();
+ return buildLoadTableResponseWithDelegationCredentials(
+ identifier, metadata, delegationModes, actionsRequested, refreshCredentialsEndpoint)
+ .build();
}
throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
Review Comment:
This message is confusing, how about the following:
```
throw new IllegalStateException(
"Expected a BaseTable object from registerTable() for %s, got: %s"
.formatted(identifier, table.getClass().getName()));
```
Not a blocker since this PR doesn't touch it.
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -808,6 +834,44 @@ private Set<PolarisStorageActions> authorizeLoadTable(
return actionsRequested;
}
+ private Set<PolarisStorageActions> authorizeRegisterTable(
+ TableIdentifier tableIdentifier,
+ EnumSet<AccessDelegationMode> delegationModes,
+ boolean overwrite) {
+
+ if (delegationModes.isEmpty()) {
+ PolarisAuthorizableOperation op =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE
+ : PolarisAuthorizableOperation.REGISTER_TABLE;
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, tableIdentifier);
+ return Set.of();
+ }
+
+ PolarisAuthorizableOperation readOp =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE_WITH_READ_DELEGATION
+ : PolarisAuthorizableOperation.REGISTER_TABLE_WITH_READ_DELEGATION;
+ PolarisAuthorizableOperation writeOp =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE_WITH_WRITE_DELEGATION
+ : PolarisAuthorizableOperation.REGISTER_TABLE_WITH_WRITE_DELEGATION;
+
+ Set<PolarisStorageActions> actionsRequested =
+ EnumSet.of(PolarisStorageActions.READ, PolarisStorageActions.LIST);
+
+ try {
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(writeOp, tableIdentifier);
+ actionsRequested.add(PolarisStorageActions.WRITE);
+ } catch (ForbiddenException e) {
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(readOp, tableIdentifier);
+ }
+
+ checkAllowExternalCatalogCredentialVending(delegationModes);
Review Comment:
A question: do we support register table in the remote catalogs?
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -600,26 +600,50 @@ public LoadTableResponse createTableStaged(
*
* @param namespace The namespace to register the table in
* @param request the register table request
+ * @param delegationModes the access delegation modes to use
+ * @param refreshCredentialsEndpoint the refresh credentials endpoint to use
* @return ETagged {@link LoadTableResponse} to uniquely identify the table metadata
*/
- public LoadTableResponse registerTable(Namespace namespace, RegisterTableRequest request) {
+ public LoadTableResponse registerTable(
+ Namespace namespace,
+ RegisterTableRequest request,
+ EnumSet<AccessDelegationMode> delegationModes,
+ Optional<String> refreshCredentialsEndpoint) {
+
+ request.validate();
Review Comment:
I'd prefer to move it to adapter layer, but since createTable uses the same pattern, I'm OK to change it as a followup.
##########
polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizableOperation.java:
##########
@@ -129,6 +129,10 @@ public enum PolarisAuthorizableOperation {
CREATE_TABLE_STAGED_WITH_WRITE_DELEGATION(EnumSet.of(TABLE_CREATE, TABLE_WRITE_DATA)),
REGISTER_TABLE(TABLE_CREATE),
REGISTER_TABLE_OVERWRITE(TABLE_FULL_METADATA),
+ REGISTER_TABLE_WITH_READ_DELEGATION(EnumSet.of(TABLE_CREATE, TABLE_READ_DATA)),
+ REGISTER_TABLE_WITH_WRITE_DELEGATION(EnumSet.of(TABLE_CREATE, TABLE_WRITE_DATA)),
+ REGISTER_TABLE_OVERWRITE_WITH_READ_DELEGATION(EnumSet.of(TABLE_FULL_METADATA, TABLE_READ_DATA)),
+ REGISTER_TABLE_OVERWRITE_WITH_WRITE_DELEGATION(EnumSet.of(TABLE_FULL_METADATA, TABLE_WRITE_DATA)),
Review Comment:
These looks correct to me, they are also consistent with the table creation operations. cc @collado-mike @dennishuo @singhpk234
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4498485344
FYI: with the release of Iceberg 1.11, I am going to attempt to change the base branch of this PR from `feature/iceberg-1.11` to `main`. Pray for me π
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4006667923
Rebased to fix conflicts.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra merged PR #3734:
URL: https://github.com/apache/polaris/pull/3734
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274815356
##########
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:
##########
@@ -935,6 +1020,62 @@ public void testRegisterAndLoadTableWithReturnedETag() {
}
}
+ /**
+ * Build an Iceberg table, then invoke a subsequent register table call that overwrites the
+ * existing table metadata. Verifies that the overwrite is applied and the catalog reflects the
+ * updated metadata.
+ */
+ @Test
+ public void testRegisterTableOverwriteViaRest() {
+ Namespace ns = Namespace.of("ns_overwrite_rest");
+ restCatalog.createNamespace(ns);
+
+ // Create a source table and capture its metadata location
+ Table source = restCatalog.buildTable(TableIdentifier.of(ns, "source_table"), SCHEMA).create();
Review Comment:
This code wasn't added in this PR but I'll add the test in #4506
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274817475
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -853,6 +884,42 @@ private Set<PolarisStorageActions> authorizeLoadTable(
return actionsRequested;
}
+ private Set<PolarisStorageActions> authorizeRegisterTable(
+ TableIdentifier tableIdentifier,
+ EnumSet<AccessDelegationMode> delegationModes,
+ boolean overwrite) {
+
+ if (delegationModes.isEmpty()) {
+ PolarisAuthorizableOperation op =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE
+ : PolarisAuthorizableOperation.REGISTER_TABLE;
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, tableIdentifier);
Review Comment:
There is a check for existing table names.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4006675425
For some reason, CI is not running for this PR π€·ββοΈ
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4040905341
FYI I had to rebase and change the implementation due to #3719.
@sririshindra and @flyrain since you authored/reviewed #3719, could you review this one please?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3734:
URL: https://github.com/apache/polaris/pull/3734#issuecomment-4498896954
FYI I successfully changed the base branch to main and updated the PR.
However, since this PR depends on #4506, I switched it back to draft for now.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274452823
##########
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:
##########
@@ -935,6 +1020,62 @@ public void testRegisterAndLoadTableWithReturnedETag() {
}
}
+ /**
+ * Build an Iceberg table, then invoke a subsequent register table call that overwrites the
+ * existing table metadata. Verifies that the overwrite is applied and the catalog reflects the
+ * updated metadata.
+ */
+ @Test
+ public void testRegisterTableOverwriteViaRest() {
+ Namespace ns = Namespace.of("ns_overwrite_rest");
+ restCatalog.createNamespace(ns);
+
+ // Create a source table and capture its metadata location
+ Table source = restCatalog.buildTable(TableIdentifier.of(ns, "source_table"), SCHEMA).create();
Review Comment:
The PR adds an explicit rejection path for registerTable overwrite on federated/external catalogs (BadRequestException in IcebergCatalogHandler when overwrite=true and baseCatalog is not IcebergCatalog). Please check whether an integration test should be added to cover this user-visible behavior (e.g., EXTERNAL catalog + overwrite=true returns HTTP 400 with the expected message), since current integration coverage only exercises the internal-catalog overwrite success path.
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -853,6 +884,42 @@ private Set<PolarisStorageActions> authorizeLoadTable(
return actionsRequested;
}
+ private Set<PolarisStorageActions> authorizeRegisterTable(
+ TableIdentifier tableIdentifier,
+ EnumSet<AccessDelegationMode> delegationModes,
+ boolean overwrite) {
+
+ if (delegationModes.isEmpty()) {
+ PolarisAuthorizableOperation op =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE
+ : PolarisAuthorizableOperation.REGISTER_TABLE;
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, tableIdentifier);
Review Comment:
Authorization for overwrite register currently uses authorizeCreateTableLikeUnderNamespaceOperationOrThrow (namespace-targeted). For overwrite=true on an *existing* table, this likely bypasses table-scoped grants (e.g., a principal with TABLE_FULL_METADATA granted on the specific table but not on the namespace/catalog could be incorrectly denied) and makes the privilege boundary less precise. Consider authorizing overwrite against the table entity when it exists (authorizeBasicTableLikeOperationOrThrow with ICEBERG_TABLE) and only falling back to namespace-targeted authorization when the table is missing (to support the overwrite-creates-if-missing behavior).
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -609,14 +609,45 @@ public LoadTableResponse createTableStaged(
*
* @param namespace The namespace to register the table in
* @param request the register table request
+ * @param delegationModes the access delegation modes to use
+ * @param refreshCredentialsEndpoint the refresh credentials endpoint to use
* @return ETagged {@link LoadTableResponse} to uniquely identify the table metadata
*/
- public LoadTableResponse registerTable(Namespace namespace, RegisterTableRequest request) {
- PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REGISTER_TABLE;
- authorizeCreateTableLikeUnderNamespaceOperationOrThrow(
- op, TableIdentifier.of(namespace, request.name()));
+ public LoadTableResponse registerTable(
+ Namespace namespace,
+ RegisterTableRequest request,
+ EnumSet<AccessDelegationMode> delegationModes,
+ Optional<String> refreshCredentialsEndpoint) {
+
+ request.validate();
+ TableIdentifier identifier = TableIdentifier.of(namespace, request.name());
+ boolean overwrite = request.overwrite();
+
+ Set<PolarisStorageActions> actionsRequested =
Review Comment:
registerTable resolves/validates the requested access delegation mode (resolveAccessDelegationModes) only *after* calling baseCatalog.registerTable(...). Since resolveAccessDelegationModes can throw (e.g., REMOTE_SIGNING currently rejected, or vended-credentials disallowed for an external/federated catalog), an invalid access-delegation request could still register/overwrite the table and then fail the HTTP call. Consider resolving/validating the delegation mode (and any feature-flag gating) before performing the register/overwrite side effect, so error responses donβt leave partially-applied state.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r2919904143
##########
runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractIcebergCatalogHandlerAuthzTest.java:
##########
@@ -593,18 +603,6 @@ public String metadataLocation() {
.createTests();
}
- @TestFactory
- Stream<DynamicNode> testLoadTablePrivileges() {
Review Comment:
I moved this test down below because it was misplaced.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r2941563341
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -600,26 +600,50 @@ public LoadTableResponse createTableStaged(
*
* @param namespace The namespace to register the table in
* @param request the register table request
+ * @param delegationModes the access delegation modes to use
+ * @param refreshCredentialsEndpoint the refresh credentials endpoint to use
* @return ETagged {@link LoadTableResponse} to uniquely identify the table metadata
*/
- public LoadTableResponse registerTable(Namespace namespace, RegisterTableRequest request) {
+ public LoadTableResponse registerTable(
+ Namespace namespace,
+ RegisterTableRequest request,
+ EnumSet<AccessDelegationMode> delegationModes,
+ Optional<String> refreshCredentialsEndpoint) {
+
+ request.validate();
TableIdentifier identifier = TableIdentifier.of(namespace, request.name());
boolean overwrite = request.overwrite();
+ Set<PolarisStorageActions> actionsRequested =
+ authorizeRegisterTable(identifier, delegationModes, overwrite);
+
if (overwrite) {
- authorizeCreateTableLikeUnderNamespaceOperationOrThrow(
- PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE, identifier);
- return registerTableWithOverwrite(identifier, request);
+ return registerTableWithOverwrite(
+ identifier, request, delegationModes, actionsRequested, refreshCredentialsEndpoint);
}
- // Creating new table requires REGISTER_TABLE privilege
- PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REGISTER_TABLE;
- authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, identifier);
- return catalogHandlerUtils().registerTable(baseCatalog, namespace, request);
+ Table table = baseCatalog.registerTable(identifier, request.metadataLocation());
+
+ if (table instanceof BaseTable baseTable) {
+ TableMetadata tableMetadata = baseTable.operations().current();
+ return buildLoadTableResponseWithDelegationCredentials(
Review Comment:
Could you add/update an integration test to ensure `registerTable` responses contain vended credentials now?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274164850
##########
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:
##########
@@ -708,15 +708,101 @@ public void testCreateTableWithOverriddenBaseLocationMustResideInNsDirectory() {
.isInstanceOf(ForbiddenException.class);
}
+ /**
+ * Create an INTERNAL catalog. Register a table WITH access delegation and verify that the
+ * registerTable response contains vended credentials (when supported by the storage type).
+ */
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegation() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ catalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = catalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
+ /**
+ * Create an EXTERNAL catalog with credential vending enabled. Register a table WITH access
+ * delegation and verify that the registerTable response contains vended credentials (when
+ * supported by the storage type).
+ */
+ @CatalogConfig(
+ value = Catalog.TypeEnum.EXTERNAL,
+ properties = {"polaris.config.enable.credential.vending", "true"})
+ @RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
+ @Test
+ public void testRegisterTableWithAccessDelegationForExternalCatalog() {
+ Namespace ns1 = Namespace.of("ns1");
+ restCatalog.createNamespace(ns1);
+ TableMetadata tableMetadata =
+ TableMetadata.newTableMetadata(
+ new Schema(List.of(Types.NestedField.required(1, "col1", new Types.StringType()))),
+ PartitionSpec.unpartitioned(),
+ externalCatalogBaseLocation + "/ns1/my_table",
+ Map.of());
+ try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
+ initializeClientFileIO(resolvingFileIO);
+ resolvingFileIO.setConf(new Configuration());
+ String fileLocation = externalCatalogBaseLocation + "/ns1/my_table/metadata/v1.metadata.json";
+ TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
+ try {
+ LoadTableResponse registerResponse =
+ catalogApi.registerTableWithAccessDelegation(
+ currentCatalogName, ns1, "my_table", fileLocation);
+
+ assertThat(registerResponse).isNotNull();
+ assertThat(registerResponse.tableMetadata()).isNotNull();
+ assertThat(registerResponse.tableMetadata().location()).isEqualTo(tableMetadata.location());
+ assertThat(registerResponse.metadataLocation()).isEqualTo(fileLocation);
+
+ if (getStorageConfigInfo().getStorageType() != StorageConfigInfo.StorageTypeEnum.FILE) {
+ assertThat(registerResponse.credentials())
+ .as("Cloud storage should vend credentials")
+ .isNotEmpty();
+ }
+ } finally {
+ resolvingFileIO.deleteFile(fileLocation);
+ }
+ }
+ }
+
/**
* Create an EXTERNAL catalog. The test configuration, by default, disables access delegation for
- * EXTERNAL catalogs, so register a table and try to load it with the REST client configured to
- * try to fetch vended credentials. Expect a ForbiddenException.
+ * EXTERNAL catalogs, so try to register a table with the REST client configured to try to fetch
+ * vended credentials. Expect a ForbiddenException.
*/
@CatalogConfig(Catalog.TypeEnum.EXTERNAL)
@RestCatalogConfig({"header.X-Iceberg-Access-Delegation", "vended-credentials"})
@Test
- public void testLoadTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
+ public void testRegisterTableWithAccessDelegationForExternalCatalogWithConfigDisabled() {
Review Comment:
I could not design such a test. The test framework either enables or disables vended credentials for the entire test. Thus, in order to load a table with access delegation on, I first need to create such a table; but then, the create-table operation fails, and we never get to the load-table operation.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274217508
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -631,7 +655,9 @@ private LoadTableResponse registerTableWithOverwrite(
Table table = icebergCatalog.registerTable(identifier, request.metadataLocation(), true);
if (table instanceof BaseTable baseTable) {
TableMetadata metadata = baseTable.operations().current();
- return LoadTableResponse.builder().withTableMetadata(metadata).build();
+ return buildLoadTableResponseWithDelegationCredentials(
+ identifier, metadata, delegationModes, actionsRequested, refreshCredentialsEndpoint)
+ .build();
}
throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
Review Comment:
I agree that the current message is cryptic, but your suggestion leaks internal implementation details to clients, so I'm a bit reluctant to follow it.
OTOH, this `throw` statement is imho never reached in practice.
How about:
```java
throw new IllegalStateException(
"Cannot register table %s: unknown table format".formatted(identifier));
```
?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [Iceberg 1.11] Support access delegation in registerTable [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3734:
URL: https://github.com/apache/polaris/pull/3734#discussion_r3274300755
##########
runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java:
##########
@@ -808,6 +834,44 @@ private Set<PolarisStorageActions> authorizeLoadTable(
return actionsRequested;
}
+ private Set<PolarisStorageActions> authorizeRegisterTable(
+ TableIdentifier tableIdentifier,
+ EnumSet<AccessDelegationMode> delegationModes,
+ boolean overwrite) {
+
+ if (delegationModes.isEmpty()) {
+ PolarisAuthorizableOperation op =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE
+ : PolarisAuthorizableOperation.REGISTER_TABLE;
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(op, tableIdentifier);
+ return Set.of();
+ }
+
+ PolarisAuthorizableOperation readOp =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE_WITH_READ_DELEGATION
+ : PolarisAuthorizableOperation.REGISTER_TABLE_WITH_READ_DELEGATION;
+ PolarisAuthorizableOperation writeOp =
+ overwrite
+ ? PolarisAuthorizableOperation.REGISTER_TABLE_OVERWRITE_WITH_WRITE_DELEGATION
+ : PolarisAuthorizableOperation.REGISTER_TABLE_WITH_WRITE_DELEGATION;
+
+ Set<PolarisStorageActions> actionsRequested =
+ EnumSet.of(PolarisStorageActions.READ, PolarisStorageActions.LIST);
+
+ try {
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(writeOp, tableIdentifier);
+ actionsRequested.add(PolarisStorageActions.WRITE);
+ } catch (ForbiddenException e) {
+ authorizeCreateTableLikeUnderNamespaceOperationOrThrow(readOp, tableIdentifier);
+ }
+
+ checkAllowExternalCatalogCredentialVending(delegationModes);
Review Comment:
Yes, for non-overwrite scenarios only.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org