Skip to content

Conversation

@XJDKC
Copy link
Member

@XJDKC XJDKC commented Oct 4, 2025

Milestones

This is Part 4 of the [Splitting] Initial SigV4 Auth Support for Catalog Federation. Upcoming parts will build on this system:

Introduction

This PR introduces a flexible credential management system for Polaris. Building on Part 3's service identity management, this system combines Polaris service identities with user-provided authentication parameters to generate credentials for remote catalog access.
The core of this PR is the new ConnectionCredentialVendor interface, which:

  • Generates connection credentials by combining service identity with user auth parameters
  • Supports different authentication types (AWS SIGV4, AZURE Entra, GCP IAM) through CDI, currently only supports SigV4.
  • Provides on-demand credential generation
  • Enables easy extension for new authentication types

In the long term, we should move the storage credential management logic out of PolarisMetastoreManager, PolarisMetastoreManager should only provide persistence interfaces.

Key Components

  1. ConnectionCredentialVendor
    The central interface that defines how connection credentials are generated. It combines Polaris service identities with user-provided authentication parameters to produce the final credentials needed for remote catalog access. This interface serves as the foundation for all authentication type-specific implementations.

  2. DefaultPolarisCredentialManager
    The primary implementation that orchestrates credential generation. It uses CDI to automatically select the appropriate vendor based on authentication type, delegates the credential generation process, and provides consistent error handling. This class integrates with the ServiceIdentityProvider from Part 3 to resolve Polaris service identities.

  3. SigV4ConnectionCredentialVendor
    A reference implementation for AWS SigV4 authentication. It handles the complex process of resolving AWS IAM credentials from service identities, performing AWS STS AssumeRole operations, and generating temporary credentials for catalog access. This implementation demonstrates best practices for vendor development.

  4. @SupportsAuthType
    A CDI qualifier annotation that marks vendor implementations with their supported authentication types. This enables automatic vendor selection at runtime while maintaining type safety. The qualifier is essential for the CDI-based pluggable architecture.

Future Improvements

  • Add credential caching support: provide a unified cache for storage creds and connection creds
  • Migrate storage creds to this new framework

@XJDKC XJDKC changed the title [DRAFT] SigV4 Auth Support for Catalog Federation - Part 4: Connection Credential Manager SigV4 Auth Support for Catalog Federation - Part 4: Connection Credential Manager Oct 6, 2025
@XJDKC XJDKC marked this pull request as ready for review October 6, 2025 15:28
@HonahX HonahX self-requested a review October 6, 2025 15:43

@Override
public @Nonnull ConnectionCredentials getConnectionCredentials(
@Nonnull ConnectionConfigInfoDpo connectionConfig) {
Copy link
Member Author

Choose a reason for hiding this comment

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

In the future, we may embed creds cache in the credential manager, if we can't find a valid entry in the cache, we will select the correct vendor and delegate the credential retrieval to the credential vendor (for both storage and connection).

In this way, we can deprecate the old flow (using metastore to get the subscoped creds).

Since we need to generate cache key and may need realm id and the catalog id, wandering if we should pass in the whole catalog entity here. But we can refactor this later once we add cache support for credential manager.

cc: @dimas-b @dennishuo @HonahX

Copy link
Contributor

@dimas-b dimas-b left a comment

Choose a reason for hiding this comment

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

LGTM overall 👍 Thanks @XJDKC ! Some comments below... mostly about CDI.

Copy link
Contributor

@HonahX HonahX left a comment

Choose a reason for hiding this comment

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

This looks great!

AssumeRoleRequest.Builder requestBuilder =
AssumeRoleRequest.builder()
.roleArn(sigv4Params.getRoleArn())
.roleSessionName(
Copy link
Contributor

Choose a reason for hiding this comment

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

Though this is probably fine for most use cases since the assumeRole session credential doesn't ever (normally) leave the Catalog server itself (in contrast to StorageIntegration ones where we need to vend it out), we should probably still find a way to provide a hook for adding a sessionPolicy here.

Maybe at least a TODO. A "simple" approach would be to allow configuring a whole service-level scoping policy string that would rely on wildcards to share across catalogs/realms.

More advanced would be to derive the policyString from a combination of the Type in the connectionConfig, and the service-level configuration.

If we ever do refactor to merge this for Catalog and Storage we at least would need to abstract out the sessionPolicy generation

Copy link
Member Author

@XJDKC XJDKC Oct 7, 2025

Choose a reason for hiding this comment

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

Good point, since we don't vend / return this credentials to the client, so it should be fine.

For the simple approach, we need to use different service-level scoping policy for different services (based on the sigv4 signing name). e.g., if the service is

  • glue we need to get glue:ListTables, ``glue:ListDatabases`, e.t.c,
    • We may also need some privileges on Lake Formation so that we can get the vended credentials, if we want to use the vended credentials to load table metadata rather than using the storage config.
  • execute-api (api gateway), we need to use execute-api:Invoke
  • s3tables: we need another set of privileges.

I will add a TODO for now since I need to spend some time to figure out the correct policy string for each service. We may need a refactor on the policy generation.

String.class, AwsProperties.REST_SECRET_ACCESS_KEY, "the aws access key secret", true),
AWS_SESSION_TOKEN(
String.class, AwsProperties.REST_SESSION_TOKEN, "the aws scoped access token", true),
EXPIRATION_TIME(
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 actually need this to be an enum value? I do not see any real usage of it 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

I just follow the StorageAccessProperty. If we want to remove CatalogAccessProperty, we should also deprecate StorageAccessProperty later.

I think initially, the reason we add the StorageAccessProperty is because we want all the storage credentials related properties must be explicitly defined in the num class, otherwise, AccessConfig is just an open-end property map.

Copy link
Contributor

Choose a reason for hiding this comment

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

StorageAccessProperty.EXPIRATION_TIME is actually referenced in code, while this one is not 🤔

Copy link
Member Author

@XJDKC XJDKC Oct 7, 2025

Choose a reason for hiding this comment

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

StorageAccessProperty.EXPIRATION_TIME is also not referenced in the callee, we just use it to add expiration_time property to the AccessConfig in AzureCredentialsStorageIntegration and AwsCredentialStorageIntegration (the equivalent of ConnectionCredentialVendor)

Copy link
Member Author

@XJDKC XJDKC Oct 7, 2025

Choose a reason for hiding this comment

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

Another usage of this enum class is:
It's a bridge between polaris and iceberg sdk. Polaris can understand this enum class, but we need to convert it to the property that iceberg sdk can understands.
Considering this, I prefer to keep it as it's.

i.e., Inside polaris, we will always use this enum class to refer the property, when we need to use iceberg sdk, like RESTCatalog and FileIO, we will convert the property to string-based property that iceberg sdk can understand.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would we end up using the same expiration-time between different auth types in the future?

I recall StorageAccessProperty.EXPIRATION_TIME being more of the deprecated field, where we prefer AWS_SESSION_TOKEN_EXPIRES_AT_MS to be more specific about what it is. That one also has the s3 prefix: s3.session-token-expires-at-ms.

Is there ever a situation where we might need to put an S3 credential into the same config map as a sigv4 catalog-connection credential?

In that case we'd need separate expiration times as well if they're not in separate tuples. Following the same convention of the rest. prefix used in AwsProperties, we'd then want this to be rest.session-token-expires-at-ms.

}

// Delegate to the vendor to generate credentials
return selectedVendor.get().getConnectionCredentials(connectionConfig);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since DefaultPolarisCredentialManager multiplexes over type-specific lower level implementations, having them under the same java interface (ConnectionCredentialVendor) does not sound right to me.

If a ConnectionCredentialVendor is impl. it type-specific, then DefaultPolarisCredentialManager should not be a sub-type of ConnectionCredentialVendor because it is not type-specific.

All calls are made via the PolarisCredentialManager interface.

WDYT about detaching PolarisCredentialManager from ConnectionCredentialVendor but keeping current DefaultPolarisCredentialManager code?

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree it might look a bit confusing right now since PolarisCredentialManager doesn't define additional methods and everything still lives under ConnectionCredentialVendor.

The main reason I introduced the PolarisCredentialManager interface early is to establish a clear separation of concerns before we add StorageCredentialVendor and potentially other vendor types. The goal is for PolarisCredentialManager to act as the central entry point for all credential management (including caching and multiplexing), while ConnectionCredentialVendor represents just one of several possible vendor implementations. i.e., The PolarisCredentialManager is also a Connection Credential Vendor.

So even though it looks slightly redundant in this PR, it helps set up a cleaner, more extensible structure for the upcoming changes and avoids unnecessary refactoring later. I'm happy to add a short comment or javadoc note to clarify that intent if it helps.

I'd prefer to keep PolarisCredentialManager implement ConnectionCredentialVendor for now.
But if you feel strongly about separating it, I can also duplicate the method in PolarisCredentialManager and make it a standalone interface.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you suggesting that in the future PolarisCredentialManager will extend ConnectionCredentialVendor and some other AbcCredentialVendor and DefCredentialVendor?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, if we want to migrate the storage credential related to this new framework, we need to make PolarisCredentialManager extends StorageCredentialVendor as well.

interface PolarisCredentialManager implements ConnectionCredentialVendor, StorageCredentialVendor {}

class DefaultPolarisCredentialManager implements PolarisCredentialManager {
  private AccessCredsCache accessCredsCache;
  private final Instance<ConnectionCredentialVendor> connectionCredentialVendors;
  private final Instance<StorageCredentialVendor> storageCredentialVendors;

  @Override
  public @Nonnull ConnectionCredentials getConnectionCredentials(
      @Nonnull ConnectionConfigInfoDpo connectionConfig) {
    // 1. generate cache key
    // 2. check if there is a valid connection credential in the cache
    // 3. if yes, get the credential from cache and return it directly
    // 4. If not, select the credential vendor based on Auth Type
    // 5. Delegate to the connection credential vendor to fetch the connection credentials
    // 6. Store the connection credentials in the cache
    // 7. return the connection credentials
  }

  @Override
  public @Nonnull StorageAccessConfig getSubscopedStorageCreds(
      boolean allowListOperation,
      @Nonnull Set<String> allowedReadLocations,
      @Nonnull Set<String> allowedWriteLocations,
      Optional<String> refreshCredentialsEndpoint) {
    // 1. generate cache key
    // 2. check if there is a valid storage credential in the cache
    // 3. if yes, get the credential from cache and return it directly
    // 4. If not, select the credential vendor based on Storage Type
    // 5. Delegate to the storage credential vendor to fetch the storage credentials
    // 6. Store the storage credentials in the cache
    // 7. return the storage credentials
  }
}

Copy link
Contributor

@dimas-b dimas-b Oct 7, 2025

Choose a reason for hiding this comment

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

that approach is fine from my POV, except that I do not think PolarisCredentialManager is necessary as an interface... Why not implement all of those "leaf" interfaces in the DefaultPolarisCredentialManager class?

Copy link
Member Author

@XJDKC XJDKC Oct 8, 2025

Choose a reason for hiding this comment

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

You are right, but that's why there are some ambiguities: take a look into the code I posted above, if we remove PolarisCredentialManager and define DefaultPolarisCredentialManager like that, we have SigV4ConnectionCredentialVendor and DefaultPolarisCredentialManager and both of them inherit ConnectionCredentialVendor. If the caller uses ConnectionCredentialVendor as the variable type, which object the caller will get. DefaultPolarisCredentialManager can get the correct one because it will select the candidate based on the authentication type, but if we just define @Inject ConnectionCredentialVendor credentialVendor, the CDI framework can't tell which one should be used.

PolarisCredentialManager is the multiplexing layer, the idea is that, for the caller, if you need a connection credential, or a storage credential, just use CDI to get a PolarisCredentialManager, pass in the needed info, then PolarisCredentialManager will handle all the things for you, e.g., forwarding the calls to the actual credential vendor, cache the credentials. So, we can't directly inject ConnectionCredentialVendor, we should use a separate interface, and PolarisCredentialManager is the one we are looking for.

Copy link
Contributor

@dimas-b dimas-b Oct 8, 2025

Choose a reason for hiding this comment

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

If the caller uses ConnectionCredentialVendor as the variable type, which object the caller will get [...]

This can be resolved in CDI with the help of "qualifiers". Simple callers get the "default" impl., e.g. the cache / multiplexer, while the cache can further qualify the next level of implementation via @AuthType.

Copy link
Member Author

@XJDKC XJDKC Oct 8, 2025

Choose a reason for hiding this comment

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

Yes, this can't be resolved in CDI, but why do we make things very complicated.

With this approach, when we want to get the DefaultPolarisCredentialManager, we need to filter based on Qualifier.
When we want to get the specific vendor, we need to filter based on @AuthType.

  @Produces
  @RequestScoped
  public ConnectionCredentialVendor connectionCredentialVendor(
      PolarisCredentialManagerConfiguration config,
      @Any Instance<ConnectionCredentialVendor> credentialManagers) {
    return (ConnectionCredentialVendor) credentialManagers.select(Identifier.Literal.of(config.type())).get();
  }

  @Produces
  @RequestScoped
  public StorageCredentialVendor storageCredentialVendor(
      PolarisCredentialManagerConfiguration config,
      @Any Instance<StorageCredentialVendor> credentialManagers) {
    return (StorageCredentialVendor) credentialManagers.select(Identifier.Literal.of(config.type())).get();
  }

Why not just add a new interface that implements all the credential vendors?
That way, whenever we need credentials, we can simply use PolarisCredentialManager. It's cleaner and doesn't introduce any downside.

If vendors want to provide their own DefaultPolarisCredentialManager, they don't need to understand the underlying mechanism and also follow this pattern. (i.e., providing two producers and return different vendor type).

And the callers also don't need to understand that the one they are using is not the specific ConnectionCredentialVendor but the DefaultPolarisCredentialManager which has the cache logic and the multiplexing logic.

Copy link
Contributor

@dimas-b dimas-b Oct 8, 2025

Choose a reason for hiding this comment

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

let's revisit later :) I think current code is functional and clear enough for maintenance.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds good, happy to discuss this further if needed!

@dimas-b
Copy link
Contributor

dimas-b commented Oct 7, 2025

It feels like we're getting into somewhat hypothetical and a bit too abstract discussions here 🙂 I do not want to block progress on the Catalog Federation feature, so I'd be ok with merging this PR "as is" if other reviewers more familiar with the feature and intended final state of the code approve.

@XJDKC
Copy link
Member Author

XJDKC commented Oct 7, 2025

It feels like we're getting into somewhat hypothetical and a bit too abstract discussions here 🙂 I do not want to block progress on the Catalog Federation feature, so I'd be ok with merging this PR "as is" if other reviewers more familiar with the feature and intended final state of the code approve.

Thanks Dmitri, the runtime logic can always be evolved and refined later. There are still many things we need to do for catalog federation, so we can continue the discussion about the interface in future PRs!

cc: @dennishuo @HonahX

HonahX
HonahX previously approved these changes Oct 7, 2025
Copy link
Contributor

@HonahX HonahX left a comment

Choose a reason for hiding this comment

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

Thanks @dimas-b for the thorough review on this! I think we've had a lot constructive and thoughtful discussions. The remaining points, as you mentioned, are more forward-looking points could be addressed when we actually add those features/refactorings.

With this and the fact that catalog federation is well-guarded by a param, I vote +1 on this to support federate to Glue IRC

@github-project-automation github-project-automation bot moved this from PRs In Progress to Ready to merge in Basic Kanban Board Oct 7, 2025
Copy link
Contributor

@dennishuo dennishuo left a comment

Choose a reason for hiding this comment

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

Generally LGTM, just a comment about the naming of the expiration-time property. We could fixup in a followup if needed

String.class, AwsProperties.REST_SECRET_ACCESS_KEY, "the aws access key secret", true),
AWS_SESSION_TOKEN(
String.class, AwsProperties.REST_SESSION_TOKEN, "the aws scoped access token", true),
EXPIRATION_TIME(
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we end up using the same expiration-time between different auth types in the future?

I recall StorageAccessProperty.EXPIRATION_TIME being more of the deprecated field, where we prefer AWS_SESSION_TOKEN_EXPIRES_AT_MS to be more specific about what it is. That one also has the s3 prefix: s3.session-token-expires-at-ms.

Is there ever a situation where we might need to put an S3 credential into the same config map as a sigv4 catalog-connection credential?

In that case we'd need separate expiration times as well if they're not in separate tuples. Following the same convention of the rest. prefix used in AwsProperties, we'd then want this to be rest.session-token-expires-at-ms.

@HonahX
Copy link
Contributor

HonahX commented Oct 8, 2025

Thanks @XJDKC @dennishuo @dimas-b for reviewing! Given the size of the PR I propose to do non-urgent small changes in follow-up for easier reviewing process.

@HonahX HonahX merged commit 519e127 into apache:main Oct 8, 2025
16 checks passed
@github-project-automation github-project-automation bot moved this from Ready to merge to Done in Basic Kanban Board Oct 8, 2025
@XJDKC
Copy link
Member Author

XJDKC commented Oct 8, 2025

Generally LGTM, just a comment about the naming of the expiration-time property. We could fixup in a followup if needed

Good catch! I also looked into the Iceberg SDK, unfortunately, there isn't currently a property that indicates the expiration time of the token/credential for remote catalog access. So for now, I reused the expiration-time property, which is already used by StorageAccessProperty.

I can modify this in a follow up PR!

snazy added a commit to snazy/polaris that referenced this pull request Nov 20, 2025
* Build: remove code to post-process generated Quarkus jars (apache#2667)

Before Quarkus 3.28, the Quarkus generated jars used the "current" timestamp for all ZIP entries, which made the jars not-reproducible.
Since Quarkus 3.28, the generated jars use a fixed timestamp for all ZIP entries, so the custom code is no longer necessary.

This PR depends on Quarkus 3.28.

* Update docker.io/jaegertracing/all-in-one Docker tag to v1.74.0 (apache#2751)

* Updating metastore documentation with Aurora postgres example (apache#2706)

* added Aurora postgres to metastore documentation

* Service: Add events for APIs awaiting API changes (apache#2712)

* fix(enhancement): add .idea, .vscode, .venv to top level .gitignore (apache#2718)

fix(enhancement): add .idea, .vscode, .venv to top level .gitignore

* Fix javadocs of `PolarisPrincipal.getPrincipalRoles()` (apache#2752)

* fix(enhancement): squash commits (apache#2643)

* fix(deps): update dependency io.smallrye.config:smallrye-config-core to v3.14.1 (apache#2755)

* Extract interface for RequestIdGenerator (apache#2720)

Summary of changes:

1. Extracted an interface from `RequestIdGenerator`.
2. The `generateRequestId` method now returns a `Uni<String>` in case custom implementations need to perform I/O or other blocking calls during request ID generation.
3. Also addressed comments in apache#2602.

* JDBC: Handle schema evolution (apache#2714)

* Deprecate legacy management endpoints for removal (apache#2749)

* Deprecate LegacyManagementEndpoints for removal

* Add PolarisResolutionManifestCatalogView.getResolvedCatalogEntity helper (apache#2750)

this centralizes some common code and simplifies some test setups

* Enforce that S3 credentials are vended when requested (apache#2711)

This is a follow-up change to apache#2672 striving to improve user-facing error reporting for S3 storage systems without STS.

* Add property to `AccessConfig` to indicate whether the backing storage integration can produce credentials.

* Add a check to `IcebergCatalogHandler` (leading to 400) that storage credentials are vended when requested and the backend is capable of vending credentials in principle.

* Update `PolarisStorageIntegrationProviderImpl` to indicate that FILE storage does not support credential vending (requesitng redential vending with FILE storage does not produce any credentials and does not flag an error, which matches current Polaris behaviour).

* Only those S3 systems where STS is not available (or disabled / not permitted) are affected.

* Other storage integrations are not affected by this PR.

* [Catalog Federation] Ignore JIT entities when deleting federated catalogs, add integration test for namespace/table-level RBAC (apache#2690)

When enabling table/namespace level RBAC in federated catalog, JIT entities will be created during privilege grant. In the short term, we should ignore them when dropping the catalog. In the long term, we will clean-up those entities when deleting the catalog.

This will be the first step towards JIT entity clean-up:

1. Ignore JIT entities when dropping federated catalog (orphan entities)
2. Register tasks/in-place cleanup JIT entities during catalog drop
3. Add new functionality to PolarisMetastoreManager to support atomic delete non-used JIT entities during revoke.
4. Global Garbage Collector to clean-up unreachable entities (entities with non-existing catalog path/parent)

* SigV4 Auth Support for Catalog Federation - Part 3: Service Identity Info Injection (apache#2523)

This PR introduces service identity management for SigV4 Auth Support for Catalog Federation. Unlike user-supplied parameters, the service identity represents the identity of the Polaris service itself and should be managed by Polaris.

* Service Identity Injection

* Return injected service identity info in response

* Use AwsCredentialsProvider to retrieve the credentials

* Move some logic to ServiceIdentityConfiguration

* Rename ServiceIdentityRegistry to ServiceIdentityProvider

* Rename ResolvedServiceIdentity to ServiceIdentityCredential

* Simplify the logic and add more tests

* Use SecretReference and fix some small issues

* Disable Catalog Federation

* Update actions/stale digest to 5f858e3 (apache#2758)

* Service: RealmContextFilter test refactor (apache#2747)

* Update dependency software.amazon.awssdk:bom to v2.35.0 (apache#2760)

* Update apache/spark Docker tag to v3.5.7 (apache#2727)

* Update eric-maynard Team entry (apache#2763)

I'm no longer affiliated with Snowflake, so we should update this page accordingly

* Refactor resolutionManifest handling in PolarisAdminService (apache#2748)

- remove mutable `resolutionManifest` field in favor of letting the
  "authorize" methods return their `PolarisResolutionManifest`
- replace "find" helpers with "get" helpers that have built-in error
  handling

* Implement Finer Grained Operations and Privileges For Update Table (apache#2697)

This implements finer grained operations and privileges for update table in a backwards compatible way as discussed on the mailing list.

The idea is that all the existing privileges and operations will work and continue to work even after this change. (i.e. TABLE_WRITE_PROPERTIES will still ensure update table is authorized even after these changes).

However, because Polaris will now be able to identify each operation within an UpdateTable request and has a privilege model with inheritance that maps to each operation, users will now have the option of restricting permissions at a finer level if desired.

* [Python CLI][CI Failure] Pin pydantic version to < 2.12.0 to fix CI failure (apache#2770)

* Delete ServiceSecretReference (apache#2768)

* JDBC: Fix Bootstrap with schema options (apache#2762)

* Site: Add puppygraph integration (apache#2753)

* Update Changelog with finer grained authz (apache#2775)

* Add Arguments to Various Event Records (apache#2765)

* Update immutables to v2.11.5 (apache#2776)

* Client: add support for policy management (apache#2701)

Implementation for policy management via Polaris CLI (apache#1867).

Here are the subcommands to API mapping:

attach
 - PUT /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}/mappings
create
 - POST /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}/mappings
delete
 - DELETE /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}
detach
 - POST /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}/mappings
get
 - GET /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}
list
 - GET /polaris/v1/{prefix}/namespaces/{namespace}/policies 
   - This is default for `list` operation
 - GET /polaris/v1/{prefix}/applicable-policies
   - This is when we have `--applicable` option provided
update
 - PUT /polaris/v1/{prefix}/namespaces/{namespace}/policies/{policy-name}

* Update dependency com.google.cloud:google-cloud-storage-bom to v2.58.1 (apache#2764)

* Update dependency org.jboss.weld:weld-junit5 to v5.0.3.Final (apache#2777)

* Update the LICENSE and NOTICE files in the runtime (apache#2779)

* SigV4 Auth Support for Catalog Federation - Part 4: Connection Credential Manager (apache#2759)

This PR introduces a flexible credential management system for Polaris. Building on Part 3's service identity management, this system combines Polaris service identities with user-provided authentication parameters to generate credentials for remote catalog access.
The core of this PR is the new ConnectionCredentialVendor interface, which:

Generates connection credentials by combining service identity with user auth parameters
Supports different authentication types (AWS SIGV4, AZURE Entra, GCP IAM) through CDI, currently only supports SigV4.
Provides on-demand credential generation
Enables easy extension for new authentication types
In the long term, we should move the storage credential management logic out of PolarisMetastoreManager, PolarisMetastoreManager should only provide persistence interfaces.

* Extract IcebergCatalog.getAccessConfig to a separate class AccessConfigProvider (apache#2736)

This PR extracts credential vending entrypoint getAccessConfig from IcebergCatalog into a new centralized AccessConfigProvider class, decoupling credential generation from catalog implementations.

The old SupportsCredentialVending is removed in this PR upon discussion

* Update immutables to v2.11.6 (apache#2780)

* Enhance Release docs (apache#2787)

* Spark: Remove unnecessary dependency (apache#2789)

* Update Pull Request Template (apache#2788)

* Freeze 1.2 change log (apache#2783)

* [Catalog Federation] Enable Credential Vending for Passthrough Facade Catalog (apache#2784)

This PR introduces credential vending support for passthrough-facade catalogs.

When creating a passthrough-facade catalog, the configuration currently requires two components:

StorageConfig – specifies the storage info for the remote catalog.
ConnectionInfo – defines connection parameters for the underlying remote catalog.

With this change, the StorageConfig is now also used to vend temporary credentials for user requests.
Credential vending honors table-level RBAC policies to determine whether to issue read-only or read-write credentials, ensuring access control consistency with Polaris authorization semantics.

A new test case validates the credential vending workflow, verifying both read and write credential vending.

Note: the remote catalog referenced by the passthrough-facade does not need to support IRC

* Site: Add docs for catalog federation (apache#2761)

* Python client: update CHANGELOG.MD for recent changes (apache#2796)

* Python client: remove Python 3.9 support (apache#2795)

* Update dependency software.amazon.awssdk:bom to v2.35.5 (apache#2799)

* FIX REG tests with cloud providers (apache#2793)

* [Catalog Federation] Block credential vending for remote tables outside allowed location list (apache#2791)

* Correct invalid example in management service OpenAPI spec (apache#2801)

The `example` was incorrectly placed as a sibling of `$ref` within a `schema` object in `polaris-management-service.yml`. According to the OpenAPI specification, properties that are siblings of a `$ref` are ignored.

This was causing a `NullPointerException` in OpenAPI Generator v7.13.0+ due to a change in how examples are processed. The generator now expects all `examples` to be valid and non-empty, and a misplaced `example` can lead to a null reference when the generator tries to access it (we are not yet using v7.13.0+, thus not a problem at the moment).

This commit moves the `example` to be a sibling of the `schema` object, which is the correct placement according to the OpenAPI specification.

Reference error when using newer version of openapi-generator-cli:
```
openapi-generator-cli generate -i spec/polaris-catalog-service.yaml -g python -o client/python --additional-properties=packageName=polaris.catalog --additional-properties=apiNameSuffix="" --skip-validate-spec --additional-properties=pythonVersion=3.13 --ignore-file-override /local/client/python/.openapi-generator-ignore 
...
  Exception: Cannot invoke "io.swagger.v3.oas.models.examples.Example.getValue()" because the return value of "java.util.Map.get(Object)" is null
	at org.openapitools.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:1606)
	at org.openapitools.codegen.DefaultGenerator.processPaths(DefaultGenerator.java:1474)
	at org.openapitools.codegen.DefaultGenerator.generateApis(DefaultGenerator.java:663)
	at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:1296)
	at org.openapitools.codegen.cmd.Generate.execute(Generate.java:535)
	at org.openapitools.codegen.cmd.OpenApiGeneratorCommand.run(OpenApiGeneratorCommand.java:32)
	at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:66)
Caused by: java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.examples.Example.getValue()" because the return value of "java.util.Map.get(Object)" is null
	at org.openapitools.codegen.utils.ExamplesUtils.unaliasExamples(ExamplesUtils.java:75)
	at org.openapitools.codegen.DefaultCodegen.unaliasExamples(DefaultCodegen.java:2343)
	at org.openapitools.codegen.DefaultCodegen.fromResponse(DefaultCodegen.java:4934)
	at org.openapitools.codegen.DefaultCodegen.fromOperation(DefaultCodegen.java:4575)
	at org.openapitools.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:1574)
	... 6 more
```

* Update dependency io.opentelemetry:opentelemetry-bom to v1.55.0 (apache#2804)

* Update dependency io.micrometer:micrometer-bom to v1.15.5 (apache#2806)

* Bump version for python deps (apache#2800)

* bump version for python deps

* bump version for python deps

* bump version for python deps

* Update openapi-generatr-cli from 7.11.0.post0 to 7.12.0

* Pin poetry version

* Pin poetry version

* Update dependency io.projectreactor.netty:reactor-netty-http to v1.2.11 (apache#2809)

* [Catalog Federation] Add Connection Credential Vendors for Other Auth Types (apache#2782)

Add Connection Credential Vendors for Other Auth Types

This change is a prerequisite for enabling connection credential caching.
By making PolarisCredentialManager the central entry point for obtaining connection credentials, we can introduce caching cleanly and manage all credential flows in a consistent way.

* Last merged commit 6b957ec

---------

Co-authored-by: Mend Renovate <bot@renovateapp.com>
Co-authored-by: fabio-rizzo-01 <fabio.rizzocascio@jpmorgan.com>
Co-authored-by: Adnan Hemani <adnan.h@berkeley.edu>
Co-authored-by: Artur Rakhmatulin <artur.rakhmatulin@gmail.com>
Co-authored-by: Alexandre Dutra <adutra@apache.org>
Co-authored-by: Prashant Singh <35593236+singhpk234@users.noreply.github.com>
Co-authored-by: Christopher Lambert <xn137@gmx.de>
Co-authored-by: Dmitri Bourlatchkov <dmitri.bourlatchkov@gmail.com>
Co-authored-by: Honah (Jonas) J. <honahx@apache.org>
Co-authored-by: Rulin Xing <xjdkcsq3@gmail.com>
Co-authored-by: Eric Maynard <eric.maynard+oss@snowflake.com>
Co-authored-by: Travis Bowen <122238243+travis-bowen@users.noreply.github.com>
Co-authored-by: Jaz Ku <jsku@dons.usfca.edu>
Co-authored-by: Yong Zheng <yongzheng0809@gmail.com>
Co-authored-by: JB Onofré <jbonofre@apache.org>
Co-authored-by: Yufei Gu <yufei@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants