From 92b53bbeeba1505d4600495b255b38e71f3a73fb Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Tue, 23 May 2023 18:46:59 +0530 Subject: [PATCH 01/12] HDDS-8677. Ozone admin OM CLI command for block tokens --- hadoop-hdds/framework/pom.xml | 6 ++ .../security/symmetric/ManagedSecretKey.java | 26 ++++++++ hadoop-ozone/common/pom.xml | 4 ++ .../java/org/apache/hadoop/ozone/OmUtils.java | 1 + .../om/protocol/OzoneManagerProtocol.java | 3 + ...ManagerProtocolClientSideTranslatorPB.java | 16 +++++ .../apache/hadoop/ozone/TestBlockTokens.java | 41 +++++++++++++ .../src/main/proto/OmClientProtocol.proto | 19 ++++++ .../apache/hadoop/ozone/om/OzoneManager.java | 5 ++ .../OzoneManagerRequestHandler.java | 19 ++++++ .../ozone/admin/om/FetchKeySubCommand.java | 60 +++++++++++++++++++ .../apache/hadoop/ozone/admin/om/OMAdmin.java | 3 +- 12 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java diff --git a/hadoop-hdds/framework/pom.xml b/hadoop-hdds/framework/pom.xml index 746129aae27c..39db6446e395 100644 --- a/hadoop-hdds/framework/pom.xml +++ b/hadoop-hdds/framework/pom.xml @@ -170,6 +170,12 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd"> org.awaitility awaitility + + org.apache.ozone + ozone-interface-client + 1.4.0-SNAPSHOT + compile + diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java index 2ff44daf9bec..39e270ee73e8 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java @@ -20,6 +20,7 @@ import com.google.protobuf.ByteString; import org.apache.hadoop.hdds.protocol.proto.SCMSecretKeyProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.util.ProtobufUtils; @@ -151,4 +152,29 @@ public static ManagedSecretKey fromProtobuf( message.getAlgorithm()); return new ManagedSecretKey(id, creationTime, expiryTime, secretKey); } + + public static ManagedSecretKey fromProtobuf( + OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse response) { + UUID id = ProtobufUtils.fromProtobuf(response.getSecretKey().getId()); + Instant creationTime = + Instant.ofEpochMilli(response.getSecretKey().getCreationTime()); + Instant expiryTime = + Instant.ofEpochMilli(response.getSecretKey().getExpiryTime()); + SecretKey secretKey = + new SecretKeySpec(response.getSecretKey().getEncoded().toByteArray(), + response.getSecretKey().getAlgorithm()); + return new ManagedSecretKey(id, creationTime, expiryTime, secretKey); + } + + public static OzoneManagerProtocolProtos.ManagedSecretKey toProto( + ManagedSecretKey secretKey) { + OzoneManagerProtocolProtos.ManagedSecretKey.Builder builder = + OzoneManagerProtocolProtos.ManagedSecretKey.newBuilder(); + builder.setId(ProtobufUtils.toProtobuf(secretKey.getId())) + .setCreationTime(secretKey.getCreationTime().toEpochMilli()) + .setExpiryTime(secretKey.getExpiryTime().toEpochMilli()) + .setAlgorithm(secretKey.getSecretKey().getAlgorithm()) + .setEncoded(ByteString.copyFrom(secretKey.getSecretKey().getEncoded())); + return builder.build(); + } } diff --git a/hadoop-ozone/common/pom.xml b/hadoop-ozone/common/pom.xml index 0199d7809a0d..298eba552276 100644 --- a/hadoop-ozone/common/pom.xml +++ b/hadoop-ozone/common/pom.xml @@ -111,6 +111,10 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.hadoop hadoop-hdfs-client + + org.apache.ozone + hdds-server-framework + diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java index 940fffb60301..6b926a7f4b02 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java @@ -255,6 +255,7 @@ public static boolean isReadOnly( case TenantListUser: case ListSnapshot: case EchoRPC: + case GetCurrentSecretKey: case RangerBGSync: // RangerBGSync is a read operation in the sense that it doesn't directly // write to OM DB. And therefore it doesn't need a OMClientRequest. diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java index ffbb0d3d400d..b72cfa36099c 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; +import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.IOmMetadataReader; import org.apache.hadoop.ozone.om.OMConfigKeys; @@ -995,4 +996,6 @@ EchoRPCResponse echoRPCReq(byte[] payloadReq, */ boolean recoverLease(String volumeName, String bucketName, String keyName) throws IOException; + + ManagedSecretKey getCurrentSecretKey() throws IOException; } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index b3c522eb61a7..2327695af0c5 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -32,6 +32,7 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos .UpgradeFinalizationStatus; import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; +import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.tracing.TracingUtil; import org.apache.hadoop.io.Text; import org.apache.hadoop.ozone.ClientVersion; @@ -104,6 +105,8 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; @@ -1355,6 +1358,19 @@ public S3VolumeContext getS3VolumeContext() throws IOException { return S3VolumeContext.fromProtobuf(resp); } + @Override + public ManagedSecretKey getCurrentSecretKey() throws IOException { + final GetCurrentSecretKeyRequest.Builder requestBuilder = + GetCurrentSecretKeyRequest.newBuilder(); + final OMRequest omRequest = createOMRequest(Type.GetCurrentSecretKey) + .setGetCurrentSecretKeyRequest(requestBuilder) + .build(); + final OMResponse omResponse = submitRequest(omRequest); + final GetCurrentSecretKeyResponse resp = + handleError(omResponse).getGetCurrentSecretKeyResponse(); + return ManagedSecretKey.fromProtobuf(resp); + } + /** * Return the proxy object underlying this protocol translator. * diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index a55e608fbf06..d6a3ff0434cc 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -20,6 +20,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.hadoop.hdds.annotation.InterfaceAudience; +import org.apache.hadoop.hdds.cli.OzoneAdmin; import org.apache.hadoop.hdds.conf.DefaultConfigManager; import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.scm.ScmConfig; @@ -55,10 +56,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.crypto.SecretKey; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; +import java.util.Base64; import java.util.Objects; import java.util.Properties; import java.util.UUID; @@ -112,6 +117,7 @@ public final class TestBlockTokens { public Timeout timeout = Timeout.seconds(180); private static MiniKdc miniKdc; + private static OzoneAdmin ozoneAdmin; private static OzoneConfiguration conf; private static File workDir; private static File ozoneKeytab; @@ -121,6 +127,7 @@ public final class TestBlockTokens { private static String host; private static String clusterId; private static String scmId; + private static String omServiceId; private static MiniOzoneHAClusterImpl cluster; private static OzoneClient client; private static BlockInputStreamFactory blockInputStreamFactory = @@ -137,6 +144,7 @@ public static void init() throws Exception { GenericTestUtils.getTestDir(TestBlockTokens.class.getSimpleName()); clusterId = UUID.randomUUID().toString(); scmId = UUID.randomUUID().toString(); + omServiceId = "om-service-test"; startMiniKdc(); setSecureConfig(); @@ -144,6 +152,7 @@ public static void init() throws Exception { setSecretKeysConfig(); startCluster(); client = cluster.newClient(); + ozoneAdmin = new OzoneAdmin(conf); createTestData(); } @@ -271,6 +280,37 @@ public void blockTokenFailsOnWrongPassword() throws Exception { assertExceptionContains("Invalid token for user", ex); } + @Test + public void testGetCurrentSecretKey() { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(outputStream); + System.setOut(printStream); + + String[] args = + new String[]{"om", "fetch-current-key", "--service-id=" + omServiceId}; + ozoneAdmin.execute(args); + + String actualOutput = outputStream.toString(); + System.setOut(System.out); + + String actualCurrentKey = testGetCurrentSecretKeyUtil(actualOutput); + SecretKey key = + getScmSecretKeyManager().getCurrentSecretKey().getSecretKey(); + byte[] encodedKey = key.getEncoded(); + String expectedCurrentKey = Base64.getEncoder().encodeToString(encodedKey); + assertEquals(expectedCurrentKey, actualCurrentKey); + } + + private String testGetCurrentSecretKeyUtil(String output) { + // Extract the current secret key from the output + String[] lines = output.split(System.lineSeparator()); + for (String line : lines) { + if (line.startsWith("Current Secret Key: ")) { + return line.substring("Current Secret Key: ".length()).trim(); + } + } + return null; + } private UUID extractSecretKeyId(OmKeyInfo keyInfo) throws IOException { OmKeyLocationInfo locationInfo = @@ -383,6 +423,7 @@ private static void startCluster() MiniOzoneCluster.Builder builder = MiniOzoneCluster.newHABuilder(conf) .setClusterId(clusterId) .setSCMServiceId("TestSecretKey") + .setOMServiceId("om-service-test") .setScmId(scmId) .setNumDatanodes(3) .setNumOfStorageContainerManagers(3) diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index a0d5fcbf6cc5..d4ff6ec68333 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -134,6 +134,7 @@ enum Type { TransferLeadership = 117; SnapshotPurge = 118; RecoverLease = 119; + GetCurrentSecretKey = 120; } message OMRequest { @@ -252,6 +253,7 @@ message OMRequest { optional SnapshotPurgeRequest SnapshotPurgeRequest = 118; optional RecoverLeaseRequest RecoverLeaseRequest = 119; + optional GetCurrentSecretKeyRequest GetCurrentSecretKeyRequest = 120; } message OMResponse { @@ -362,6 +364,7 @@ message OMResponse { optional hdds.TransferLeadershipResponseProto TransferOmLeadershipResponse = 117; optional SnapshotPurgeResponse SnapshotPurgeResponse = 118; optional RecoverLeaseResponse RecoverLeaseResponse = 119; + optional GetCurrentSecretKeyResponse GetCurrentSecretKeyResponse = 120; } enum Status { @@ -589,6 +592,22 @@ message SetVolumePropertyResponse { optional bool response = 1; } +message GetCurrentSecretKeyRequest { + +} + +message ManagedSecretKey { + required hdds.UUID id = 1; + required uint64 creationTime = 2; + required uint64 expiryTime = 3; + required string algorithm = 4; + required bytes encoded = 5; +} + +message GetCurrentSecretKeyResponse { + required ManagedSecretKey secretKey = 1; +} + /** * Checks if the user has specified permissions for the volume */ diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index b309d314d0b8..ccafb492afc0 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -81,6 +81,7 @@ import org.apache.hadoop.hdds.ratis.RatisHelper; import org.apache.hadoop.hdds.scm.ScmInfo; import org.apache.hadoop.hdds.scm.client.HddsClientUtils; +import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.server.OzoneAdmins; import org.apache.hadoop.hdds.utils.db.Table; import org.apache.hadoop.hdds.utils.db.Table.KeyValue; @@ -1064,6 +1065,10 @@ private void stopSecretManager() { } } + public ManagedSecretKey getCurrentSecretKey() { + return secretKeyClient.getCurrentSecretKey(); + } + @VisibleForTesting public void startSecretManager() { try { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index 44ec2be5f910..23f2b6568bcb 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -34,6 +34,7 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipResponseProto; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus; import org.apache.hadoop.hdds.client.ReplicationConfig; +import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.utils.db.SequenceNumberNotFoundException; import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.OzoneManager; @@ -78,6 +79,8 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVolumeRequest; @@ -310,6 +313,12 @@ public OMResponse handleReadRequest(OMRequest request) { responseBuilder.setTransferOmLeadershipResponse(transferLeadership( request.getTransferOmLeadershipRequest())); break; + case GetCurrentSecretKey: + GetCurrentSecretKeyResponse getCurrentSecretKeyResponse = + getCurrentSecretKey(request.getGetCurrentSecretKeyRequest()); + responseBuilder.setGetCurrentSecretKeyResponse( + getCurrentSecretKeyResponse); + break; default: responseBuilder.setSuccess(false); responseBuilder.setMessage("Unrecognized Command Type: " + cmdType); @@ -944,6 +953,16 @@ private RangerBGSyncResponse triggerRangerBGSync( return RangerBGSyncResponse.newBuilder().setRunSuccess(res).build(); } + private GetCurrentSecretKeyResponse getCurrentSecretKey( + GetCurrentSecretKeyRequest request) { + ManagedSecretKey managedSecretKey = impl.getCurrentSecretKey(); + GetCurrentSecretKeyResponse response = + GetCurrentSecretKeyResponse.newBuilder() + .setSecretKey(ManagedSecretKey.toProto(managedSecretKey)) + .build(); + return response; + } + @RequestFeatureValidator( conditions = ValidationCondition.OLDER_CLIENT_REQUESTS, processingPhase = RequestProcessingPhase.POST_PROCESS, diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java new file mode 100644 index 000000000000..78b9f0c51e1f --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -0,0 +1,60 @@ +/** + * 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.admin.om; + +import java.util.Base64; +import java.util.concurrent.Callable; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; +import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; +import picocli.CommandLine; + +import javax.crypto.SecretKey; + +/** + * Handler of ozone admin om fetch-current-key command. + */ +@CommandLine.Command( + name = "fetch-current-key", + description = "CLI command to fetch the latest key", + mixinStandardHelpOptions = true, + versionProvider = HddsVersionProvider.class +) +public class FetchKeySubCommand implements Callable { + @CommandLine.ParentCommand + private OMAdmin parent; + + @CommandLine.Option( + names = {"-id", "--service-id"}, + description = "Ozone Manager Service ID", + required = true + ) + private String omServiceId; + + @Override + public Void call() throws Exception { + OzoneManagerProtocol client = parent.createOmClient(omServiceId); + ManagedSecretKey managedSecretKey = client.getCurrentSecretKey(); + SecretKey key = managedSecretKey.getSecretKey(); + byte[] encodedKey = key.getEncoded(); + String keyString = Base64.getEncoder().encodeToString(encodedKey); + System.out.println("Current Secret Key: " + keyString); + return null; + } +} + diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java index 9bb447669d8b..d3b36db6d849 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java @@ -59,7 +59,8 @@ FinalizationStatusSubCommand.class, DecommissionOMSubcommand.class, UpdateRangerSubcommand.class, - TransferOmLeaderSubCommand.class + TransferOmLeaderSubCommand.class, + FetchKeySubCommand.class }) @MetaInfServices(SubcommandWithParent.class) public class OMAdmin extends GenericCli implements SubcommandWithParent { From 3996e7cfde3d05c3fd6d9532bef7bfb21efe0517 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Wed, 24 May 2023 10:53:25 +0530 Subject: [PATCH 02/12] Fix basic (findbugs) --- .../test/java/org/apache/hadoop/ozone/TestBlockTokens.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index d6a3ff0434cc..901e2ce053e1 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -61,6 +61,7 @@ import java.io.PrintStream; import java.io.File; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.io.InputStream; import java.net.InetAddress; import java.util.Base64; @@ -281,16 +282,16 @@ public void blockTokenFailsOnWrongPassword() throws Exception { } @Test - public void testGetCurrentSecretKey() { + public void testGetCurrentSecretKey() throws UnsupportedEncodingException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); + PrintStream printStream = new PrintStream(outputStream, true, "UTF-8"); System.setOut(printStream); String[] args = new String[]{"om", "fetch-current-key", "--service-id=" + omServiceId}; ozoneAdmin.execute(args); - String actualOutput = outputStream.toString(); + String actualOutput = outputStream.toString("UTF-8"); System.setOut(System.out); String actualCurrentKey = testGetCurrentSecretKeyUtil(actualOutput); From 971af3db65cd2fc0e1dceb9c632a21b6bbb05a09 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 25 May 2023 08:27:47 +0530 Subject: [PATCH 03/12] Rename CLI --- .../test/java/org/apache/hadoop/ozone/TestBlockTokens.java | 2 +- .../org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index 901e2ce053e1..beb8e7f6ddcc 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -288,7 +288,7 @@ public void testGetCurrentSecretKey() throws UnsupportedEncodingException { System.setOut(printStream); String[] args = - new String[]{"om", "fetch-current-key", "--service-id=" + omServiceId}; + new String[]{"om", "fetch-key", "--service-id=" + omServiceId}; ozoneAdmin.execute(args); String actualOutput = outputStream.toString("UTF-8"); diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 78b9f0c51e1f..050ca264d02e 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -27,10 +27,10 @@ import javax.crypto.SecretKey; /** - * Handler of ozone admin om fetch-current-key command. + * Handler of ozone admin om fetch-key command. */ @CommandLine.Command( - name = "fetch-current-key", + name = "fetch-key", description = "CLI command to fetch the latest key", mixinStandardHelpOptions = true, versionProvider = HddsVersionProvider.class From e768848d7ac7350317806c6a766766d98ad428fc Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 25 May 2023 08:33:40 +0530 Subject: [PATCH 04/12] Use try-with-resources --- .../hadoop/ozone/admin/om/FetchKeySubCommand.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 050ca264d02e..e083413e09f1 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -48,12 +48,13 @@ public class FetchKeySubCommand implements Callable { @Override public Void call() throws Exception { - OzoneManagerProtocol client = parent.createOmClient(omServiceId); - ManagedSecretKey managedSecretKey = client.getCurrentSecretKey(); - SecretKey key = managedSecretKey.getSecretKey(); - byte[] encodedKey = key.getEncoded(); - String keyString = Base64.getEncoder().encodeToString(encodedKey); - System.out.println("Current Secret Key: " + keyString); + try (OzoneManagerProtocol client = parent.createOmClient(omServiceId)) { + ManagedSecretKey managedSecretKey = client.getCurrentSecretKey(); + SecretKey key = managedSecretKey.getSecretKey(); + byte[] encodedKey = key.getEncoded(); + String keyString = Base64.getEncoder().encodeToString(encodedKey); + System.out.println("Current Secret Key: " + keyString); + } return null; } } From 9bd5790c130c46e1855d359147c242362cd43b27 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 25 May 2023 09:33:02 +0530 Subject: [PATCH 05/12] Output expiration time as part of command --- .../hadoop/ozone/admin/om/FetchKeySubCommand.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index e083413e09f1..9ea5f561fbaf 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -17,6 +17,9 @@ package org.apache.hadoop.ozone.admin.om; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.concurrent.Callable; import org.apache.hadoop.hdds.cli.HddsVersionProvider; @@ -53,7 +56,15 @@ public Void call() throws Exception { SecretKey key = managedSecretKey.getSecretKey(); byte[] encodedKey = key.getEncoded(); String keyString = Base64.getEncoder().encodeToString(encodedKey); + + Instant expiryTime = managedSecretKey.getExpiryTime(); + DateTimeFormatter formatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss") + .withZone(ZoneOffset.UTC); + String expiryTimeString = formatter.format(expiryTime); + System.out.println("Current Secret Key: " + keyString); + System.out.println("Expiry Time: " + expiryTimeString); } return null; } From f07031ce287a9382fd00be86f66ce3b9b8b1d072 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Tue, 30 May 2023 12:22:34 +0530 Subject: [PATCH 06/12] Simplify patch: avoid importing dependencies --- hadoop-hdds/framework/pom.xml | 6 ----- .../security/symmetric/ManagedSecretKey.java | 26 ------------------- hadoop-ozone/common/pom.xml | 4 --- .../om/protocol/OzoneManagerProtocol.java | 3 +-- ...ManagerProtocolClientSideTranslatorPB.java | 8 ++---- .../apache/hadoop/ozone/TestBlockTokens.java | 19 +------------- .../src/main/proto/OmClientProtocol.proto | 10 +------ .../apache/hadoop/ozone/om/OzoneManager.java | 5 ++-- .../OzoneManagerRequestHandler.java | 16 +++--------- .../ozone/admin/om/FetchKeySubCommand.java | 22 ++-------------- 10 files changed, 13 insertions(+), 106 deletions(-) diff --git a/hadoop-hdds/framework/pom.xml b/hadoop-hdds/framework/pom.xml index 39db6446e395..746129aae27c 100644 --- a/hadoop-hdds/framework/pom.xml +++ b/hadoop-hdds/framework/pom.xml @@ -170,12 +170,6 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd"> org.awaitility awaitility - - org.apache.ozone - ozone-interface-client - 1.4.0-SNAPSHOT - compile - diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java index 39e270ee73e8..2ff44daf9bec 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/ManagedSecretKey.java @@ -20,7 +20,6 @@ import com.google.protobuf.ByteString; import org.apache.hadoop.hdds.protocol.proto.SCMSecretKeyProtocolProtos; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.util.ProtobufUtils; @@ -152,29 +151,4 @@ public static ManagedSecretKey fromProtobuf( message.getAlgorithm()); return new ManagedSecretKey(id, creationTime, expiryTime, secretKey); } - - public static ManagedSecretKey fromProtobuf( - OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse response) { - UUID id = ProtobufUtils.fromProtobuf(response.getSecretKey().getId()); - Instant creationTime = - Instant.ofEpochMilli(response.getSecretKey().getCreationTime()); - Instant expiryTime = - Instant.ofEpochMilli(response.getSecretKey().getExpiryTime()); - SecretKey secretKey = - new SecretKeySpec(response.getSecretKey().getEncoded().toByteArray(), - response.getSecretKey().getAlgorithm()); - return new ManagedSecretKey(id, creationTime, expiryTime, secretKey); - } - - public static OzoneManagerProtocolProtos.ManagedSecretKey toProto( - ManagedSecretKey secretKey) { - OzoneManagerProtocolProtos.ManagedSecretKey.Builder builder = - OzoneManagerProtocolProtos.ManagedSecretKey.newBuilder(); - builder.setId(ProtobufUtils.toProtobuf(secretKey.getId())) - .setCreationTime(secretKey.getCreationTime().toEpochMilli()) - .setExpiryTime(secretKey.getExpiryTime().toEpochMilli()) - .setAlgorithm(secretKey.getSecretKey().getAlgorithm()) - .setEncoded(ByteString.copyFrom(secretKey.getSecretKey().getEncoded())); - return builder.build(); - } } diff --git a/hadoop-ozone/common/pom.xml b/hadoop-ozone/common/pom.xml index 298eba552276..0199d7809a0d 100644 --- a/hadoop-ozone/common/pom.xml +++ b/hadoop-ozone/common/pom.xml @@ -111,10 +111,6 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.hadoop hadoop-hdfs-client - - org.apache.ozone - hdds-server-framework - diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java index b72cfa36099c..90f36d039d04 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java @@ -23,7 +23,6 @@ import java.util.List; import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; -import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.IOmMetadataReader; import org.apache.hadoop.ozone.om.OMConfigKeys; @@ -997,5 +996,5 @@ EchoRPCResponse echoRPCReq(byte[] payloadReq, boolean recoverLease(String volumeName, String bucketName, String keyName) throws IOException; - ManagedSecretKey getCurrentSecretKey() throws IOException; + void refetchSecretKey() throws IOException; } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index 2327695af0c5..225725bfb249 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -32,7 +32,6 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos .UpgradeFinalizationStatus; import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; -import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.tracing.TracingUtil; import org.apache.hadoop.io.Text; import org.apache.hadoop.ozone.ClientVersion; @@ -106,7 +105,6 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyRequest; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; @@ -1359,16 +1357,14 @@ public S3VolumeContext getS3VolumeContext() throws IOException { } @Override - public ManagedSecretKey getCurrentSecretKey() throws IOException { + public void refetchSecretKey() throws IOException { final GetCurrentSecretKeyRequest.Builder requestBuilder = GetCurrentSecretKeyRequest.newBuilder(); final OMRequest omRequest = createOMRequest(Type.GetCurrentSecretKey) .setGetCurrentSecretKeyRequest(requestBuilder) .build(); final OMResponse omResponse = submitRequest(omRequest); - final GetCurrentSecretKeyResponse resp = - handleError(omResponse).getGetCurrentSecretKeyResponse(); - return ManagedSecretKey.fromProtobuf(resp); + handleError(omResponse); } /** diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index beb8e7f6ddcc..8f3c39e3033e 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -56,7 +56,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.crypto.SecretKey; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.File; @@ -64,7 +63,6 @@ import java.io.UnsupportedEncodingException; import java.io.InputStream; import java.net.InetAddress; -import java.util.Base64; import java.util.Objects; import java.util.Properties; import java.util.UUID; @@ -294,24 +292,9 @@ public void testGetCurrentSecretKey() throws UnsupportedEncodingException { String actualOutput = outputStream.toString("UTF-8"); System.setOut(System.out); - String actualCurrentKey = testGetCurrentSecretKeyUtil(actualOutput); - SecretKey key = - getScmSecretKeyManager().getCurrentSecretKey().getSecretKey(); - byte[] encodedKey = key.getEncoded(); - String expectedCurrentKey = Base64.getEncoder().encodeToString(encodedKey); - assertEquals(expectedCurrentKey, actualCurrentKey); + assertTrue(actualOutput.contains("Successfully re-fetched the secret key")); } - private String testGetCurrentSecretKeyUtil(String output) { - // Extract the current secret key from the output - String[] lines = output.split(System.lineSeparator()); - for (String line : lines) { - if (line.startsWith("Current Secret Key: ")) { - return line.substring("Current Secret Key: ".length()).trim(); - } - } - return null; - } private UUID extractSecretKeyId(OmKeyInfo keyInfo) throws IOException { OmKeyLocationInfo locationInfo = diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index d4ff6ec68333..053f092d89ea 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -596,16 +596,8 @@ message GetCurrentSecretKeyRequest { } -message ManagedSecretKey { - required hdds.UUID id = 1; - required uint64 creationTime = 2; - required uint64 expiryTime = 3; - required string algorithm = 4; - required bytes encoded = 5; -} - message GetCurrentSecretKeyResponse { - required ManagedSecretKey secretKey = 1; + } /** diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index ccafb492afc0..3b43d1b3f04e 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -81,7 +81,6 @@ import org.apache.hadoop.hdds.ratis.RatisHelper; import org.apache.hadoop.hdds.scm.ScmInfo; import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.server.OzoneAdmins; import org.apache.hadoop.hdds.utils.db.Table; import org.apache.hadoop.hdds.utils.db.Table.KeyValue; @@ -1065,8 +1064,8 @@ private void stopSecretManager() { } } - public ManagedSecretKey getCurrentSecretKey() { - return secretKeyClient.getCurrentSecretKey(); + public void refetchSecretKey() { + secretKeyClient.getCurrentSecretKey(); } @VisibleForTesting diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index 23f2b6568bcb..7c4436309046 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -34,7 +34,6 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipResponseProto; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus; import org.apache.hadoop.hdds.client.ReplicationConfig; -import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.hdds.utils.db.SequenceNumberNotFoundException; import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.OzoneManager; @@ -79,7 +78,6 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoResponse; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketResponse; @@ -314,10 +312,7 @@ public OMResponse handleReadRequest(OMRequest request) { request.getTransferOmLeadershipRequest())); break; case GetCurrentSecretKey: - GetCurrentSecretKeyResponse getCurrentSecretKeyResponse = - getCurrentSecretKey(request.getGetCurrentSecretKeyRequest()); - responseBuilder.setGetCurrentSecretKeyResponse( - getCurrentSecretKeyResponse); + responseBuilder.setGetCurrentSecretKeyResponse(getCurrentSecretKey()); break; default: responseBuilder.setSuccess(false); @@ -953,13 +948,10 @@ private RangerBGSyncResponse triggerRangerBGSync( return RangerBGSyncResponse.newBuilder().setRunSuccess(res).build(); } - private GetCurrentSecretKeyResponse getCurrentSecretKey( - GetCurrentSecretKeyRequest request) { - ManagedSecretKey managedSecretKey = impl.getCurrentSecretKey(); + private GetCurrentSecretKeyResponse getCurrentSecretKey() { + impl.refetchSecretKey(); GetCurrentSecretKeyResponse response = - GetCurrentSecretKeyResponse.newBuilder() - .setSecretKey(ManagedSecretKey.toProto(managedSecretKey)) - .build(); + GetCurrentSecretKeyResponse.newBuilder().build(); return response; } diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 9ea5f561fbaf..8ba9eaac5b07 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -17,18 +17,11 @@ package org.apache.hadoop.ozone.admin.om; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.Base64; import java.util.concurrent.Callable; import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.security.symmetric.ManagedSecretKey; import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; import picocli.CommandLine; -import javax.crypto.SecretKey; - /** * Handler of ozone admin om fetch-key command. */ @@ -52,19 +45,8 @@ public class FetchKeySubCommand implements Callable { @Override public Void call() throws Exception { try (OzoneManagerProtocol client = parent.createOmClient(omServiceId)) { - ManagedSecretKey managedSecretKey = client.getCurrentSecretKey(); - SecretKey key = managedSecretKey.getSecretKey(); - byte[] encodedKey = key.getEncoded(); - String keyString = Base64.getEncoder().encodeToString(encodedKey); - - Instant expiryTime = managedSecretKey.getExpiryTime(); - DateTimeFormatter formatter = DateTimeFormatter - .ofPattern("yyyy-MM-dd HH:mm:ss") - .withZone(ZoneOffset.UTC); - String expiryTimeString = formatter.format(expiryTime); - - System.out.println("Current Secret Key: " + keyString); - System.out.println("Expiry Time: " + expiryTimeString); + client.refetchSecretKey(); + System.out.println("Successfully re-fetched the secret key."); } return null; } From 0bc81a30e682845085971f71d489e585ae6c9f26 Mon Sep 17 00:00:00 2001 From: tanvipenumudy <46785609+tanvipenumudy@users.noreply.github.com> Date: Thu, 1 Jun 2023 08:02:42 +0530 Subject: [PATCH 07/12] Update hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java Modify description to CLI command Co-authored-by: Duong Nguyen --- .../org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 8ba9eaac5b07..0cbae30f3fca 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -27,7 +27,7 @@ */ @CommandLine.Command( name = "fetch-key", - description = "CLI command to fetch the latest key", + description = "CLI command to force OM to fetch the the latest secret key from SCM.", mixinStandardHelpOptions = true, versionProvider = HddsVersionProvider.class ) From 3711d8c3cd39f568f2047e5824fec101062eb015 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 1 Jun 2023 08:58:20 +0530 Subject: [PATCH 08/12] Refactor Request/Response names to RefetchSecretKey --- .../main/java/org/apache/hadoop/ozone/OmUtils.java | 2 +- .../OzoneManagerProtocolClientSideTranslatorPB.java | 10 +++++----- .../org/apache/hadoop/ozone/TestBlockTokens.java | 3 +-- .../src/main/proto/OmClientProtocol.proto | 10 +++++----- .../ozone/protocolPB/OzoneManagerRequestHandler.java | 12 ++++++------ 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java index 6b926a7f4b02..05790d0cd0d7 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java @@ -255,7 +255,7 @@ public static boolean isReadOnly( case TenantListUser: case ListSnapshot: case EchoRPC: - case GetCurrentSecretKey: + case RefetchSecretKey: case RangerBGSync: // RangerBGSync is a read operation in the sense that it doesn't directly // write to OM DB. And therefore it doesn't need a OMClientRequest. diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index 225725bfb249..0695a289c69f 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -104,7 +104,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclResponse; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; @@ -1358,10 +1358,10 @@ public S3VolumeContext getS3VolumeContext() throws IOException { @Override public void refetchSecretKey() throws IOException { - final GetCurrentSecretKeyRequest.Builder requestBuilder = - GetCurrentSecretKeyRequest.newBuilder(); - final OMRequest omRequest = createOMRequest(Type.GetCurrentSecretKey) - .setGetCurrentSecretKeyRequest(requestBuilder) + final RefetchSecretKeyRequest.Builder requestBuilder = + RefetchSecretKeyRequest.newBuilder(); + final OMRequest omRequest = createOMRequest(Type.RefetchSecretKey) + .setRefetchSecretKeyRequest(requestBuilder) .build(); final OMResponse omResponse = submitRequest(omRequest); handleError(omResponse); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index 8f3c39e3033e..aa46491fff4d 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -280,7 +280,7 @@ public void blockTokenFailsOnWrongPassword() throws Exception { } @Test - public void testGetCurrentSecretKey() throws UnsupportedEncodingException { + public void testFetchKeyOMAdminCommand() throws UnsupportedEncodingException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PrintStream printStream = new PrintStream(outputStream, true, "UTF-8"); System.setOut(printStream); @@ -295,7 +295,6 @@ public void testGetCurrentSecretKey() throws UnsupportedEncodingException { assertTrue(actualOutput.contains("Successfully re-fetched the secret key")); } - private UUID extractSecretKeyId(OmKeyInfo keyInfo) throws IOException { OmKeyLocationInfo locationInfo = keyInfo.getKeyLocationVersions().get(0).getLocationList().get(0); diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index 053f092d89ea..e0e11b4d8f3c 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -134,7 +134,7 @@ enum Type { TransferLeadership = 117; SnapshotPurge = 118; RecoverLease = 119; - GetCurrentSecretKey = 120; + RefetchSecretKey = 120; } message OMRequest { @@ -253,7 +253,7 @@ message OMRequest { optional SnapshotPurgeRequest SnapshotPurgeRequest = 118; optional RecoverLeaseRequest RecoverLeaseRequest = 119; - optional GetCurrentSecretKeyRequest GetCurrentSecretKeyRequest = 120; + optional RefetchSecretKeyRequest RefetchSecretKeyRequest = 120; } message OMResponse { @@ -364,7 +364,7 @@ message OMResponse { optional hdds.TransferLeadershipResponseProto TransferOmLeadershipResponse = 117; optional SnapshotPurgeResponse SnapshotPurgeResponse = 118; optional RecoverLeaseResponse RecoverLeaseResponse = 119; - optional GetCurrentSecretKeyResponse GetCurrentSecretKeyResponse = 120; + optional RefetchSecretKeyResponse RefetchSecretKeyResponse = 120; } enum Status { @@ -592,11 +592,11 @@ message SetVolumePropertyResponse { optional bool response = 1; } -message GetCurrentSecretKeyRequest { +message RefetchSecretKeyRequest { } -message GetCurrentSecretKeyResponse { +message RefetchSecretKeyResponse { } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index 7c4436309046..27efe5906171 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -78,7 +78,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetKeyInfoResponse; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetCurrentSecretKeyResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVolumeRequest; @@ -311,8 +311,8 @@ public OMResponse handleReadRequest(OMRequest request) { responseBuilder.setTransferOmLeadershipResponse(transferLeadership( request.getTransferOmLeadershipRequest())); break; - case GetCurrentSecretKey: - responseBuilder.setGetCurrentSecretKeyResponse(getCurrentSecretKey()); + case RefetchSecretKey: + responseBuilder.setRefetchSecretKeyResponse(refetchSecretKey()); break; default: responseBuilder.setSuccess(false); @@ -948,10 +948,10 @@ private RangerBGSyncResponse triggerRangerBGSync( return RangerBGSyncResponse.newBuilder().setRunSuccess(res).build(); } - private GetCurrentSecretKeyResponse getCurrentSecretKey() { + private RefetchSecretKeyResponse refetchSecretKey() { impl.refetchSecretKey(); - GetCurrentSecretKeyResponse response = - GetCurrentSecretKeyResponse.newBuilder().build(); + RefetchSecretKeyResponse response = + RefetchSecretKeyResponse.newBuilder().build(); return response; } From f80fad98d3b94eb805a2aaadb3a55e9a27c5d92c Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 1 Jun 2023 09:00:55 +0530 Subject: [PATCH 09/12] fix checkstyle --- .../org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 0cbae30f3fca..8d5d8cc0e807 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -27,7 +27,8 @@ */ @CommandLine.Command( name = "fetch-key", - description = "CLI command to force OM to fetch the the latest secret key from SCM.", + description = "CLI command to force OM to fetch the latest secret key " + + "from SCM.", mixinStandardHelpOptions = true, versionProvider = HddsVersionProvider.class ) From b0b3ea7868e37898bc67aaa5a5f4fbb9726ed800 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 1 Jun 2023 09:16:34 +0530 Subject: [PATCH 10/12] Move tests to a separate class --- .../apache/hadoop/ozone/TestBlockTokens.java | 25 --- .../hadoop/ozone/TestBlockTokensCLI.java | 212 ++++++++++++++++++ 2 files changed, 212 insertions(+), 25 deletions(-) create mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java index aa46491fff4d..6661c81b44c6 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokens.java @@ -20,7 +20,6 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.hadoop.hdds.annotation.InterfaceAudience; -import org.apache.hadoop.hdds.cli.OzoneAdmin; import org.apache.hadoop.hdds.conf.DefaultConfigManager; import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.scm.ScmConfig; @@ -56,11 +55,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.io.File; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.io.InputStream; import java.net.InetAddress; import java.util.Objects; @@ -116,7 +112,6 @@ public final class TestBlockTokens { public Timeout timeout = Timeout.seconds(180); private static MiniKdc miniKdc; - private static OzoneAdmin ozoneAdmin; private static OzoneConfiguration conf; private static File workDir; private static File ozoneKeytab; @@ -126,7 +121,6 @@ public final class TestBlockTokens { private static String host; private static String clusterId; private static String scmId; - private static String omServiceId; private static MiniOzoneHAClusterImpl cluster; private static OzoneClient client; private static BlockInputStreamFactory blockInputStreamFactory = @@ -143,7 +137,6 @@ public static void init() throws Exception { GenericTestUtils.getTestDir(TestBlockTokens.class.getSimpleName()); clusterId = UUID.randomUUID().toString(); scmId = UUID.randomUUID().toString(); - omServiceId = "om-service-test"; startMiniKdc(); setSecureConfig(); @@ -151,7 +144,6 @@ public static void init() throws Exception { setSecretKeysConfig(); startCluster(); client = cluster.newClient(); - ozoneAdmin = new OzoneAdmin(conf); createTestData(); } @@ -279,22 +271,6 @@ public void blockTokenFailsOnWrongPassword() throws Exception { assertExceptionContains("Invalid token for user", ex); } - @Test - public void testFetchKeyOMAdminCommand() throws UnsupportedEncodingException { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream, true, "UTF-8"); - System.setOut(printStream); - - String[] args = - new String[]{"om", "fetch-key", "--service-id=" + omServiceId}; - ozoneAdmin.execute(args); - - String actualOutput = outputStream.toString("UTF-8"); - System.setOut(System.out); - - assertTrue(actualOutput.contains("Successfully re-fetched the secret key")); - } - private UUID extractSecretKeyId(OmKeyInfo keyInfo) throws IOException { OmKeyLocationInfo locationInfo = keyInfo.getKeyLocationVersions().get(0).getLocationList().get(0); @@ -406,7 +382,6 @@ private static void startCluster() MiniOzoneCluster.Builder builder = MiniOzoneCluster.newHABuilder(conf) .setClusterId(clusterId) .setSCMServiceId("TestSecretKey") - .setOMServiceId("om-service-test") .setScmId(scmId) .setNumDatanodes(3) .setNumOfStorageContainerManagers(3) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java new file mode 100644 index 000000000000..6a1ca1e4e5c4 --- /dev/null +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java @@ -0,0 +1,212 @@ +/* + * 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; + +import org.apache.hadoop.hdds.annotation.InterfaceAudience; +import org.apache.hadoop.hdds.cli.OzoneAdmin; +import org.apache.hadoop.hdds.conf.DefaultConfigManager; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.hdds.scm.ScmConfig; +import org.apache.hadoop.hdds.scm.server.SCMHTTPServerConfig; +import org.apache.hadoop.hdds.utils.IOUtils; +import org.apache.hadoop.minikdc.MiniKdc; +import org.apache.hadoop.ozone.client.OzoneClient; +import org.apache.hadoop.ozone.om.OzoneManager; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.ozone.test.GenericTestUtils; +import org.apache.ratis.util.ExitUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.net.InetAddress; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.TimeoutException; + +import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION; +import static org.apache.hadoop.hdds.DFSConfigKeysLegacy.DFS_DATANODE_KERBEROS_KEYTAB_FILE_KEY; +import static org.apache.hadoop.hdds.DFSConfigKeysLegacy.DFS_DATANODE_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_BLOCK_TOKEN_ENABLED; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_CONTAINER_TOKEN_ENABLED; +import static org.apache.hadoop.hdds.scm.ScmConfig.ConfigStrings.HDDS_SCM_KERBEROS_KEYTAB_FILE_KEY; +import static org.apache.hadoop.hdds.scm.ScmConfig.ConfigStrings.HDDS_SCM_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY; +import static org.apache.hadoop.hdds.scm.server.SCMHTTPServerConfig.ConfigStrings.HDDS_SCM_HTTP_KERBEROS_KEYTAB_FILE_KEY; +import static org.apache.hadoop.hdds.scm.server.SCMHTTPServerConfig.ConfigStrings.HDDS_SCM_HTTP_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS; +import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HTTP_KERBEROS_KEYTAB_FILE; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HTTP_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS; +import static org.junit.Assert.assertTrue; + +/** + * Integration test class to verify block token CLI commands functionality in a + * secure cluster. + */ +@InterfaceAudience.Private +public final class TestBlockTokensCLI { + private static final Logger LOG = LoggerFactory + .getLogger(TestBlockTokensCLI.class); + + @Rule + public Timeout timeout = Timeout.seconds(180); + + private static MiniKdc miniKdc; + private static OzoneAdmin ozoneAdmin; + private static OzoneConfiguration conf; + private static File workDir; + private static File ozoneKeytab; + private static File spnegoKeytab; + private static String host; + private static String clusterId; + private static String scmId; + private static String omServiceId; + private static MiniOzoneHAClusterImpl cluster; + private static OzoneClient client; + + @BeforeClass + public static void init() throws Exception { + conf = new OzoneConfiguration(); + conf.set(OZONE_SCM_CLIENT_ADDRESS_KEY, "localhost"); + + ExitUtils.disableSystemExit(); + + workDir = + GenericTestUtils.getTestDir(TestBlockTokens.class.getSimpleName()); + clusterId = UUID.randomUUID().toString(); + scmId = UUID.randomUUID().toString(); + omServiceId = "om-service-test"; + + startMiniKdc(); + setSecureConfig(); + createCredentialsInKDC(); + setSecretKeysConfig(); + startCluster(); + client = cluster.newClient(); + ozoneAdmin = new OzoneAdmin(conf); + } + + @AfterClass + public static void stop() { + miniKdc.stop(); + IOUtils.close(LOG, client); + if (cluster != null) { + cluster.stop(); + } + DefaultConfigManager.clearDefaultConfigs(); + } + + private static void setSecretKeysConfig() { + // enable tokens + conf.setBoolean(HDDS_BLOCK_TOKEN_ENABLED, true); + conf.setBoolean(HDDS_CONTAINER_TOKEN_ENABLED, true); + } + + private static void createCredentialsInKDC() throws Exception { + ScmConfig scmConfig = conf.getObject(ScmConfig.class); + SCMHTTPServerConfig httpServerConfig = + conf.getObject(SCMHTTPServerConfig.class); + createPrincipal(ozoneKeytab, scmConfig.getKerberosPrincipal()); + createPrincipal(spnegoKeytab, httpServerConfig.getKerberosPrincipal()); + } + + private static void createPrincipal(File keytab, String... principal) + throws Exception { + miniKdc.createPrincipal(keytab, principal); + } + + private static void startMiniKdc() throws Exception { + Properties securityProperties = MiniKdc.createConf(); + miniKdc = new MiniKdc(securityProperties, workDir); + miniKdc.start(); + } + + private static void setSecureConfig() throws IOException { + conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true); + host = InetAddress.getLocalHost().getCanonicalHostName() + .toLowerCase(); + + conf.set(HADOOP_SECURITY_AUTHENTICATION, KERBEROS.name()); + + String curUser = UserGroupInformation.getCurrentUser().getUserName(); + conf.set(OZONE_ADMINISTRATORS, curUser); + + String realm = miniKdc.getRealm(); + String hostAndRealm = host + "@" + realm; + conf.set(HDDS_SCM_KERBEROS_PRINCIPAL_KEY, "scm/" + hostAndRealm); + conf.set(HDDS_SCM_HTTP_KERBEROS_PRINCIPAL_KEY, "HTTP_SCM/" + hostAndRealm); + conf.set(OZONE_OM_KERBEROS_PRINCIPAL_KEY, "scm/" + hostAndRealm); + conf.set(OZONE_OM_HTTP_KERBEROS_PRINCIPAL_KEY, "HTTP_OM/" + hostAndRealm); + conf.set(DFS_DATANODE_KERBEROS_PRINCIPAL_KEY, "scm/" + hostAndRealm); + + ozoneKeytab = new File(workDir, "scm.keytab"); + spnegoKeytab = new File(workDir, "http.keytab"); + + conf.set(HDDS_SCM_KERBEROS_KEYTAB_FILE_KEY, + ozoneKeytab.getAbsolutePath()); + conf.set(HDDS_SCM_HTTP_KERBEROS_KEYTAB_FILE_KEY, + spnegoKeytab.getAbsolutePath()); + conf.set(OZONE_OM_KERBEROS_KEYTAB_FILE_KEY, + ozoneKeytab.getAbsolutePath()); + conf.set(OZONE_OM_HTTP_KERBEROS_KEYTAB_FILE, + spnegoKeytab.getAbsolutePath()); + conf.set(DFS_DATANODE_KERBEROS_KEYTAB_FILE_KEY, + ozoneKeytab.getAbsolutePath()); + } + + @Test + public void testFetchKeyOMAdminCommand() throws UnsupportedEncodingException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(outputStream, true, "UTF-8"); + System.setOut(printStream); + + String[] args = + new String[]{"om", "fetch-key", "--service-id=" + omServiceId}; + ozoneAdmin.execute(args); + + String actualOutput = outputStream.toString("UTF-8"); + System.setOut(System.out); + + assertTrue(actualOutput.contains("Successfully re-fetched the secret key")); + } + + private static void startCluster() + throws IOException, TimeoutException, InterruptedException { + OzoneManager.setTestSecureOmFlag(true); + MiniOzoneCluster.Builder builder = MiniOzoneCluster.newHABuilder(conf) + .setClusterId(clusterId) + .setSCMServiceId("TestSecretKey") + .setOMServiceId(omServiceId) + .setScmId(scmId) + .setNumDatanodes(3) + .setNumOfStorageContainerManagers(3) + .setNumOfOzoneManagers(1); + + cluster = (MiniOzoneHAClusterImpl) builder.build(); + cluster.waitForClusterToBeReady(); + } +} From 752bc5a89d7f5b71fa1c7db5835173930cf04126 Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 1 Jun 2023 11:47:39 +0530 Subject: [PATCH 11/12] Implement refetchSecretKey under DefaultSecretKeySignerClient --- .../security/symmetric/DefaultSecretKeySignerClient.java | 8 +++++++- .../hdds/security/symmetric/SecretKeySignerClient.java | 3 +++ .../java/org/apache/hadoop/ozone/TestBlockTokensCLI.java | 6 +++++- .../java/org/apache/hadoop/ozone/om/OzoneManager.java | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/DefaultSecretKeySignerClient.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/DefaultSecretKeySignerClient.java index daabf74e3716..d5e12689f9c2 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/DefaultSecretKeySignerClient.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/DefaultSecretKeySignerClient.java @@ -60,6 +60,12 @@ public ManagedSecretKey getCurrentSecretKey() { "SecretKey client must have been initialized already."); } + @Override + public void refetchSecretKey() { + // pass duration as ZERO to force a refresh. + checkAndRefresh(Duration.ZERO); + } + @Override public void start(ConfigurationSource conf) throws IOException { final ManagedSecretKey initialKey = @@ -103,7 +109,7 @@ private void scheduleSecretKeyPoller(ConfigurationSource conf, TimeUnit.MILLISECONDS); } - private void checkAndRefresh(Duration rotateDuration) { + private synchronized void checkAndRefresh(Duration rotateDuration) { ManagedSecretKey current = cache.get(); Instant nextRotate = current.getCreationTime().plus(rotateDuration); // when the current key passes the rotation cycle, fetch the next one diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/SecretKeySignerClient.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/SecretKeySignerClient.java index d05786db5c62..0ae010545f74 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/SecretKeySignerClient.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/symmetric/SecretKeySignerClient.java @@ -40,4 +40,7 @@ default void start(ConfigurationSource conf) throws IOException { */ default void stop() { } + + default void refetchSecretKey() { + } } diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java index 6a1ca1e4e5c4..6dec05c258d1 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java @@ -38,7 +38,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.net.InetAddress; import java.util.Properties; import java.util.UUID; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index 3b43d1b3f04e..70579e086142 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -1065,7 +1065,7 @@ private void stopSecretManager() { } public void refetchSecretKey() { - secretKeyClient.getCurrentSecretKey(); + secretKeyClient.refetchSecretKey(); } @VisibleForTesting From d749efa622babe7d8f67295da42e46f4923be5db Mon Sep 17 00:00:00 2001 From: tanvipenumudy Date: Thu, 1 Jun 2023 16:49:10 +0530 Subject: [PATCH 12/12] Modify refetchSecretKey() to return Secret Key ID --- .../om/protocol/OzoneManagerProtocol.java | 3 ++- ...ManagerProtocolClientSideTranslatorPB.java | 11 +++++--- .../hadoop/ozone/TestBlockTokensCLI.java | 27 ++++++++++++++++--- .../src/main/proto/OmClientProtocol.proto | 2 +- .../apache/hadoop/ozone/om/OzoneManager.java | 4 ++- .../OzoneManagerRequestHandler.java | 7 +++-- .../ozone/admin/om/FetchKeySubCommand.java | 5 ++-- 7 files changed, 46 insertions(+), 13 deletions(-) diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java index 90f36d039d04..aaffb0d3603f 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java @@ -21,6 +21,7 @@ import java.io.Closeable; import java.io.IOException; import java.util.List; +import java.util.UUID; import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; import org.apache.hadoop.ozone.OzoneAcl; @@ -996,5 +997,5 @@ EchoRPCResponse echoRPCReq(byte[] payloadReq, boolean recoverLease(String volumeName, String bucketName, String keyName) throws IOException; - void refetchSecretKey() throws IOException; + UUID refetchSecretKey() throws IOException; } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index 0695a289c69f..421b6b521656 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -104,7 +105,6 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetAclResponse; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetFileStatusResponse; @@ -156,6 +156,8 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RecoverLeaseResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RecoverTrashRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RecoverTrashResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RemoveAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RemoveAclResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeysArgs; @@ -203,6 +205,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.protobuf.ByteString; +import org.apache.hadoop.util.ProtobufUtils; import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes; import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.TOKEN_ERROR_OTHER; @@ -1357,14 +1360,16 @@ public S3VolumeContext getS3VolumeContext() throws IOException { } @Override - public void refetchSecretKey() throws IOException { + public UUID refetchSecretKey() throws IOException { final RefetchSecretKeyRequest.Builder requestBuilder = RefetchSecretKeyRequest.newBuilder(); final OMRequest omRequest = createOMRequest(Type.RefetchSecretKey) .setRefetchSecretKeyRequest(requestBuilder) .build(); final OMResponse omResponse = submitRequest(omRequest); - handleError(omResponse); + final RefetchSecretKeyResponse resp = + handleError(omResponse).getRefetchSecretKeyResponse(); + return ProtobufUtils.fromProtobuf(resp.getId()); } /** diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java index 6dec05c258d1..c53ef2ea185b 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestBlockTokensCLI.java @@ -23,6 +23,7 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.scm.ScmConfig; import org.apache.hadoop.hdds.scm.server.SCMHTTPServerConfig; +import org.apache.hadoop.hdds.security.symmetric.SecretKeyManager; import org.apache.hadoop.hdds.utils.IOUtils; import org.apache.hadoop.minikdc.MiniKdc; import org.apache.hadoop.ozone.client.OzoneClient; @@ -65,7 +66,7 @@ import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY; import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; /** * Integration test class to verify block token CLI commands functionality in a @@ -89,6 +90,7 @@ public final class TestBlockTokensCLI { private static String clusterId; private static String scmId; private static String omServiceId; + private static String scmServiceId; private static MiniOzoneHAClusterImpl cluster; private static OzoneClient client; @@ -104,6 +106,7 @@ public static void init() throws Exception { clusterId = UUID.randomUUID().toString(); scmId = UUID.randomUUID().toString(); omServiceId = "om-service-test"; + scmServiceId = "scm-service-test"; startMiniKdc(); setSecureConfig(); @@ -124,6 +127,10 @@ public static void stop() { DefaultConfigManager.clearDefaultConfigs(); } + private SecretKeyManager getScmSecretKeyManager() { + return cluster.getActiveSCM().getSecretKeyManager(); + } + private static void setSecretKeysConfig() { // enable tokens conf.setBoolean(HDDS_BLOCK_TOKEN_ENABLED, true); @@ -195,7 +202,21 @@ public void testFetchKeyOMAdminCommand() throws UnsupportedEncodingException { String actualOutput = outputStream.toString("UTF-8"); System.setOut(System.out); - assertTrue(actualOutput.contains("Successfully re-fetched the secret key")); + String actualUUID = testFetchKeyOMAdminCommandUtil(actualOutput); + String expectedUUID = + getScmSecretKeyManager().getCurrentSecretKey().getId().toString(); + assertEquals(expectedUUID, actualUUID); + } + + private String testFetchKeyOMAdminCommandUtil(String output) { + // Extract the current secret key id from the output + String[] lines = output.split(System.lineSeparator()); + for (String line : lines) { + if (line.startsWith("Current Secret Key ID: ")) { + return line.substring("Current Secret Key ID: ".length()).trim(); + } + } + return null; } private static void startCluster() @@ -203,7 +224,7 @@ private static void startCluster() OzoneManager.setTestSecureOmFlag(true); MiniOzoneCluster.Builder builder = MiniOzoneCluster.newHABuilder(conf) .setClusterId(clusterId) - .setSCMServiceId("TestSecretKey") + .setSCMServiceId(scmServiceId) .setOMServiceId(omServiceId) .setScmId(scmId) .setNumDatanodes(3) diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index e0e11b4d8f3c..13febc8b1d22 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -597,7 +597,7 @@ message RefetchSecretKeyRequest { } message RefetchSecretKeyResponse { - + optional hdds.UUID id = 1; } /** diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index 70579e086142..4397ee04ef7a 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -46,6 +46,7 @@ import java.util.SortedSet; import java.util.Timer; import java.util.TimerTask; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -1064,8 +1065,9 @@ private void stopSecretManager() { } } - public void refetchSecretKey() { + public UUID refetchSecretKey() { secretKeyClient.refetchSecretKey(); + return secretKeyClient.getCurrentSecretKey().getId(); } @VisibleForTesting diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index 27efe5906171..25cb86a72ab7 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; import com.google.protobuf.ByteString; @@ -137,6 +138,7 @@ import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PartInfo; import org.apache.hadoop.ozone.upgrade.UpgradeFinalizer.StatusAndMessages; +import org.apache.hadoop.util.ProtobufUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -949,9 +951,10 @@ private RangerBGSyncResponse triggerRangerBGSync( } private RefetchSecretKeyResponse refetchSecretKey() { - impl.refetchSecretKey(); + UUID uuid = impl.refetchSecretKey(); RefetchSecretKeyResponse response = - RefetchSecretKeyResponse.newBuilder().build(); + RefetchSecretKeyResponse.newBuilder() + .setId(ProtobufUtils.toProtobuf(uuid)).build(); return response; } diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java index 8d5d8cc0e807..ba0220292cc1 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/FetchKeySubCommand.java @@ -17,6 +17,7 @@ package org.apache.hadoop.ozone.admin.om; +import java.util.UUID; import java.util.concurrent.Callable; import org.apache.hadoop.hdds.cli.HddsVersionProvider; import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; @@ -46,8 +47,8 @@ public class FetchKeySubCommand implements Callable { @Override public Void call() throws Exception { try (OzoneManagerProtocol client = parent.createOmClient(omServiceId)) { - client.refetchSecretKey(); - System.out.println("Successfully re-fetched the secret key."); + UUID uuid = client.refetchSecretKey(); + System.out.println("Current Secret Key ID: " + uuid); } return null; }