This is an automated email from the ASF dual-hosted git repository.
pifta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new a6ed346744 HDDS-8590. Implement a protocol call to get the rootCA from
SCM (#4934)
a6ed346744 is described below
commit a6ed346744c69d19c1000cb0c3ad75d9dd4fe669
Author: Galsza <[email protected]>
AuthorDate: Wed Jun 21 23:20:42 2023 +0200
HDDS-8590. Implement a protocol call to get the rootCA from SCM (#4934)
---
.../hadoop/hdds/protocol/SCMSecurityProtocol.java | 11 +++++-
.../SCMSecurityProtocolClientSideTranslatorPB.java | 11 ++++++
.../src/main/proto/ScmServerSecurityProtocol.proto | 14 ++++++-
.../SCMSecurityProtocolServerSideTranslatorPB.java | 16 ++++++--
.../hdds/scm/server/SCMSecurityProtocolServer.java | 46 +++++++++++++++++-----
.../hdds/scm/server/StorageContainerManager.java | 19 ++++++---
.../scm/server/TestSCMSecurityProtocolServer.java | 38 +++++++++++++++++-
7 files changed, 132 insertions(+), 23 deletions(-)
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/SCMSecurityProtocol.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/SCMSecurityProtocol.java
index 2354a9b8d8..ed4906e3b7 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/SCMSecurityProtocol.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/SCMSecurityProtocol.java
@@ -164,11 +164,18 @@ public interface SCMSecurityProtocol {
* Get SCM signed certificate.
*
* @param nodeDetails - Node Details.
- * @param certSignReq - Certificate signing request.
+ * @param certSignReq - Certificate signing request.
* @return String - pem encoded SCM signed
- * certificate.
+ * certificate.
*/
String getCertificate(NodeDetailsProto nodeDetails,
String certSignReq) throws IOException;
+ /**
+ * Get all root CA certificates known to SCM.
+ *
+ * @return String - pem encoded list of root CA certificates
+ */
+ List<String> getAllRootCaCertificates() throws IOException;
+
}
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/SCMSecurityProtocolClientSideTranslatorPB.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/SCMSecurityProtocolClientSideTranslatorPB.java
index e3803c492a..32bdb2139a 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/SCMSecurityProtocolClientSideTranslatorPB.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/SCMSecurityProtocolClientSideTranslatorPB.java
@@ -32,6 +32,7 @@ import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeDetailsProto;
import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.OzoneManagerDetailsProto;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmNodeDetailsProto;
import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos;
+import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetAllRootCaCertificatesRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetSCMCertRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCACertificateRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
@@ -409,4 +410,14 @@ public class SCMSecurityProtocolClientSideTranslatorPB
implements
public Object getUnderlyingProxyObject() {
return rpcProxy;
}
+
+ @Override
+ public List<String> getAllRootCaCertificates() throws IOException {
+ SCMGetAllRootCaCertificatesRequestProto protoIns =
+ SCMGetAllRootCaCertificatesRequestProto.getDefaultInstance();
+ return submitRequest(Type.GetAllRootCaCertificates,
+ builder -> builder.setGetAllRootCaCertificatesRequestProto(protoIns))
+ .getAllRootCaCertificatesResponseProto()
+ .getAllX509RootCaCertificatesList();
+ }
}
diff --git
a/hadoop-hdds/interface-server/src/main/proto/ScmServerSecurityProtocol.proto
b/hadoop-hdds/interface-server/src/main/proto/ScmServerSecurityProtocol.proto
index 1768444e07..85ae39379f 100644
---
a/hadoop-hdds/interface-server/src/main/proto/ScmServerSecurityProtocol.proto
+++
b/hadoop-hdds/interface-server/src/main/proto/ScmServerSecurityProtocol.proto
@@ -56,6 +56,8 @@ message SCMSecurityRequest {
optional SCMGetLatestCrlIdRequestProto getLatestCrlIdRequest = 11;
optional SCMRevokeCertificatesRequestProto revokeCertificatesRequest = 12;
optional SCMGetCertRequestProto getCertRequest = 13;
+ optional SCMGetAllRootCaCertificatesRequestProto
+ getAllRootCaCertificatesRequestProto = 14;
}
message SCMSecurityResponse {
@@ -80,6 +82,8 @@ message SCMSecurityResponse {
optional SCMGetLatestCrlIdResponseProto getLatestCrlIdResponseProto = 9;
optional SCMRevokeCertificatesResponseProto
revokeCertificatesResponseProto = 10;
+
+ optional SCMGetAllRootCaCertificatesResponseProto
allRootCaCertificatesResponseProto = 11;
}
enum Type {
@@ -95,6 +99,7 @@ enum Type {
GetLatestCrlId = 10;
RevokeCertificates = 11;
GetCert = 12;
+ GetAllRootCaCertificates = 13;
}
enum Status {
@@ -195,6 +200,10 @@ message SCMListCertificateResponseProto {
repeated string certificates = 2;
}
+message SCMGetAllRootCaCertificatesResponseProto {
+ repeated string allX509RootCaCertificates = 1;
+}
+
message SCMGetRootCACertificateRequestProto {
}
@@ -241,10 +250,13 @@ message SCMRevokeCertificatesRequestProto {
optional uint64 revokeTime = 3;
}
+message SCMGetAllRootCaCertificatesRequestProto {
+}
+
message SCMRevokeCertificatesResponseProto {
optional int64 crlId = 1;
}
service SCMSecurityProtocolService {
rpc submitRequest (SCMSecurityRequest) returns (SCMSecurityResponse);
-}
\ No newline at end of file
+}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/SCMSecurityProtocolServerSideTranslatorPB.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/SCMSecurityProtocolServerSideTranslatorPB.java
index 736aef15a0..d65eacc84c 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/SCMSecurityProtocolServerSideTranslatorPB.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/SCMSecurityProtocolServerSideTranslatorPB.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.apache.hadoop.hdds.protocol.SCMSecurityProtocol;
import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos;
+import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetAllRootCaCertificatesResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto.ResponseCode;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertificateRequestProto;
@@ -53,8 +54,6 @@ import com.google.protobuf.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.Type.GetSCMCertificate;
-
/**
* This class is the server-side translator that forwards requests received on
* {@link SCMSecurityProtocolPB} to the {@link
@@ -148,7 +147,11 @@ public class SCMSecurityProtocolServerSideTranslatorPB
.build();
case GetCert:
return scmSecurityResponse.setGetCertResponseProto(
- getCertificate(request.getGetCertRequest()))
+ getCertificate(request.getGetCertRequest()))
+ .build();
+ case GetAllRootCaCertificates:
+ return scmSecurityResponse
+ .setAllRootCaCertificatesResponseProto(getAllRootCa())
.build();
default:
@@ -397,6 +400,13 @@ public class SCMSecurityProtocolServerSideTranslatorPB
".scm.ratis.enable config");
}
+ public SCMGetAllRootCaCertificatesResponseProto getAllRootCa()
+ throws IOException {
+ return SCMGetAllRootCaCertificatesResponseProto.newBuilder()
+ .addAllAllX509RootCaCertificates(impl.getAllRootCaCertificates())
+ .build();
+ }
+
private void setRootCAIfNeeded(SCMGetCertResponseProto.Builder builder)
throws IOException {
if (scm.getScmStorageConfig().checkPrimarySCMIdInitialized()) {
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java
index c8183ed0cb..c576875603 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java
@@ -87,6 +87,7 @@ import static
org.apache.hadoop.hdds.security.exception.SCMSecurityException.Err
import static
org.apache.hadoop.hdds.security.exception.SCMSecurityException.ErrorCode.GET_CA_CERT_FAILED;
import static
org.apache.hadoop.hdds.security.exception.SCMSecurityException.ErrorCode.GET_CERTIFICATE_FAILED;
import static
org.apache.hadoop.hdds.security.x509.certificate.authority.CertificateApprover.ApprovalType.KERBEROS_TRUSTED;
+import static
org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec.getPEMEncodedString;
/**
* The protocol used to perform security related operations with SCM.
@@ -101,7 +102,7 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
.getLogger(SCMSecurityProtocolServer.class);
private final CertificateServer rootCertificateServer;
private final CertificateServer scmCertificateServer;
- private final X509Certificate rootCACertificate;
+ private final List<X509Certificate> rootCACertificateList;
private final RPC.Server rpcServer; // HADOOP RPC SERVER
private final SCMUpdateServiceGrpcServer grpcUpdateServer; // gRPC SERVER
private final InetSocketAddress rpcAddress;
@@ -116,13 +117,13 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
SCMSecurityProtocolServer(OzoneConfiguration conf,
CertificateServer rootCertificateServer,
CertificateServer scmCertificateServer,
- X509Certificate rootCACert, StorageContainerManager scm,
+ List<X509Certificate> rootCACertList, StorageContainerManager scm,
@Nullable SecretKeyManager secretKeyManager)
throws IOException {
this.storageContainerManager = scm;
this.rootCertificateServer = rootCertificateServer;
this.scmCertificateServer = scmCertificateServer;
- this.rootCACertificate = rootCACert;
+ this.rootCACertificateList = rootCACertList;
this.secretKeyManager = secretKeyManager;
final int handlerCount =
conf.getInt(ScmConfigKeys.OZONE_SCM_SECURITY_HANDLER_COUNT_KEY,
@@ -232,6 +233,17 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
}
}
+ @Override
+ public synchronized List<String> getAllRootCaCertificates()
+ throws IOException {
+ List<String> pemEncodedList =
+ new ArrayList<>(rootCACertificateList.size());
+ for (X509Certificate cert : rootCACertificateList) {
+ pemEncodedList.add(getPEMEncodedString(cert));
+ }
+ return pemEncodedList;
+ }
+
/**
* Get SCM signed certificate for OM.
*
@@ -292,7 +304,7 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
KERBEROS_TRUSTED, nodeType);
}
try {
- return CertificateCodec.getPEMEncodedString(future.get());
+ return getPEMEncodedString(future.get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw generateException(e, nodeType);
@@ -339,7 +351,7 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
X509Certificate certificate =
scmCertificateServer.getCertificate(certSerialId);
if (certificate != null) {
- return CertificateCodec.getPEMEncodedString(certificate);
+ return getPEMEncodedString(certificate);
}
} catch (CertificateException e) {
throw new SCMSecurityException("getCertificate operation failed. ", e,
@@ -359,7 +371,7 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
public String getCACertificate() throws IOException {
LOGGER.debug("Getting CA certificate.");
try {
- return CertificateCodec.getPEMEncodedString(
+ return getPEMEncodedString(
scmCertificateServer.getCaCertPath());
} catch (CertificateException e) {
throw new SCMSecurityException("getRootCertificate operation failed. ",
@@ -385,7 +397,7 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
List<String> results = new ArrayList<>(certificates.size());
for (X509Certificate cert : certificates) {
try {
- String certStr = CertificateCodec.getPEMEncodedString(cert);
+ String certStr = getPEMEncodedString(cert);
results.add(certStr);
} catch (SCMSecurityException e) {
throw new SCMSecurityException("listCertificate operation failed.",
@@ -403,13 +415,27 @@ public class SCMSecurityProtocolServer implements
SCMSecurityProtocol,
}
@Override
- public String getRootCACertificate() throws IOException {
+ public synchronized String getRootCACertificate() throws IOException {
LOGGER.debug("Getting Root CA certificate.");
+ X509Certificate lastExpiringRootCa = null;
if (storageContainerManager.getScmStorageConfig()
.checkPrimarySCMIdInitialized()) {
- return CertificateCodec.getPEMEncodedString(rootCACertificate);
+ Date lastCertDate = new Date(0);
+ for (X509Certificate cert : rootCACertificateList) {
+ if (cert.getNotAfter().after(lastCertDate)) {
+ lastCertDate = cert.getNotAfter();
+ lastExpiringRootCa = cert;
+ }
+ }
+ }
+ if (lastExpiringRootCa == null) {
+ return null;
}
- return null;
+ return CertificateCodec.getPEMEncodedString(lastExpiringRootCa);
+ }
+
+ public synchronized void addNewRootCa(X509Certificate rootCaCertToAdd) {
+ rootCACertificateList.add(rootCaCertToAdd);
}
@Override
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
index fac7f0711c..2a791171a7 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
@@ -27,6 +27,7 @@ import com.google.protobuf.BlockingService;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
+
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdds.HddsConfigKeys;
@@ -882,14 +883,22 @@ public final class StorageContainerManager extends
ServiceRuntimeInfoImpl
SecretKeyManager secretKeyManager = secretKeyManagerService != null ?
secretKeyManagerService.getSecretKeyManager() : null;
+ X509Certificate rootCaCert = scmCertificateClient == null ? null :
+ scmCertificateClient.getRootCACertificate() != null ?
+ scmCertificateClient.getRootCACertificate() :
+ scmCertificateClient.getCACertificate();
+ List<X509Certificate> rootCaList = new ArrayList<>();
+ if (rootCaCert != null) {
+ rootCaList.add(rootCaCert);
+ }
// We need to pass getCACertificate as rootCA certificate,
// as for SCM CA is root-CA.
securityProtocolServer = new SCMSecurityProtocolServer(conf,
- rootCertificateServer, scmCertificateServer,
- scmCertificateClient == null ? null :
- scmCertificateClient.getRootCACertificate() != null ?
- scmCertificateClient.getRootCACertificate() :
- scmCertificateClient.getCACertificate(), this, secretKeyManager);
+ rootCertificateServer,
+ scmCertificateServer,
+ rootCaList,
+ this,
+ secretKeyManager);
if (securityConfig.isContainerTokenEnabled()) {
containerTokenMgr = createContainerTokenSecretManager(configuration);
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMSecurityProtocolServer.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMSecurityProtocolServer.java
index 82f2cc182a..7803025d9d 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMSecurityProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMSecurityProtocolServer.java
@@ -20,28 +20,42 @@ import static
org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_SECURITY_SERVIC
import static
org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_SECURITY_SERVICE_BIND_HOST_DEFAULT;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
+import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import java.io.IOException;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
/**
* Test class for {@link SCMSecurityProtocolServer}.
- * */
+ */
@Timeout(20)
public class TestSCMSecurityProtocolServer {
private SCMSecurityProtocolServer securityProtocolServer;
private OzoneConfiguration config;
+ @Mock
+ private StorageContainerManager mockScm;
+ @Mock
+ private SCMStorageConfig storageConfigMock;
@BeforeEach
public void setUp() throws Exception {
+ MockitoAnnotations.openMocks(this);
config = new OzoneConfiguration();
config.set(OZONE_SCM_SECURITY_SERVICE_ADDRESS_KEY,
OZONE_SCM_SECURITY_SERVICE_BIND_HOST_DEFAULT + ":0");
securityProtocolServer = new SCMSecurityProtocolServer(config, null,
- null, null, null, null);
+ null, new ArrayList<>(), mockScm, null);
}
@AfterEach
@@ -62,4 +76,24 @@ public class TestSCMSecurityProtocolServer {
public void testStop() {
securityProtocolServer.stop();
}
+
+ @Test
+ public void testReturnLastRootCa() throws Exception {
+ KeyPair keyPair = KeyStoreTestUtil.generateKeyPair("RSA");
+ X509Certificate oldRootCa = KeyStoreTestUtil.generateCertificate("CN=dn",
+ keyPair, 15, "SHA256withRSA");
+ X509Certificate latestRootCa =
KeyStoreTestUtil.generateCertificate("CN=dn",
+ keyPair, 30, "SHA256withRSA");
+ Assertions.assertTrue(oldRootCa.getNotAfter().toInstant()
+ .isBefore(latestRootCa.getNotAfter().toInstant()));
+ securityProtocolServer.addNewRootCa(oldRootCa);
+ securityProtocolServer.addNewRootCa(latestRootCa);
+ String pemEncodedLatestRootCa =
+ CertificateCodec.getPEMEncodedString(latestRootCa);
+ Mockito.when(mockScm.getScmStorageConfig()).thenReturn(storageConfigMock);
+ Mockito.when(
+ storageConfigMock.checkPrimarySCMIdInitialized()).thenReturn(true);
+ Assertions.assertEquals(securityProtocolServer.getRootCACertificate(),
+ pemEncodedLatestRootCa);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]