This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new f39b34dd5c HDDS-10142. Add hidden command to set bucket encryption key
to fix HDDS-7449 (#6020)
f39b34dd5c is described below
commit f39b34dd5cd5a9d82a49a90e2941b15b74d90a79
Author: tanvipenumudy <[email protected]>
AuthorDate: Wed Jan 24 12:39:02 2024 +0530
HDDS-10142. Add hidden command to set bucket encryption key to fix
HDDS-7449 (#6020)
---
.../apache/hadoop/ozone/client/OzoneBucket.java | 6 ++
.../ozone/client/protocol/ClientProtocol.java | 18 +++++
.../apache/hadoop/ozone/client/rpc/RpcClient.java | 16 +++++
.../hadoop/ozone/om/helpers/OmBucketArgs.java | 35 ++++++++++
.../hadoop/ozone/shell/TestOzoneShellHA.java | 62 ++++++++++++++++-
.../ozone/shell/TestOzoneShellHAWithFSO.java | 1 +
.../src/main/proto/OmClientProtocol.proto | 1 +
.../apache/hadoop/ozone/common/BekInfoUtils.java | 70 +++++++++++++++++++
.../om/request/bucket/OMBucketCreateRequest.java | 42 +----------
.../request/bucket/OMBucketSetPropertyRequest.java | 20 ++++++
.../hadoop/ozone/client/ClientProtocolStub.java | 8 +++
.../hadoop/ozone/shell/bucket/BucketCommands.java | 3 +-
.../ozone/shell/bucket/SetEncryptionKey.java | 81 ++++++++++++++++++++++
13 files changed, 322 insertions(+), 41 deletions(-)
diff --git
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java
index 441d9143b5..ca885b3b6b 100644
---
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java
+++
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java
@@ -413,6 +413,12 @@ public class OzoneBucket extends WithMetadata {
this.listCacheSize = listCacheSize;
}
+ @Deprecated
+ public void setEncryptionKey(String bekName) throws IOException {
+ proxy.setEncryptionKey(volumeName, name, bekName);
+ encryptionKeyName = bekName;
+ }
+
/**
* Creates a new key in the bucket, with default replication type RATIS and
* with replication factor THREE.
diff --git
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
index 5316f7a99e..e455e3040a 100644
---
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
+++
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
@@ -997,6 +997,24 @@ public interface ClientProtocol {
void setReplicationConfig(String volumeName, String bucketName,
ReplicationConfig replicationConfig) throws IOException;
+ /**
+ * Set Bucket Encryption Key (BEK).
+ *
+ * @param volumeName
+ * @param bucketName
+ * @param bekName
+ * @throws IOException
+ * @deprecated This functionality is deprecated as it is not intended for
+ * users to reset bucket encryption under normal circumstances and may be
+ * removed in the future. Users are advised to exercise caution and consider
+ * alternative approaches for managing bucket encryption unless HDDS-7449 or
+ * HDDS-7526 is encountered. As a result, the setter methods for this
+ * functionality have been marked as deprecated.
+ */
+ @Deprecated
+ void setEncryptionKey(String volumeName, String bucketName,
+ String bekName) throws IOException;
+
/**
* Returns OzoneKey that contains the application generated/visible
* metadata for an Ozone Object.
diff --git
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 850ae0d193..e14ae5828d 100644
---
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -1213,6 +1213,22 @@ public class RpcClient implements ClientProtocol {
}
+ @Deprecated
+ @Override
+ public void setEncryptionKey(String volumeName, String bucketName,
+ String bekName) throws IOException {
+ verifyVolumeName(volumeName);
+ verifyBucketName(bucketName);
+ OmBucketArgs.Builder builder = OmBucketArgs.newBuilder();
+ BucketEncryptionKeyInfo bek = new BucketEncryptionKeyInfo.Builder()
+ .setKeyName(bekName).build();
+ builder.setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setBucketEncryptionKey(bek);
+ OmBucketArgs finalArgs = builder.build();
+ ozoneManagerClient.setBucketProperty(finalArgs);
+ }
+
@Override
public void setReplicationConfig(
String volumeName, String bucketName, ReplicationConfig
replicationConfig)
diff --git
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java
index f8c752aab2..e382377dff 100644
---
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java
+++
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java
@@ -27,6 +27,7 @@ import org.apache.hadoop.ozone.audit.Auditable;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketArgs;
import com.google.common.base.Preconditions;
+import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
/**
* A class that encapsulates Bucket Arguments.
@@ -50,6 +51,10 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
*/
private StorageType storageType;
+ /**
+ * Bucket encryption key info if encryption is enabled.
+ */
+ private BucketEncryptionKeyInfo bekInfo;
private long quotaInBytes = OzoneConsts.QUOTA_RESET;
private long quotaInNamespace = OzoneConsts.QUOTA_RESET;
private boolean quotaInBytesSet = false;
@@ -150,6 +155,10 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
return defaultReplicationConfig;
}
+ public BucketEncryptionKeyInfo getBucketEncryptionKeyInfo() {
+ return bekInfo;
+ }
+
/**
* Sets the Bucket default replication config.
*/
@@ -168,6 +177,12 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
this.quotaInNamespace = quotaInNamespace;
}
+ @Deprecated
+ private void setBucketEncryptionKey(
+ BucketEncryptionKeyInfo bucketEncryptionKey) {
+ this.bekInfo = bucketEncryptionKey;
+ }
+
/**
* Returns Bucket Owner Name.
*
@@ -216,6 +231,7 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
private long quotaInBytes;
private boolean quotaInNamespaceSet = false;
private long quotaInNamespace;
+ private BucketEncryptionKeyInfo bekInfo;
private DefaultReplicationConfig defaultReplicationConfig;
private String ownerName;
/**
@@ -241,6 +257,12 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
return this;
}
+ @Deprecated
+ public Builder setBucketEncryptionKey(BucketEncryptionKeyInfo info) {
+ this.bekInfo = info;
+ return this;
+ }
+
public Builder addMetadata(Map<String, String> metadataMap) {
this.metadata = metadataMap;
return this;
@@ -291,6 +313,9 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
if (quotaInNamespaceSet) {
omBucketArgs.setQuotaInNamespace(quotaInNamespace);
}
+ if (bekInfo != null && bekInfo.getKeyName() != null) {
+ omBucketArgs.setBucketEncryptionKey(bekInfo);
+ }
return omBucketArgs;
}
}
@@ -322,6 +347,11 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
if (ownerName != null) {
builder.setOwnerName(ownerName);
}
+
+ if (bekInfo != null && bekInfo.getKeyName() != null) {
+ builder.setBekInfo(OMPBHelper.convert(bekInfo));
+ }
+
return builder.build();
}
@@ -355,6 +385,11 @@ public final class OmBucketArgs extends WithMetadata
implements Auditable {
if (bucketArgs.hasQuotaInNamespace()) {
omBucketArgs.setQuotaInNamespace(bucketArgs.getQuotaInNamespace());
}
+
+ if (bucketArgs.hasBekInfo()) {
+ omBucketArgs.setBucketEncryptionKey(
+ OMPBHelper.convert(bucketArgs.getBekInfo()));
+ }
return omBucketArgs;
}
}
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
index dd84489b68..de25f24f33 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
@@ -29,12 +29,17 @@ import java.util.HashSet;
import java.util.List;
import java.util.UUID;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.kms.KMSClientProvider;
+import org.apache.hadoop.crypto.key.kms.server.MiniKMS;
import org.apache.hadoop.hdds.utils.IOUtils;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.fs.FileChecksum;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.TrashPolicy;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.client.ReplicationType;
@@ -60,7 +65,6 @@ import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.ozone.test.GenericTestUtils;
import org.apache.hadoop.util.ToolRunner;
-import org.apache.hadoop.fs.TrashPolicy;
import org.apache.hadoop.ozone.om.TrashPolicyOzone;
import com.google.common.base.Strings;
@@ -81,6 +85,7 @@ import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.VOLU
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -117,6 +122,8 @@ public class TestOzoneShellHA {
private static File testFile;
private static String testFilePathString;
private static MiniOzoneCluster cluster = null;
+ private static File testDir;
+ private static MiniKMS miniKMS;
private static OzoneClient client;
private OzoneShell ozoneShell = null;
private OzoneAdmin ozoneAdminShell = null;
@@ -140,9 +147,20 @@ public class TestOzoneShellHA {
@BeforeAll
public static void init() throws Exception {
OzoneConfiguration conf = new OzoneConfiguration();
+ startKMS();
startCluster(conf);
}
+ protected static void startKMS() throws Exception {
+ testDir = GenericTestUtils.getTestDir(
+ TestOzoneShellHA.class.getSimpleName());
+ File kmsDir = new File(testDir, UUID.randomUUID().toString());
+ assertTrue(kmsDir.mkdirs());
+ MiniKMS.Builder miniKMSBuilder = new MiniKMS.Builder();
+ miniKMS = miniKMSBuilder.setKmsConfDir(kmsDir).build();
+ miniKMS.start();
+ }
+
protected static void startCluster(OzoneConfiguration conf) throws Exception
{
String path = GenericTestUtils.getTempPath(
TestOzoneShellHA.class.getSimpleName());
@@ -160,6 +178,8 @@ public class TestOzoneShellHA {
clusterId = UUID.randomUUID().toString();
scmId = UUID.randomUUID().toString();
final int numDNs = 5;
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_KEY_PROVIDER_PATH,
+ getKeyProviderURI(miniKMS));
cluster = MiniOzoneCluster.newOMHABuilder(conf)
.setClusterId(clusterId)
.setScmId(scmId)
@@ -181,9 +201,17 @@ public class TestOzoneShellHA {
cluster.shutdown();
}
+ if (miniKMS != null) {
+ miniKMS.stop();
+ }
+
if (baseDir != null) {
FileUtil.fullyDelete(baseDir, true);
}
+
+ if (testDir != null) {
+ FileUtil.fullyDelete(testDir, true);
+ }
}
@BeforeEach
@@ -1322,6 +1350,33 @@ public class TestOzoneShellHA {
}
}
+ @Test
+ public void testSetEncryptionKey() throws Exception {
+ final String volumeName = "volume111";
+ getVolume(volumeName);
+ String bucketPath = "/volume111/bucket0";
+ String[] args = new String[]{"bucket", "create", bucketPath};
+ execute(ozoneShell, args);
+
+ OzoneVolume volume =
+ client.getObjectStore().getVolume(volumeName);
+ OzoneBucket bucket = volume.getBucket("bucket0");
+ assertNull(bucket.getEncryptionKeyName());
+ String newEncKey = "enckey1";
+
+ KeyProvider provider = cluster.getOzoneManager().getKmsProvider();
+ KeyProvider.Options options = KeyProvider.options(cluster.getConf());
+ options.setDescription(newEncKey);
+ options.setBitLength(128);
+ provider.createKey(newEncKey, options);
+ provider.flush();
+
+ args = new String[]{"bucket", "set-encryption-key", bucketPath, "-k",
+ newEncKey};
+ execute(ozoneShell, args);
+ assertEquals(newEncKey,
volume.getBucket("bucket0").getEncryptionKeyName());
+ }
+
@Test
public void testCreateBucketWithECReplicationConfigWithoutReplicationParam()
{
getVolume("volume102");
@@ -1935,4 +1990,9 @@ public class TestOzoneShellHA {
new String[]{"volume", "delete", "/volume1"});
out.reset();
}
+
+ private static String getKeyProviderURI(MiniKMS kms) {
+ return KMSClientProvider.SCHEME_NAME + "://" +
+ kms.getKMSUrl().toExternalForm().replace("://", "@");
+ }
}
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHAWithFSO.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHAWithFSO.java
index 0c6a5e8143..3d1757ecbd 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHAWithFSO.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHAWithFSO.java
@@ -37,6 +37,7 @@ public class TestOzoneShellHAWithFSO extends TestOzoneShellHA
{
OzoneConfiguration conf = new OzoneConfiguration();
conf.set(OMConfigKeys.OZONE_DEFAULT_BUCKET_LAYOUT,
OMConfigKeys.OZONE_BUCKET_LAYOUT_FILE_SYSTEM_OPTIMIZED);
+ startKMS();
startCluster(conf);
}
diff --git
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index fd83981507..19844eed01 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -805,6 +805,7 @@ message BucketArgs {
optional uint64 quotaInNamespace = 9;
optional string ownerName = 10;
optional hadoop.hdds.DefaultReplicationConfig defaultReplicationConfig =
11;
+ optional BucketEncryptionInfoProto bekInfo = 12;
}
message PrefixInfo {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/common/BekInfoUtils.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/common/BekInfoUtils.java
new file mode 100644
index 0000000000..7cfad3b8a3
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/common/BekInfoUtils.java
@@ -0,0 +1,70 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hadoop.ozone.common;
+
+import org.apache.hadoop.crypto.CipherSuite;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketEncryptionInfoProto;
+import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
+
+import java.io.IOException;
+
+import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CryptoProtocolVersionProto.ENCRYPTION_ZONES;
+
+/**
+ * Utility class for common bucket encryption key operations.
+ */
+public final class BekInfoUtils {
+
+ private BekInfoUtils() {
+ }
+
+ public static BucketEncryptionInfoProto getBekInfo(
+ KeyProviderCryptoExtension kmsProvider, BucketEncryptionInfoProto bek)
+ throws IOException {
+ BucketEncryptionInfoProto.Builder bekb = null;
+ if (kmsProvider == null) {
+ throw new OMException("Invalid KMS provider, check configuration " +
+ CommonConfigurationKeys.HADOOP_SECURITY_KEY_PROVIDER_PATH,
+ OMException.ResultCodes.INVALID_KMS_PROVIDER);
+ }
+ if (bek.getKeyName() == null) {
+ throw new OMException("Bucket encryption key needed.", OMException
+ .ResultCodes.BUCKET_ENCRYPTION_KEY_NOT_FOUND);
+ }
+ // Talk to KMS to retrieve the bucket encryption key info.
+ KeyProvider.Metadata metadata = kmsProvider.getMetadata(
+ bek.getKeyName());
+ if (metadata == null) {
+ throw new OMException("Bucket encryption key " + bek.getKeyName()
+ + " doesn't exist.",
+ OMException.ResultCodes.BUCKET_ENCRYPTION_KEY_NOT_FOUND);
+ }
+ // If the provider supports pool for EDEKs, this will fill in the pool
+ kmsProvider.warmUpEncryptedKeys(bek.getKeyName());
+ bekb = BucketEncryptionInfoProto.newBuilder()
+ .setKeyName(bek.getKeyName())
+ .setCryptoProtocolVersion(ENCRYPTION_ZONES)
+ .setSuite(OMPBHelper.convert(
+ CipherSuite.convert(metadata.getCipher())));
+ return bekb.build();
+ }
+}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
index de8152af46..7cce3ac456 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
@@ -18,10 +18,7 @@
package org.apache.hadoop.ozone.om.request.bucket;
-import org.apache.hadoop.crypto.CipherSuite;
-import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
-import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
@@ -33,6 +30,7 @@ import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.audit.OMAction;
import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.common.BekInfoUtils;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OzoneManager;
@@ -52,14 +50,12 @@ import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.om.response.bucket.OMBucketCreateResponse;
import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
-import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketEncryptionInfoProto;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketInfo;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateBucketRequest;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateBucketResponse;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type;
-import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
import org.apache.hadoop.ozone.security.acl.OzoneObj;
import org.apache.hadoop.util.Time;
@@ -75,7 +71,6 @@ import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.BUCK
import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.VOLUME_NOT_FOUND;
import static
org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.BUCKET_LOCK;
import static
org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.VOLUME_LOCK;
-import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CryptoProtocolVersionProto.ENCRYPTION_ZONES;
/**
* Handles CreateBucket Request.
@@ -116,7 +111,8 @@ public class OMBucketCreateRequest extends OMClientRequest {
.setModificationTime(initialTime);
if (bucketInfo.hasBeinfo()) {
- newBucketInfo.setBeinfo(getBeinfo(kmsProvider, bucketInfo));
+ newBucketInfo.setBeinfo(
+ BekInfoUtils.getBekInfo(kmsProvider, bucketInfo.getBeinfo()));
}
boolean hasSourceVolume = bucketInfo.hasSourceVolume();
@@ -338,38 +334,6 @@ public class OMBucketCreateRequest extends OMClientRequest
{
omBucketInfo.setAcls(acls);
}
- private BucketEncryptionInfoProto getBeinfo(
- KeyProviderCryptoExtension kmsProvider, BucketInfo bucketInfo)
- throws IOException {
- BucketEncryptionInfoProto bek = bucketInfo.getBeinfo();
- BucketEncryptionInfoProto.Builder bekb = null;
- if (kmsProvider == null) {
- throw new OMException("Invalid KMS provider, check configuration " +
- CommonConfigurationKeys.HADOOP_SECURITY_KEY_PROVIDER_PATH,
- OMException.ResultCodes.INVALID_KMS_PROVIDER);
- }
- if (bek.getKeyName() == null) {
- throw new OMException("Bucket encryption key needed.", OMException
- .ResultCodes.BUCKET_ENCRYPTION_KEY_NOT_FOUND);
- }
- // Talk to KMS to retrieve the bucket encryption key info.
- KeyProvider.Metadata metadata = kmsProvider.getMetadata(
- bek.getKeyName());
- if (metadata == null) {
- throw new OMException("Bucket encryption key " + bek.getKeyName()
- + " doesn't exist.",
- OMException.ResultCodes.BUCKET_ENCRYPTION_KEY_NOT_FOUND);
- }
- // If the provider supports pool for EDEKs, this will fill in the pool
- kmsProvider.warmUpEncryptedKeys(bek.getKeyName());
- bekb = BucketEncryptionInfoProto.newBuilder()
- .setKeyName(bek.getKeyName())
- .setCryptoProtocolVersion(ENCRYPTION_ZONES)
- .setSuite(OMPBHelper.convert(
- CipherSuite.convert(metadata.getCipher())));
- return bekb.build();
- }
-
/**
* Check namespace quota.
*/
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java
index 821c374c2d..9c7ef1087c 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java
@@ -23,12 +23,15 @@ import java.nio.file.InvalidPathException;
import java.util.List;
import com.google.common.base.Preconditions;
+import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.audit.OMAction;
+import org.apache.hadoop.ozone.common.BekInfoUtils;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
+import org.apache.hadoop.ozone.om.helpers.BucketEncryptionKeyInfo;
import org.apache.hadoop.ozone.om.request.util.OmResponseUtil;
import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator;
import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase;
@@ -87,6 +90,18 @@ public class OMBucketSetPropertyRequest extends
OMClientRequest {
.getSetBucketPropertyRequest().toBuilder()
.setModificationTime(modificationTime);
+ BucketArgs bucketArgs =
+ getOmRequest().getSetBucketPropertyRequest().getBucketArgs();
+
+ if (bucketArgs.hasBekInfo()) {
+ KeyProviderCryptoExtension kmsProvider = ozoneManager.getKmsProvider();
+ BucketArgs.Builder bucketArgsBuilder =
+ setBucketPropertyRequestBuilder.getBucketArgsBuilder();
+ bucketArgsBuilder.setBekInfo(
+ BekInfoUtils.getBekInfo(kmsProvider, bucketArgs.getBekInfo()));
+ setBucketPropertyRequestBuilder.setBucketArgs(bucketArgsBuilder.build());
+ }
+
return getOmRequest().toBuilder()
.setSetBucketPropertyRequest(setBucketPropertyRequestBuilder)
.setUserInfo(getUserInfo())
@@ -190,6 +205,11 @@ public class OMBucketSetPropertyRequest extends
OMClientRequest {
bucketInfoBuilder.setDefaultReplicationConfig(defaultReplicationConfig);
}
+ BucketEncryptionKeyInfo bek = omBucketArgs.getBucketEncryptionKeyInfo();
+ if (bek != null && bek.getKeyName() != null) {
+ bucketInfoBuilder.setBucketEncryptionKey(bek);
+ }
+
omBucketInfo = bucketInfoBuilder.build();
// Update table cache.
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
index 174af69e25..f0528facbb 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
@@ -573,6 +573,14 @@ public class ClientProtocolStub implements ClientProtocol {
}
+ @Deprecated
+ @Override
+ public void setEncryptionKey(String volumeName, String bucketName,
+ String bekName)
+ throws IOException {
+
+ }
+
@Override
public OzoneKey headObject(String volumeName, String bucketName,
String keyName) throws IOException {
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/BucketCommands.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/BucketCommands.java
index 454660e2ca..80e26e0445 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/BucketCommands.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/BucketCommands.java
@@ -50,7 +50,8 @@ import picocli.CommandLine.ParentCommand;
SetAclBucketHandler.class,
ClearQuotaHandler.class,
SetReplicationConfigHandler.class,
- UpdateBucketHandler.class
+ UpdateBucketHandler.class,
+ SetEncryptionKey.class
},
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class)
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/SetEncryptionKey.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/SetEncryptionKey.java
new file mode 100644
index 0000000000..86a50e9df3
--- /dev/null
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/SetEncryptionKey.java
@@ -0,0 +1,81 @@
+/*
+ * 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.hadoop.ozone.shell.bucket;
+
+import org.apache.hadoop.ozone.client.OzoneBucket;
+import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.client.OzoneClientException;
+import org.apache.hadoop.ozone.shell.OzoneAddress;
+import picocli.CommandLine;
+
+import java.io.IOException;
+
+/**
+ * Command-line tool to set the encryption key of a bucket.
+ *
+ * There are known bugs, HDDS-7449 and HDDS-7526, which could potentially
result
+ * in the loss of bucket encryption properties when either quota or bucket
+ * replication properties are (re)set on an existing bucket, posing a critical
+ * issue. This may affect consumers using previous versions of Ozone.
+ *
+ * To address this bug, this CLI tool provides the ability to (re)set the
+ * Bucket Encryption Key (BEK) for HDDS-7449/HDDS-7526 affected buckets using
+ * the Ozone shell.
+ *
+ * Users can execute the following command for setting BEK for a given bucket:
+ * "ozone sh bucket set-encryption-key -k <enckey> <vol>/<buck>"
+ *
+ * Please note that this operation only resets the BEK and does not modify any
+ * other properties of the bucket or the existing keys within it.
+ *
+ * Existing keys in the bucket will retain their current properties, and any
+ * keys added before the BEK reset will remain unencrypted. Keys added after
the
+ * BEK reset will be encrypted using the new BEK details provided.
+ *
+ * @deprecated This functionality is deprecated as it is not intended for users
+ * to reset bucket encryption post-bucket creation under normal circumstances
+ * and may be removed in the future. Users are advised to exercise caution and
+ * consider alternative approaches for managing bucket encryption unless
+ * HDDS-7449 or HDDS-7526 is encountered. As a result, the setter methods and
+ * this CLI functionality have been marked as deprecated, and the command has
+ * been hidden.
+ */
+@Deprecated
[email protected](name = "set-encryption-key",
+ description = "Set Bucket Encryption Key (BEK) for a given bucket. Users "
+
+ "are advised to exercise caution and consider alternative approaches "
+
+ "for managing bucket encryption unless HDDS-7449 or HDDS-7526 is " +
+ "encountered.",
+ hidden = true)
+public class SetEncryptionKey extends BucketHandler {
+
+ @CommandLine.Option(names = {"--key", "-k"},
+ description = "bucket encryption key name")
+ private String bekName;
+
+ @Override
+ protected void execute(OzoneClient client, OzoneAddress address)
+ throws IOException, OzoneClientException {
+
+ String volumeName = address.getVolumeName();
+ String bucketName = address.getBucketName();
+ OzoneBucket bucket =
+ client.getObjectStore().getVolume(volumeName).getBucket(bucketName);
+ bucket.setEncryptionKey(bekName);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]