-
Notifications
You must be signed in to change notification settings - Fork 314
[Catalog Federation] Add Connection Credential Vendors for Other Auth Types #2782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[Catalog Federation] Add Connection Credential Vendors for Other Auth Types #2782
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall 👍 Some comments below.
...core/src/main/java/org/apache/polaris/core/credentials/connection/CatalogAccessProperty.java
Outdated
Show resolved
Hide resolved
// OAuth credentials don't expire - set expiration to Instant.MAX to indicate infinite validity | ||
// If the credential expires, users need to update the catalog entity to rotate the credential. | ||
return ConnectionCredentials.builder() | ||
.putCredential(CatalogAccessProperty.OAUTH2_CREDENTIAL.getPropertyName(), credential) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is nothing in this class that actually relates to the OAuth2 spec as far as I can tell. It only relates to the Iceberg OAuth2Properties.CREDENTIAL
constant, which again has very little to do with OAuth2 RFCs as far as connection configuration is concerned... It's just a property name plus format spec 🤷
What the client does with this property (whether it's OAuth2 or something else) is beyond the scope of this credential vendor. At this level we do not know how the credential is used.
I'd propose to rename this to "Iceberg Credential Vendor".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right, this class currently just retrieves the OAuth credential from UserSecretsManager
and returns it. The PolarisCredentialManager
will then cache it in AccessCredsCache
(not yet implemented, I plan to add that in a follow-up PR) so that we don't need to fetch the credential from UserSecretsManager
every time we make a call, especially if the secret manager doesn't have its own cache.
The main goal of this PR is to make PolarisCredentialManager
the single entry point for credential retrieval so we can centralize the caching logic in one place.
Regarding your suggestion, I agree, it's still beneficial to include OAuth in the class name to make the purpose of this class clear at a glance.
Right now, the class only returns the stored OAuth credential, but in the future, we could extend it to perform the client credentials flow to obtain a temporary token directly here, rather than relying on the Iceberg SDK to fetch a new token for every request.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fully support implementing OAuth2 flows in the future.
However, in its current form this credential vendor provides a simple pair of values, but claims the type of AuthenticationType.OAUTH
. I personally find it misleading 🤔
Even if Polaris supported OAuth2 flows to obtain a token for a catalog connection, this class populates Iceberg's credential
property, which is not a token. This property cannot hold an OAuth2 token. Instead it instruct the (Iceberg) client to perform some activities internally in order to obtain the access token. From the Polaris POV OAuth is not apparent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, how about renaming it to OAuthClientCredentialVendor
then add a real OAuthConnectionCredentialVendor
to perform the oauth2 flow and get a token?
.../org/apache/polaris/service/credentials/connection/BearerConnectionCredentialVendorTest.java
Outdated
Show resolved
Hide resolved
...rg/apache/polaris/service/credentials/connection/ImplicitConnectionCredentialVendorTest.java
Outdated
Show resolved
Hide resolved
...a/org/apache/polaris/service/credentials/connection/OAuthConnectionCredentialVendorTest.java
Outdated
Show resolved
Hide resolved
.../java/org/apache/polaris/service/credentials/connection/SigV4ConnectionCredentialVendor.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! It looks great!
@Override | ||
public @Nonnull Map<String, String> asIcebergCatalogProperties( | ||
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) { | ||
String bearerToken = secretsManager.readSecret(getBearerTokenReference()); | ||
return Map.of(OAuth2Properties.TOKEN, bearerToken); | ||
PolarisCredentialManager credentialManager) { | ||
// Return only metadata properties - credentials are handled by ConnectionCredentialVendor | ||
// Bearer auth has no metadata properties | ||
return Map.of(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make this a default implementation in abstract class AuthenticationParametersDpo
or the interface?
"Catalog federation is enabled but no ConnectionCredentialVendor found for " | ||
+ "authentication type '%s'. External catalog connections using this " | ||
+ "authentication type will fail.", | ||
type), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, would this check be too strong that we only consider it to be production ready if all auth types need the vendor, or this is more like a warning despite it is called "Error"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, naming needs improvement here. An error
production readiness check will not block startup. Only severe
cases break startup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure the check is logically correct. A particular deployment only needs to provide ConnectionCredentialVendor
implementations for auth types that are actually used by created catalogs.
I think the vendor availability is implicitly checked on catalog creation already.
On startup, I think we only need to check types for existing catalogs, not for all types listed in the enum. The latter would put an undue burden on custom deployments.
*/ | ||
@RequestScoped | ||
@AuthType(AuthenticationType.BEARER) | ||
@Priority(100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we extract the priority to some constants class, like FilterPriorities
. It will be easier for custom implementation to use and managed the prioty.
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.PolarisCredentialManager::getConnectionCredentials
will delegate the call to the appropriate credential vendor based on the authentication type:SigV4
->SigV4ConnectionCredentialVendor
ServiceIdentityProvider
: UsesServiceIdentityProvider
to retrieve the IAM user’s AWS credential that represents Polaris’s service identity.StsClient
: Then useStsClient
to assume the user-provided iam role and obtain temporary AWS credentials.OAuth
->OAuthConnectionCredentialVendor
UserSecretsManager
: UsesUserSecretsManager
to retrieve the OAuth2 credential from the secret manager.Bearer
->BearerConnectionCredentialVendor
UserSecretsManager
: UsesUserSecretsManager
to retrieve the bearer token from the secret manager.Implicit
->ImplicitConnectionCredentialVendor
With this structure, we no longer need to use
UserSecretsManager
directly insideIcebergCatalogPropertiesProvider::asIcebergCatalogProperties
.This unifies credential retrieval across all authentication types and simplifies the overall credential management flow.