Skip to content

Commit 519e127

Browse files
authored
SigV4 Auth Support for Catalog Federation - Part 4: Connection Credential Manager (#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.
1 parent 031a551 commit 519e127

File tree

41 files changed

+1234
-30
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1234
-30
lines changed

extensions/federation/hadoop/src/main/java/org/apache/polaris/extensions/federation/hadoop/HadoopFederatedCatalogFactory.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.polaris.core.connection.ConnectionConfigInfoDpo;
3131
import org.apache.polaris.core.connection.ConnectionType;
3232
import org.apache.polaris.core.connection.hadoop.HadoopConnectionConfigInfoDpo;
33+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
3334
import org.apache.polaris.core.secrets.UserSecretsManager;
3435
import org.slf4j.Logger;
3536
import org.slf4j.LoggerFactory;
@@ -42,7 +43,9 @@ public class HadoopFederatedCatalogFactory implements ExternalCatalogFactory {
4243

4344
@Override
4445
public Catalog createCatalog(
45-
ConnectionConfigInfoDpo connectionConfigInfoDpo, UserSecretsManager userSecretsManager) {
46+
ConnectionConfigInfoDpo connectionConfigInfoDpo,
47+
UserSecretsManager userSecretsManager,
48+
PolarisCredentialManager polarisCredentialManager) {
4649
// Currently, Polaris supports Hadoop federation only via IMPLICIT authentication.
4750
// Hence, prior to initializing the configuration, ensure that the catalog uses
4851
// IMPLICIT authentication.
@@ -56,7 +59,9 @@ public Catalog createCatalog(
5659
String warehouse = ((HadoopConnectionConfigInfoDpo) connectionConfigInfoDpo).getWarehouse();
5760
HadoopCatalog hadoopCatalog = new HadoopCatalog(conf, warehouse);
5861
hadoopCatalog.initialize(
59-
warehouse, connectionConfigInfoDpo.asIcebergCatalogProperties(userSecretsManager));
62+
warehouse,
63+
connectionConfigInfoDpo.asIcebergCatalogProperties(
64+
userSecretsManager, polarisCredentialManager));
6065
return hadoopCatalog;
6166
}
6267

extensions/federation/hive/src/main/java/org/apache/polaris/extensions/federation/hive/HiveFederatedCatalogFactory.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.polaris.core.connection.ConnectionConfigInfoDpo;
3030
import org.apache.polaris.core.connection.ConnectionType;
3131
import org.apache.polaris.core.connection.hive.HiveConnectionConfigInfoDpo;
32+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
3233
import org.apache.polaris.core.secrets.UserSecretsManager;
3334
import org.slf4j.Logger;
3435
import org.slf4j.LoggerFactory;
@@ -41,7 +42,9 @@ public class HiveFederatedCatalogFactory implements ExternalCatalogFactory {
4142

4243
@Override
4344
public Catalog createCatalog(
44-
ConnectionConfigInfoDpo connectionConfigInfoDpo, UserSecretsManager userSecretsManager) {
45+
ConnectionConfigInfoDpo connectionConfigInfoDpo,
46+
UserSecretsManager userSecretsManager,
47+
PolarisCredentialManager polarisCredentialManager) {
4548
// Currently, Polaris supports Hive federation only via IMPLICIT authentication.
4649
// Hence, prior to initializing the configuration, ensure that the catalog uses
4750
// IMPLICIT authentication.
@@ -69,7 +72,9 @@ public Catalog createCatalog(
6972
// Kerberos instances are not suitable because Kerberos ties a single identity to the server.
7073
HiveCatalog hiveCatalog = new HiveCatalog();
7174
hiveCatalog.initialize(
72-
warehouse, connectionConfigInfoDpo.asIcebergCatalogProperties(userSecretsManager));
75+
warehouse,
76+
connectionConfigInfoDpo.asIcebergCatalogProperties(
77+
userSecretsManager, polarisCredentialManager));
7378
return hiveCatalog;
7479
}
7580

polaris-core/src/main/java/org/apache/polaris/core/catalog/ExternalCatalogFactory.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.apache.iceberg.catalog.Catalog;
2222
import org.apache.polaris.core.connection.ConnectionConfigInfoDpo;
23+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
2324
import org.apache.polaris.core.secrets.UserSecretsManager;
2425

2526
/**
@@ -34,12 +35,16 @@ public interface ExternalCatalogFactory {
3435
* Creates a catalog handle for the given connection configuration.
3536
*
3637
* @param connectionConfig the connection configuration
37-
* @param userSecretsManager the user secrets manager for handling credentials
38+
* @param userSecretsManager the user secrets manager for handling user-provided credentials
39+
* @param polarisCredentialManager the credential manager for generating temporary credentials
40+
* that Polaris uses to access external systems
3841
* @return the initialized catalog
3942
* @throws IllegalStateException if the connection configuration is invalid
4043
*/
4144
Catalog createCatalog(
42-
ConnectionConfigInfoDpo connectionConfig, UserSecretsManager userSecretsManager);
45+
ConnectionConfigInfoDpo connectionConfig,
46+
UserSecretsManager userSecretsManager,
47+
PolarisCredentialManager polarisCredentialManager);
4348

4449
/**
4550
* Creates a generic table catalog for the given connection configuration.

polaris-core/src/main/java/org/apache/polaris/core/connection/BearerAuthenticationParametersDpo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.iceberg.rest.auth.OAuth2Properties;
2626
import org.apache.polaris.core.admin.model.AuthenticationParameters;
2727
import org.apache.polaris.core.admin.model.BearerAuthenticationParameters;
28+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
2829
import org.apache.polaris.core.secrets.SecretReference;
2930
import org.apache.polaris.core.secrets.UserSecretsManager;
3031

@@ -50,7 +51,7 @@ public BearerAuthenticationParametersDpo(
5051

5152
@Override
5253
public @Nonnull Map<String, String> asIcebergCatalogProperties(
53-
UserSecretsManager secretsManager) {
54+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) {
5455
String bearerToken = secretsManager.readSecret(getBearerTokenReference());
5556
return Map.of(OAuth2Properties.TOKEN, bearerToken);
5657
}

polaris-core/src/main/java/org/apache/polaris/core/connection/ImplicitAuthenticationParametersDpo.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
package org.apache.polaris.core.connection;
2020

2121
import com.google.common.base.MoreObjects;
22+
import jakarta.annotation.Nonnull;
2223
import java.util.Map;
2324
import org.apache.polaris.core.admin.model.AuthenticationParameters;
2425
import org.apache.polaris.core.admin.model.ImplicitAuthenticationParameters;
26+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
2527
import org.apache.polaris.core.secrets.UserSecretsManager;
2628

2729
/**
@@ -35,12 +37,13 @@ public ImplicitAuthenticationParametersDpo() {
3537
}
3638

3739
@Override
38-
public Map<String, String> asIcebergCatalogProperties(UserSecretsManager secretsManager) {
40+
public @Nonnull Map<String, String> asIcebergCatalogProperties(
41+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) {
3942
return Map.of();
4043
}
4144

4245
@Override
43-
public AuthenticationParameters asAuthenticationParametersModel() {
46+
public @Nonnull AuthenticationParameters asAuthenticationParametersModel() {
4447
return ImplicitAuthenticationParameters.builder()
4548
.setAuthenticationType(AuthenticationParameters.AuthenticationTypeEnum.IMPLICIT)
4649
.build();

polaris-core/src/main/java/org/apache/polaris/core/connection/OAuthClientCredentialsParametersDpo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.iceberg.rest.auth.OAuth2Util;
3636
import org.apache.polaris.core.admin.model.AuthenticationParameters;
3737
import org.apache.polaris.core.admin.model.OAuthClientCredentialsParameters;
38+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
3839
import org.apache.polaris.core.secrets.SecretReference;
3940
import org.apache.polaris.core.secrets.UserSecretsManager;
4041

@@ -104,7 +105,7 @@ public OAuthClientCredentialsParametersDpo(
104105

105106
@Override
106107
public @Nonnull Map<String, String> asIcebergCatalogProperties(
107-
UserSecretsManager secretsManager) {
108+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) {
108109
HashMap<String, String> properties = new HashMap<>();
109110
if (getTokenUri() != null) {
110111
properties.put(OAuth2Properties.OAUTH2_SERVER_URI, getTokenUri());

polaris-core/src/main/java/org/apache/polaris/core/connection/SigV4AuthenticationParametersDpo.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.iceberg.rest.auth.AuthProperties;
2929
import org.apache.polaris.core.admin.model.AuthenticationParameters;
3030
import org.apache.polaris.core.admin.model.SigV4AuthenticationParameters;
31+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
3132
import org.apache.polaris.core.secrets.UserSecretsManager;
3233

3334
/**
@@ -93,15 +94,15 @@ public SigV4AuthenticationParametersDpo(
9394

9495
@Nonnull
9596
@Override
96-
public Map<String, String> asIcebergCatalogProperties(UserSecretsManager secretsManager) {
97+
public Map<String, String> asIcebergCatalogProperties(
98+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) {
9799
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
98100
builder.put(AuthProperties.AUTH_TYPE, AuthProperties.AUTH_TYPE_SIGV4);
99101
builder.put(AwsProperties.REST_SIGNER_REGION, getSigningRegion());
100102
if (getSigningName() != null) {
101103
builder.put(AwsProperties.REST_SIGNING_NAME, getSigningName());
102104
}
103-
104-
// TODO: Add a credential manager to assume the role and get the aws session credentials
105+
// Connection credentials are handled by ConnectionConfigInfoDpo
105106
return builder.build();
106107
}
107108

polaris-core/src/main/java/org/apache/polaris/core/connection/hadoop/HadoopConnectionConfigInfoDpo.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.apache.polaris.core.connection.AuthenticationParametersDpo;
3232
import org.apache.polaris.core.connection.ConnectionConfigInfoDpo;
3333
import org.apache.polaris.core.connection.ConnectionType;
34+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
35+
import org.apache.polaris.core.credentials.connection.ConnectionCredentials;
3436
import org.apache.polaris.core.identity.dpo.ServiceIdentityInfoDpo;
3537
import org.apache.polaris.core.identity.provider.ServiceIdentityProvider;
3638
import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -71,13 +73,19 @@ public String toString() {
7173

7274
@Override
7375
public @Nonnull Map<String, String> asIcebergCatalogProperties(
74-
UserSecretsManager secretsManager) {
76+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager) {
7577
HashMap<String, String> properties = new HashMap<>();
7678
properties.put(CatalogProperties.URI, getUri());
7779
if (getWarehouse() != null) {
7880
properties.put(CatalogProperties.WAREHOUSE_LOCATION, getWarehouse());
7981
}
80-
properties.putAll(getAuthenticationParameters().asIcebergCatalogProperties(secretsManager));
82+
// Add authentication-specific properties
83+
properties.putAll(
84+
getAuthenticationParameters()
85+
.asIcebergCatalogProperties(secretsManager, credentialManager));
86+
// Add connection credentials from Polaris credential manager
87+
ConnectionCredentials connectionCredentials = credentialManager.getConnectionCredentials(this);
88+
properties.putAll(connectionCredentials.credentials());
8189
return properties;
8290
}
8391

polaris-core/src/main/java/org/apache/polaris/core/connection/hive/HiveConnectionConfigInfoDpo.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.apache.polaris.core.connection.AuthenticationParametersDpo;
3232
import org.apache.polaris.core.connection.ConnectionConfigInfoDpo;
3333
import org.apache.polaris.core.connection.ConnectionType;
34+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
35+
import org.apache.polaris.core.credentials.connection.ConnectionCredentials;
3436
import org.apache.polaris.core.identity.dpo.ServiceIdentityInfoDpo;
3537
import org.apache.polaris.core.identity.provider.ServiceIdentityProvider;
3638
import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -70,14 +72,21 @@ public String toString() {
7072

7173
@Override
7274
public @Nonnull Map<String, String> asIcebergCatalogProperties(
73-
UserSecretsManager secretsManager) {
75+
UserSecretsManager secretsManager, PolarisCredentialManager polarisCredentialManager) {
7476
HashMap<String, String> properties = new HashMap<>();
7577
properties.put(CatalogProperties.URI, getUri());
7678
if (getWarehouse() != null) {
7779
properties.put(CatalogProperties.WAREHOUSE_LOCATION, getWarehouse());
7880
}
7981
if (getAuthenticationParameters() != null) {
80-
properties.putAll(getAuthenticationParameters().asIcebergCatalogProperties(secretsManager));
82+
// Add authentication-specific properties
83+
properties.putAll(
84+
getAuthenticationParameters()
85+
.asIcebergCatalogProperties(secretsManager, polarisCredentialManager));
86+
// Add connection credentials from Polaris credential manager
87+
ConnectionCredentials connectionCredentials =
88+
polarisCredentialManager.getConnectionCredentials(this);
89+
properties.putAll(connectionCredentials.credentials());
8190
}
8291
return properties;
8392
}

polaris-core/src/main/java/org/apache/polaris/core/connection/iceberg/IcebergCatalogPropertiesProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import jakarta.annotation.Nonnull;
2222
import java.util.Map;
23+
import org.apache.polaris.core.credentials.PolarisCredentialManager;
2324
import org.apache.polaris.core.secrets.UserSecretsManager;
2425

2526
/**
@@ -30,5 +31,6 @@
3031
*/
3132
public interface IcebergCatalogPropertiesProvider {
3233
@Nonnull
33-
Map<String, String> asIcebergCatalogProperties(UserSecretsManager secretsManager);
34+
Map<String, String> asIcebergCatalogProperties(
35+
UserSecretsManager secretsManager, PolarisCredentialManager credentialManager);
3436
}

0 commit comments

Comments
 (0)