Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-11227. Use server default key provider to encrypt/decrypt keys from multiple OMs. #7081

Merged
merged 4 commits into from
Aug 22, 2024
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 @@ -583,6 +583,13 @@ public final class OzoneConfigKeys {
public static final boolean OZONE_CLIENT_KEY_LATEST_VERSION_LOCATION_DEFAULT =
true;

public static final String OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS =
"ozone.client.server-defaults.validity.period.ms";

public static final long
OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS_DEFAULT =
TimeUnit.HOURS.toMillis(1); // 1 hour

public static final String OZONE_FLEXIBLE_FQDN_RESOLUTION_ENABLED =
"ozone.network.flexible.fqdn.resolution.enabled";
public static final boolean OZONE_FLEXIBLE_FQDN_RESOLUTION_ENABLED_DEFAULT =
Expand Down
13 changes: 13 additions & 0 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3571,6 +3571,19 @@
</description>
</property>

<property>
<name>ozone.client.server-defaults.validity.period.ms</name>
<tag>OZONE, CLIENT, SECURITY</tag>
<value>3600000</value>
Copy link
Contributor

@hemantk-12 hemantk-12 Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should add the default unit otherwise there will be an unnecessary log like the one below.

24/09/18 15:43:05 INFO Configuration.deprecation: No unit for ozone.client.server-defaults.validity.period.ms(3600000) assuming MILLISECONDS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And .ms should be omitted from the property name.

<description>
The amount of milliseconds after which cached server defaults are updated.

By default this parameter is set to 1 hour.
Support multiple time unit suffix(case insensitive).
If no time unit is specified then milliseconds is assumed.
</description>
</property>

<property>
<name>ozone.scm.info.wait.duration</name>
<tag>OZONE, SCM, OM</tag>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.hadoop.ozone.OmUtils;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.OzoneFsServerDefaults;
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
Expand Down Expand Up @@ -391,6 +392,10 @@ public void deleteVolume(String volumeName) throws IOException {
proxy.deleteVolume(volumeName);
}

public OzoneFsServerDefaults getServerDefaults() throws IOException {
return proxy.getServerDefaults();
}

public KeyProvider getKeyProvider() throws IOException {
return proxy.getKeyProvider();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.hadoop.hdds.protocol.StorageType;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneFsServerDefaults;
import org.apache.hadoop.ozone.client.BucketArgs;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneKey;
Expand Down Expand Up @@ -858,6 +859,13 @@ TenantUserList listUsersInTenant(String tenantId, String prefix)
*/
TenantStateList listTenant() throws IOException;

/**
* Get server default values for a number of configuration params.
* @return Default configuration from the server.
* @throws IOException
*/
OzoneFsServerDefaults getServerDefaults() throws IOException;

/**
* Get KMS client provider.
* @return KMS client provider.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.fs.FileEncryptionInfo;
import org.apache.hadoop.fs.Syncable;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
Expand Down Expand Up @@ -61,6 +62,7 @@
import org.apache.hadoop.io.ByteBufferPool;
import org.apache.hadoop.io.ElasticByteBufferPool;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.ozone.OzoneFsServerDefaults;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.OzoneConsts;
Expand Down Expand Up @@ -178,6 +180,8 @@
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_KEY_PROVIDER_CACHE_EXPIRY;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_REQUIRED_OM_VERSION_MIN_KEY;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS_DEFAULT;
import static org.apache.hadoop.ozone.OzoneConsts.MAXIMUM_NUMBER_OF_PARTS_PER_UPLOAD;
import static org.apache.hadoop.ozone.OzoneConsts.OLD_QUOTA_DEFAULT;
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_MAXIMUM_ACCESS_ID_LENGTH;
Expand Down Expand Up @@ -224,6 +228,9 @@ public class RpcClient implements ClientProtocol {
private final ContainerClientMetrics clientMetrics;
private final MemoizedSupplier<ExecutorService> writeExecutor;
private final AtomicBoolean isS3GRequest = new AtomicBoolean(false);
private volatile OzoneFsServerDefaults serverDefaults;
private volatile long serverDefaultsLastUpdate;
private final long serverDefaultsValidityPeriod;

/**
* Creates RpcClient instance with the given configuration.
Expand Down Expand Up @@ -330,6 +337,11 @@ public void onRemoval(
.getInstance(byteBufferPool, ecReconstructExecutor);
this.clientMetrics = ContainerClientMetrics.acquire();

this.serverDefaultsValidityPeriod = conf.getTimeDuration(
OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS,
OZONE_CLIENT_SERVER_DEFAULTS_VALIDITY_PERIOD_MS_DEFAULT,
TimeUnit.MILLISECONDS);

TracingUtil.initTracing("client", conf);
}

Expand Down Expand Up @@ -2591,11 +2603,22 @@ public KeyProvider call() throws Exception {
}
}

@Override
public OzoneFsServerDefaults getServerDefaults() throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be great to have a test to verify this where it makes sure a second call within the expiration time to this API does not invoke ozoneManagerClient.getServerDefaults()

long now = Time.monotonicNow();
if ((serverDefaults == null) ||
(now - serverDefaultsLastUpdate > serverDefaultsValidityPeriod)) {
serverDefaults = ozoneManagerClient.getServerDefaults();
serverDefaultsLastUpdate = now;
}
assert serverDefaults != null;
return serverDefaults;
}

@Override
public URI getKeyProviderUri() throws IOException {
// TODO: fix me to support kms instances for difference OMs
return OzoneKMSUtil.getKeyProviderUri(ugi,
null, null, conf);
null, getServerDefaults().getKeyProviderUri(), conf);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ public static boolean isReadOnly(
case SetSafeMode:
case PrintCompactionLogDag:
case GetSnapshotInfo:
case GetServerDefaults:
return true;
case CreateVolume:
case SetVolumeProperty:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* 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;

import org.apache.hadoop.fs.FsServerDefaults;
import org.apache.hadoop.hdds.annotation.InterfaceAudience;
import org.apache.hadoop.hdds.annotation.InterfaceStability;

import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FsServerDefaultsProto;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FsServerDefaultsProto.Builder;


/****************************************************
* Provides server default configuration values to clients.
*
****************************************************/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public class OzoneFsServerDefaults extends FsServerDefaults {

public OzoneFsServerDefaults() {
}

public OzoneFsServerDefaults(String keyProviderUri) {
super(0L, 0, 0, (short)0, 0, false, 0L, null, keyProviderUri);
}

public FsServerDefaultsProto getProtobuf() {
Builder builder = FsServerDefaultsProto.newBuilder();
if (getKeyProviderUri() != null) {
builder.setKeyProviderUri(getKeyProviderUri());
}
return builder.build();
}

public static OzoneFsServerDefaults getFromProtobuf(
FsServerDefaultsProto serverDefaults) {
String keyProviderUri = null;
if (serverDefaults.hasKeyProviderUri()) {
keyProviderUri = serverDefaults.getKeyProviderUri();
}
return new OzoneFsServerDefaults(keyProviderUri);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.hadoop.fs.SafeModeAction;
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneFsServerDefaults;
import org.apache.hadoop.ozone.om.IOmMetadataReader;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.exceptions.OMException;
Expand Down Expand Up @@ -1178,4 +1179,12 @@ void setTimes(OmKeyArgs keyArgs, long mtime, long atime)
*/
boolean setSafeMode(SafeModeAction action, boolean isChecked)
throws IOException;

/**
* Get server default configurations.
*
* @return OzoneFsServerDefaults some default configurations from server.
* @throws IOException
*/
OzoneFsServerDefaults getServerDefaults() throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.apache.hadoop.ipc.CallerContext;
import org.apache.hadoop.ozone.ClientVersion;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneFsServerDefaults;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BasicOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.ErrorInfo;
Expand Down Expand Up @@ -197,6 +198,8 @@
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Secret;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SafeMode;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServerDefaultsRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServerDefaultsResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetAclRequest;
Expand Down Expand Up @@ -2644,6 +2647,22 @@ public boolean setSafeMode(SafeModeAction action, boolean isChecked)
return setSafeModeResponse.getResponse();
}

@Override
public OzoneFsServerDefaults getServerDefaults()
throws IOException {
ServerDefaultsRequest serverDefaultsRequest =
ServerDefaultsRequest.newBuilder().build();

OMRequest omRequest = createOMRequest(Type.GetServerDefaults)
.setServerDefaultsRequest(serverDefaultsRequest).build();

ServerDefaultsResponse serverDefaultsResponse =
handleError(submitRequest(omRequest)).getServerDefaultsResponse();

return OzoneFsServerDefaults.getFromProtobuf(
serverDefaultsResponse.getServerDefaults());
}

private SafeMode toProtoBuf(SafeModeAction action) {
switch (action) {
case ENTER:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4908,6 +4908,12 @@ public void testParallelDeleteBucketAndCreateKey() throws IOException,
assertThat(omSMLog.getOutput()).contains("Failed to write, Exception occurred");
}

@Test
public void testGetServerDefaults() throws IOException {
assertNotNull(getClient().getProxy().getServerDefaults());
assertNull(getClient().getProxy().getServerDefaults().getKeyProviderUri());
}

private static class OMRequestHandlerPauseInjector extends FaultInjector {
private CountDownLatch ready;
private CountDownLatch wait;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
*/
class TestSecureOzoneRpcClient extends OzoneRpcClientTests {

private static String keyProviderUri = "kms://http@kms:9600/kms";

@BeforeAll
public static void init() throws Exception {
File testDir = GenericTestUtils.getTestDir(
Expand All @@ -120,6 +122,8 @@ public static void init() throws Exception {
conf.set(OMConfigKeys.OZONE_DEFAULT_BUCKET_LAYOUT,
OMConfigKeys.OZONE_BUCKET_LAYOUT_OBJECT_STORE);
conf.setBoolean(OzoneConfigKeys.OZONE_FS_HSYNC_ENABLED, true);
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_KEY_PROVIDER_PATH,
keyProviderUri);
MiniOzoneCluster.Builder builder = MiniOzoneCluster.newBuilder(conf)
.setCertificateClient(certificateClientTest)
.setSecretKeyClient(new SecretKeyTestClient());
Expand Down Expand Up @@ -433,6 +437,13 @@ public void testS3Auth() throws Exception {
public void testZReadKeyWithUnhealthyContainerReplica() {
}

@Test
public void testGetServerDefaults() throws IOException {
assertNotNull(getClient().getProxy().getServerDefaults());
assertEquals(keyProviderUri,
getClient().getProxy().getServerDefaults().getKeyProviderUri());
}

@AfterAll
public static void shutdown() throws IOException {
shutdownCluster();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ enum Type {
RenameSnapshot = 131;
ListOpenFiles = 132;
QuotaRepair = 133;
GetServerDefaults = 134;
}

enum SafeMode {
Expand Down Expand Up @@ -287,6 +288,7 @@ message OMRequest {
optional RenameSnapshotRequest RenameSnapshotRequest = 129;
optional ListOpenFilesRequest ListOpenFilesRequest = 130;
optional QuotaRepairRequest QuotaRepairRequest = 131;
optional ServerDefaultsRequest ServerDefaultsRequest = 132;
}

message OMResponse {
Expand Down Expand Up @@ -412,6 +414,7 @@ message OMResponse {
optional RenameSnapshotResponse RenameSnapshotResponse = 132;
optional ListOpenFilesResponse ListOpenFilesResponse = 133;
optional QuotaRepairResponse QuotaRepairResponse = 134;
optional ServerDefaultsResponse ServerDefaultsResponse = 135;
}

enum Status {
Expand Down Expand Up @@ -2202,6 +2205,17 @@ message BucketQuotaCount {
message QuotaRepairResponse {
}

message ServerDefaultsRequest {
}

message FsServerDefaultsProto {
optional string keyProviderUri = 1;
}

message ServerDefaultsResponse {
required FsServerDefaultsProto serverDefaults = 1;
}

message OMLockDetailsProto {
optional bool isLockAcquired = 1;
optional uint64 waitLockNanos = 2;
Expand Down
Loading