dimas-b commented on code in PR #2736: URL: https://github.com/apache/polaris/pull/2736#discussion_r2411509105
########## runtime/service/src/main/java/org/apache/polaris/service/catalog/io/AccessConfigProvider.java: ########## @@ -0,0 +1,135 @@ +/* + * 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. + */ + +package org.apache.polaris.service.catalog.io; + +import jakarta.annotation.Nonnull; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.util.Optional; +import java.util.Set; +import org.apache.iceberg.TableMetadata; +import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.polaris.core.context.CallContext; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.persistence.MetaStoreManagerFactory; +import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper; +import org.apache.polaris.core.storage.AccessConfig; +import org.apache.polaris.core.storage.PolarisStorageActions; +import org.apache.polaris.core.storage.StorageUtil; +import org.apache.polaris.core.storage.cache.StorageCredentialCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides temporary, scoped credentials for accessing table data in object storage (S3, GCS, Azure + * Blob Storage). + * + * <p>This provider decouples credential vending from catalog implementations, and should be the + * primary entrypoint to get sub-scoped credentials for accessing table data. + */ +@ApplicationScoped +public class AccessConfigProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccessConfigProvider.class); + + private final StorageCredentialCache storageCredentialCache; + private final MetaStoreManagerFactory metaStoreManagerFactory; + + @Inject + public AccessConfigProvider( + StorageCredentialCache storageCredentialCache, + MetaStoreManagerFactory metaStoreManagerFactory) { + this.storageCredentialCache = storageCredentialCache; + this.metaStoreManagerFactory = metaStoreManagerFactory; + } + + /** + * Vends credentials for accessing table storage, extracting locations from table metadata. + * + * @param callContext the call context containing realm, principal, and security context + * @param tableIdentifier the table identifier + * @param tableMetadata the table metadata containing storage location URIs + * @param storageActions the storage operations (READ, WRITE, LIST, DELETE) to scope credentials + * to + * @param refreshCredentialsEndpoint optional endpoint URL for clients to refresh credentials + * @param resolvedPath the entity hierarchy to search for storage configuration + * @return {@link AccessConfig} with scoped credentials and metadata; empty if no storage config + * found + */ + public AccessConfig getAccessConfig( + @Nonnull CallContext callContext, + @Nonnull TableIdentifier tableIdentifier, + @Nonnull TableMetadata tableMetadata, + @Nonnull Set<PolarisStorageActions> storageActions, + @Nonnull Optional<String> refreshCredentialsEndpoint, + @Nonnull PolarisResolvedPathWrapper resolvedPath) { + return getAccessConfig( + callContext, + tableIdentifier, + StorageUtil.getLocationsUsedByTable(tableMetadata), Review Comment: minor: I propose to call `getLocationsUsedByTable()` at the call sites and avoid having `TableMetadata` as a "heavy" method parameter here. If you prefer we can add helper methods for that, but I'd prefer the "main" interface method to _not_ have `TableMetadata`. WDYT? ########## runtime/service/src/main/java/org/apache/polaris/service/catalog/io/AccessConfigProvider.java: ########## @@ -0,0 +1,135 @@ +/* + * 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. + */ + +package org.apache.polaris.service.catalog.io; + +import jakarta.annotation.Nonnull; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.util.Optional; +import java.util.Set; +import org.apache.iceberg.TableMetadata; +import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.polaris.core.context.CallContext; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.persistence.MetaStoreManagerFactory; +import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper; +import org.apache.polaris.core.storage.AccessConfig; +import org.apache.polaris.core.storage.PolarisStorageActions; +import org.apache.polaris.core.storage.StorageUtil; +import org.apache.polaris.core.storage.cache.StorageCredentialCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides temporary, scoped credentials for accessing table data in object storage (S3, GCS, Azure + * Blob Storage). + * + * <p>This provider decouples credential vending from catalog implementations, and should be the + * primary entrypoint to get sub-scoped credentials for accessing table data. + */ +@ApplicationScoped +public class AccessConfigProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccessConfigProvider.class); + + private final StorageCredentialCache storageCredentialCache; + private final MetaStoreManagerFactory metaStoreManagerFactory; + + @Inject + public AccessConfigProvider( + StorageCredentialCache storageCredentialCache, + MetaStoreManagerFactory metaStoreManagerFactory) { + this.storageCredentialCache = storageCredentialCache; + this.metaStoreManagerFactory = metaStoreManagerFactory; + } + + /** + * Vends credentials for accessing table storage, extracting locations from table metadata. + * + * @param callContext the call context containing realm, principal, and security context + * @param tableIdentifier the table identifier + * @param tableMetadata the table metadata containing storage location URIs + * @param storageActions the storage operations (READ, WRITE, LIST, DELETE) to scope credentials + * to + * @param refreshCredentialsEndpoint optional endpoint URL for clients to refresh credentials + * @param resolvedPath the entity hierarchy to search for storage configuration + * @return {@link AccessConfig} with scoped credentials and metadata; empty if no storage config + * found + */ + public AccessConfig getAccessConfig( + @Nonnull CallContext callContext, Review Comment: Starting a new thread on call/request context since the other thread got side-tracked a bit. Here's a concrete proposal. `AccessConfigProvider` is currently injected only into request-scoped beans (`IcebergCatalogAdapter`). Let's make `AccessConfigProvider` request-scoped and inject `CallContext` into it (cf. `ServiceProducers.polarisCallContext()`). This interface method will _not_ have a `CallContext` parameter, but `AccessConfigProvider` will have it as a field. When we call `FileIOUtil.refreshAccessConfig()` we'll use the injected `CallContext` from the field (CDI ensures that all related objects have the same request-scoped `CallContext`). This will keep the java interface lean (only carrying parameters specific to getting access config). General parameters (context) are provided via CDI. WDYT? -- 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]
