This is an automated email from the ASF dual-hosted git repository.

singhpk234 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new 77bc1d08ec Make KMS endpoint configurable via kms.endpoint AWS 
property (#14246)
77bc1d08ec is described below

commit 77bc1d08ecd46b1d62a3fb51ad7d1935788f30be
Author: Thomas Powell <[email protected]>
AuthorDate: Sat Oct 11 18:16:29 2025 +0100

    Make KMS endpoint configurable via kms.endpoint AWS property (#14246)
    
    Co-authored-by: Thomas Powell <[email protected]>
---
 .../iceberg/aws/TestDefaultAwsClientFactory.java   | 13 ++++++++++
 .../org/apache/iceberg/aws/AwsClientFactories.java |  7 ++++--
 .../java/org/apache/iceberg/aws/AwsProperties.java | 29 ++++++++++++++++++++++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git 
a/aws/src/integration/java/org/apache/iceberg/aws/TestDefaultAwsClientFactory.java
 
b/aws/src/integration/java/org/apache/iceberg/aws/TestDefaultAwsClientFactory.java
index e9803c8bb1..7a7e34fcf2 100644
--- 
a/aws/src/integration/java/org/apache/iceberg/aws/TestDefaultAwsClientFactory.java
+++ 
b/aws/src/integration/java/org/apache/iceberg/aws/TestDefaultAwsClientFactory.java
@@ -30,6 +30,7 @@ import 
software.amazon.awssdk.core.exception.SdkClientException;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.awssdk.services.glue.GlueClient;
 import software.amazon.awssdk.services.glue.model.GetDatabaseRequest;
+import software.amazon.awssdk.services.kms.KmsClient;
 import software.amazon.awssdk.services.s3.S3Client;
 import software.amazon.awssdk.services.s3.model.GetObjectRequest;
 import software.amazon.awssdk.services.s3.model.S3Exception;
@@ -99,4 +100,16 @@ public class TestDefaultAwsClientFactory {
         .isInstanceOf(SdkClientException.class)
         .hasMessageContaining("Unable to execute HTTP request: unknown");
   }
+
+  @Test
+  public void testKmsEndpointOverride() {
+    Map<String, String> properties = Maps.newHashMap();
+    properties.put(AwsProperties.KMS_ENDPOINT, "https://unknown:1234";);
+    AwsClientFactory factory = AwsClientFactories.from(properties);
+    KmsClient kmsClient = factory.kms();
+    assertThatThrownBy(kmsClient::listKeys)
+        .cause()
+        .isInstanceOf(SdkClientException.class)
+        .hasMessageContaining("Unable to execute HTTP request: unknown");
+  }
 }
diff --git a/aws/src/main/java/org/apache/iceberg/aws/AwsClientFactories.java 
b/aws/src/main/java/org/apache/iceberg/aws/AwsClientFactories.java
index cd5715b93b..0ee4bf26e6 100644
--- a/aws/src/main/java/org/apache/iceberg/aws/AwsClientFactories.java
+++ b/aws/src/main/java/org/apache/iceberg/aws/AwsClientFactories.java
@@ -39,6 +39,7 @@ import 
software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
 import software.amazon.awssdk.services.glue.GlueClient;
 import software.amazon.awssdk.services.glue.GlueClientBuilder;
 import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.KmsClientBuilder;
 import software.amazon.awssdk.services.s3.S3AsyncClient;
 import software.amazon.awssdk.services.s3.S3BaseClientBuilder;
 import software.amazon.awssdk.services.s3.S3Client;
@@ -155,6 +156,7 @@ public class AwsClientFactories {
       return KmsClient.builder()
           .applyMutation(awsClientProperties::applyClientRegionConfiguration)
           .applyMutation(httpClientProperties::applyHttpClientConfigurations)
+          .applyMutation(awsProperties::applyKmsEndpointConfigurations)
           
.applyMutation(awsClientProperties::applyClientCredentialConfigurations)
           .applyMutation(awsClientProperties::applyRetryConfigurations)
           .build();
@@ -208,8 +210,9 @@ public class AwsClientFactories {
    * @deprecated Not for public use. To configure the endpoint for a client, 
please use {@link
    *     S3FileIOProperties#applyEndpointConfigurations(S3BaseClientBuilder)}, 
{@link
    *     AwsProperties#applyGlueEndpointConfigurations(GlueClientBuilder)}, or 
{@link
-   *     
AwsProperties#applyDynamoDbEndpointConfigurations(DynamoDbClientBuilder)} 
accordingly. It
-   *     will be removed in 2.0.0
+   *     
AwsProperties#applyDynamoDbEndpointConfigurations(DynamoDbClientBuilder)}, or 
{@link
+   *     AwsProperties#applyKmsEndpointConfigurations(KmsClientBuilder)} 
accordingly. It will be
+   *     removed in 2.0.0
    */
   @Deprecated
   public static <T extends SdkClientBuilder> void configureEndpoint(T builder, 
String endpoint) {
diff --git a/aws/src/main/java/org/apache/iceberg/aws/AwsProperties.java 
b/aws/src/main/java/org/apache/iceberg/aws/AwsProperties.java
index 62d541da0c..a37406e1fa 100644
--- a/aws/src/main/java/org/apache/iceberg/aws/AwsProperties.java
+++ b/aws/src/main/java/org/apache/iceberg/aws/AwsProperties.java
@@ -41,6 +41,7 @@ import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
 import software.amazon.awssdk.services.glue.GlueClientBuilder;
+import software.amazon.awssdk.services.kms.KmsClientBuilder;
 import software.amazon.awssdk.services.kms.model.DataKeySpec;
 import software.amazon.awssdk.services.kms.model.EncryptionAlgorithmSpec;
 
@@ -208,6 +209,14 @@ public class AwsProperties implements Serializable {
    */
   public static final String REST_SESSION_TOKEN = "rest.session-token";
 
+  /**
+   * Configure an alternative endpoint of the KMS service for 
AwsKeyManagementClient to access.
+   *
+   * <p>This could be used to use KMS key management with any KMS-compatible 
service that has a
+   * different endpoint
+   */
+  public static final String KMS_ENDPOINT = "kms.endpoint";
+
   /** Encryption algorithm used to encrypt/decrypt master table keys */
   public static final String KMS_ENCRYPTION_ALGORITHM_SPEC = 
"kms.encryption-algorithm-spec";
 
@@ -243,6 +252,7 @@ public class AwsProperties implements Serializable {
   private String restAccessKeyId;
   private String restSecretAccessKey;
   private String restSessionToken;
+  private final String kmsEndpoint;
   private EncryptionAlgorithmSpec kmsEncryptionAlgorithmSpec;
   private DataKeySpec kmsDataKeySpec;
 
@@ -268,6 +278,7 @@ public class AwsProperties implements Serializable {
 
     this.restSigningName = REST_SIGNING_NAME_DEFAULT;
 
+    this.kmsEndpoint = null;
     this.kmsEncryptionAlgorithmSpec = KMS_ENCRYPTION_ALGORITHM_SPEC_DEFAULT;
     this.kmsDataKeySpec = KMS_DATA_KEY_SPEC_DEFAULT;
   }
@@ -312,6 +323,7 @@ public class AwsProperties implements Serializable {
     this.restSecretAccessKey = properties.get(REST_SECRET_ACCESS_KEY);
     this.restSessionToken = properties.get(REST_SESSION_TOKEN);
 
+    this.kmsEndpoint = properties.get(KMS_ENDPOINT);
     this.kmsEncryptionAlgorithmSpec =
         EncryptionAlgorithmSpec.fromValue(
             properties.getOrDefault(
@@ -411,6 +423,19 @@ public class AwsProperties implements Serializable {
     configureEndpoint(builder, dynamoDbEndpoint);
   }
 
+  /**
+   * Override the endpoint for a KMS client.
+   *
+   * <p>Sample usage:
+   *
+   * <pre>
+   *     
KmsClient.builder().applyMutation(awsProperties::applyKmsEndpointConfigurations)
+   * </pre>
+   */
+  public <T extends KmsClientBuilder> void applyKmsEndpointConfigurations(T 
builder) {
+    configureEndpoint(builder, kmsEndpoint);
+  }
+
   public Region restSigningRegion() {
     if (restSigningRegion == null) {
       this.restSigningRegion = 
DefaultAwsRegionProviderChain.builder().build().getRegion().id();
@@ -428,6 +453,10 @@ public class AwsProperties implements Serializable {
         this.restAccessKeyId, this.restSecretAccessKey, this.restSessionToken);
   }
 
+  public String kmsEndpoint() {
+    return this.kmsEndpoint;
+  }
+
   public EncryptionAlgorithmSpec kmsEncryptionAlgorithmSpec() {
     return this.kmsEncryptionAlgorithmSpec;
   }

Reply via email to