diff --git a/api/src/main/java/org/apache/iceberg/encryption/KmsClient.java b/api/src/main/java/org/apache/iceberg/encryption/KmsClient.java index ecfede3d706b..3e115d8b2ceb 100644 --- a/api/src/main/java/org/apache/iceberg/encryption/KmsClient.java +++ b/api/src/main/java/org/apache/iceberg/encryption/KmsClient.java @@ -34,7 +34,7 @@ public interface KmsClient extends Serializable { * @param wrappingKeyId a key ID that represents a wrapping key stored in KMS * @return wrapped key material */ - ByteBuffer wrapKey(ByteBuffer key, String wrappingKeyId); + String wrapKey(ByteBuffer key, String wrappingKeyId); /** * Some KMS systems support generation of secret keys inside the KMS server. @@ -69,10 +69,10 @@ default KeyGenerationResult generateKey(String wrappingKeyId) { * @param wrappingKeyId a key ID that represents a wrapping key stored in KMS * @return raw key bytes */ - ByteBuffer unwrapKey(ByteBuffer wrappedKey, String wrappingKeyId); + ByteBuffer unwrapKey(String wrappedKey, String wrappingKeyId); /** - * Initialize the KMS client with given properties. + * Initialize the KMS client with given properties * * @param properties kms client properties */ @@ -84,9 +84,9 @@ default KeyGenerationResult generateKey(String wrappingKeyId) { */ class KeyGenerationResult { private final ByteBuffer key; - private final ByteBuffer wrappedKey; + private final String wrappedKey; - public KeyGenerationResult(ByteBuffer key, ByteBuffer wrappedKey) { + public KeyGenerationResult(ByteBuffer key, String wrappedKey) { this.key = key; this.wrappedKey = wrappedKey; } @@ -95,7 +95,7 @@ public ByteBuffer key() { return key; } - public ByteBuffer wrappedKey() { + public String wrappedKey() { return wrappedKey; } } diff --git a/core/src/main/java/org/apache/iceberg/encryption/KmsUtil.java b/core/src/main/java/org/apache/iceberg/encryption/KmsUtil.java deleted file mode 100644 index 758d4deba512..000000000000 --- a/core/src/main/java/org/apache/iceberg/encryption/KmsUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.iceberg.encryption; - -import java.util.Map; -import org.apache.iceberg.common.DynConstructors; -import org.apache.iceberg.relocated.com.google.common.base.Preconditions; - -public class KmsUtil { - - private KmsUtil() {} - - public static KmsClient loadKmsClient(String classPath, Map properties) { - Preconditions.checkNotNull(classPath, "Cannot initialize KmsClient, class name is null"); - - DynConstructors.Ctor ctor; - try { - ctor = DynConstructors.builder(KmsClient.class).impl(classPath).buildChecked(); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException( - String.format( - "Cannot initialize KmsClient, missing no-arg constructor for class %s", classPath), - e); - } - - KmsClient kmsClient; - try { - kmsClient = ctor.newInstance(); - } catch (ClassCastException e) { - throw new IllegalArgumentException( - String.format("Cannot initialize KmsClient, %s does not implement KmsClient.", classPath), - e); - } - - kmsClient.initialize(properties); - return kmsClient; - } -} diff --git a/core/src/test/java/org/apache/iceberg/encryption/kms/KeyStoreKmsClient.java b/core/src/test/java/org/apache/iceberg/encryption/kms/KeyStoreKmsClient.java index c51d0d1f436b..1cd049b85542 100644 --- a/core/src/test/java/org/apache/iceberg/encryption/kms/KeyStoreKmsClient.java +++ b/core/src/test/java/org/apache/iceberg/encryption/kms/KeyStoreKmsClient.java @@ -41,20 +41,20 @@ public class KeyStoreKmsClient extends MemoryMockKMS { // Path to keystore file. Preferably kept in volatile storage, such as ramdisk. Don't store with // data. - public static final String KEYSTORE_FILE_PATH_PROP = "kms.client.keystore.path"; + public static final String KEYSTORE_FILE_PATH_PROP = "keystore.kms.client.file.path"; // Credentials (such as keystore password) must never be kept in a persistent storage. // In this class, the password is passed as a system environment variable. public static final String KEYSTORE_PASSWORD_ENV_VAR = "KEYSTORE_PASSWORD"; @Override - public ByteBuffer wrapKey(ByteBuffer key, String wrappingKeyId) { + public String wrapKey(ByteBuffer key, String wrappingKeyId) { // keytool keeps key names in lower case return super.wrapKey(key, wrappingKeyId.toLowerCase()); } @Override - public ByteBuffer unwrapKey(ByteBuffer wrappedKey, String wrappingKeyId) { + public ByteBuffer unwrapKey(String wrappedKey, String wrappingKeyId) { // keytool keeps key names in lower case return super.unwrapKey(wrappedKey, wrappingKeyId.toLowerCase()); } diff --git a/core/src/test/java/org/apache/iceberg/encryption/kms/MemoryMockKMS.java b/core/src/test/java/org/apache/iceberg/encryption/kms/MemoryMockKMS.java index 78a26d6ba973..af61ef000d89 100644 --- a/core/src/test/java/org/apache/iceberg/encryption/kms/MemoryMockKMS.java +++ b/core/src/test/java/org/apache/iceberg/encryption/kms/MemoryMockKMS.java @@ -19,6 +19,7 @@ package org.apache.iceberg.encryption.kms; import java.nio.ByteBuffer; +import java.util.Base64; import java.util.Map; import org.apache.iceberg.encryption.Ciphers; import org.apache.iceberg.encryption.KmsClient; @@ -29,7 +30,7 @@ public abstract class MemoryMockKMS implements KmsClient { protected Map masterKeys; @Override - public ByteBuffer wrapKey(ByteBuffer key, String wrappingKeyId) { + public String wrapKey(ByteBuffer key, String wrappingKeyId) { byte[] wrappingKey = masterKeys.get(wrappingKeyId); if (null == wrappingKey) { throw new RuntimeException( @@ -37,18 +38,19 @@ public ByteBuffer wrapKey(ByteBuffer key, String wrappingKeyId) { } Ciphers.AesGcmEncryptor keyEncryptor = new Ciphers.AesGcmEncryptor(wrappingKey); byte[] encryptedKey = keyEncryptor.encrypt(key.array(), null); - return ByteBuffer.wrap(encryptedKey); + return Base64.getEncoder().encodeToString(encryptedKey); } @Override - public ByteBuffer unwrapKey(ByteBuffer wrappedKey, String wrappingKeyId) { + public ByteBuffer unwrapKey(String wrappedKey, String wrappingKeyId) { + byte[] encryptedKey = Base64.getDecoder().decode(wrappedKey); byte[] wrappingKey = masterKeys.get(wrappingKeyId); if (null == wrappingKey) { throw new RuntimeException( "Cannot unwrap, because wrapping key " + wrappingKeyId + " is not found"); } Ciphers.AesGcmDecryptor keyDecryptor = new Ciphers.AesGcmDecryptor(wrappingKey); - byte[] key = keyDecryptor.decrypt(wrappedKey.array(), null); + byte[] key = keyDecryptor.decrypt(encryptedKey, null); return ByteBuffer.wrap(key); } }