Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ public void setListCacheSize(int listCacheSize) {
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,24 @@ void setBucketQuota(String volumeName, String bucketName,
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,22 @@ public void setBucketQuota(String volumeName, String bucketName,

}

@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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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.
Expand All @@ -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;
Expand Down Expand Up @@ -150,6 +155,10 @@ public DefaultReplicationConfig getDefaultReplicationConfig() {
return defaultReplicationConfig;
}

public BucketEncryptionKeyInfo getBucketEncryptionKeyInfo() {
return bekInfo;
}

/**
* Sets the Bucket default replication config.
*/
Expand All @@ -168,6 +177,12 @@ private void setQuotaInNamespace(long quotaInNamespace) {
this.quotaInNamespace = quotaInNamespace;
}

@Deprecated
private void setBucketEncryptionKey(
BucketEncryptionKeyInfo bucketEncryptionKey) {
this.bekInfo = bucketEncryptionKey;
}

/**
* Returns Bucket Owner Name.
*
Expand Down Expand Up @@ -216,6 +231,7 @@ public static class Builder {
private long quotaInBytes;
private boolean quotaInNamespaceSet = false;
private long quotaInNamespace;
private BucketEncryptionKeyInfo bekInfo;
private DefaultReplicationConfig defaultReplicationConfig;
private String ownerName;
/**
Expand All @@ -241,6 +257,12 @@ public Builder setIsVersionEnabled(Boolean versionFlag) {
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;
Expand Down Expand Up @@ -291,6 +313,9 @@ public OmBucketArgs build() {
if (quotaInNamespaceSet) {
omBucketArgs.setQuotaInNamespace(quotaInNamespace);
}
if (bekInfo != null && bekInfo.getKeyName() != null) {
omBucketArgs.setBucketEncryptionKey(bekInfo);
}
return omBucketArgs;
}
}
Expand Down Expand Up @@ -322,6 +347,11 @@ public BucketArgs getProtobuf() {
if (ownerName != null) {
builder.setOwnerName(ownerName);
}

if (bekInfo != null && bekInfo.getKeyName() != null) {
builder.setBekInfo(OMPBHelper.convert(bekInfo));
}

return builder.build();
}

Expand Down Expand Up @@ -355,6 +385,11 @@ public static OmBucketArgs getFromProtobuf(BucketArgs bucketArgs) {
if (bucketArgs.hasQuotaInNamespace()) {
omBucketArgs.setQuotaInNamespace(bucketArgs.getQuotaInNamespace());
}

if (bucketArgs.hasBekInfo()) {
omBucketArgs.setBucketEncryptionKey(
OMPBHelper.convert(bucketArgs.getBekInfo()));
}
return omBucketArgs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@
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;
Expand All @@ -60,7 +65,6 @@
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;
Expand All @@ -81,6 +85,7 @@
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;
Expand Down Expand Up @@ -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;
Expand All @@ -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());
Expand All @@ -160,6 +178,8 @@ protected static void startCluster(OzoneConfiguration conf) throws Exception {
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)
Expand All @@ -181,9 +201,17 @@ public static void shutdown() {
cluster.shutdown();
}

if (miniKMS != null) {
miniKMS.stop();
}

if (baseDir != null) {
FileUtil.fullyDelete(baseDir, true);
}

if (testDir != null) {
FileUtil.fullyDelete(testDir, true);
}
}

@BeforeEach
Expand Down Expand Up @@ -1299,6 +1327,33 @@ public void testSetECReplicationConfigOnBucket() throws Exception {
}
}

@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");
Expand Down Expand Up @@ -1912,4 +1967,9 @@ public void testLinkedAndNonLinkedBucketMetaData()
new String[]{"volume", "delete", "/volume1"});
out.reset();
}

private static String getKeyProviderURI(MiniKMS kms) {
return KMSClientProvider.SCHEME_NAME + "://" +
kms.getKMSUrl().toExternalForm().replace("://", "@");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static void init() throws Exception {
OzoneConfiguration conf = new OzoneConfiguration();
conf.set(OMConfigKeys.OZONE_DEFAULT_BUCKET_LAYOUT,
OMConfigKeys.OZONE_BUCKET_LAYOUT_FILE_SYSTEM_OPTIMIZED);
startKMS();
startCluster(conf);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading