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 61df5bf9e8 HDDS-9013. Fetch root CA certificate list during SCM
startup. (#5150)
61df5bf9e8 is described below
commit 61df5bf9e8ea72ee68fedca411c66c603c4c6601
Author: Sammi Chen <[email protected]>
AuthorDate: Wed Aug 9 21:28:59 2023 +0800
HDDS-9013. Fetch root CA certificate list during SCM startup. (#5150)
---
.../client/DefaultCertificateClient.java | 25 ++++++--
.../certificate/client/SCMCertificateClient.java | 74 +++++++++++++++++++++-
.../hdds/scm/server/StorageContainerManager.java | 18 +++---
3 files changed, 101 insertions(+), 16 deletions(-)
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/DefaultCertificateClient.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/DefaultCertificateClient.java
index a6583fc014..8cf5e9d50b 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/DefaultCertificateClient.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/DefaultCertificateClient.java
@@ -616,10 +616,15 @@ public abstract class DefaultCertificateClient implements
CertificateClient {
}
}
- codec.writeCertificate(certName,
- pemEncodedCert);
+ codec.writeCertificate(certName, pemEncodedCert);
if (addToCertMap) {
certificateMap.put(cert.getSerialNumber().toString(), certificatePath);
+ if (caType == CAType.SUBORDINATE) {
+ caCertificates.add(cert);
+ }
+ if (caType == CAType.ROOT) {
+ rootCaCertificates.add(cert);
+ }
}
} catch (IOException | java.security.cert.CertificateException e) {
throw new CertificateException("Error while storing certificate.", e,
@@ -975,6 +980,18 @@ public abstract class DefaultCertificateClient implements
CertificateClient {
}
}
+ /**
+ * Notify all certificate renewal receivers that the certificate is renewed.
+ *
+ */
+ protected void notifyNotificationReceivers(String oldCaCertId,
+ String newCaCertId) {
+ synchronized (notificationReceivers) {
+ notificationReceivers.forEach(r -> r.notifyCertificateRenewed(
+ this, oldCaCertId, newCaCertId));
+ }
+ }
+
@Override
public synchronized void close() throws IOException {
if (executorService != null) {
@@ -1215,9 +1232,7 @@ public abstract class DefaultCertificateClient implements
CertificateClient {
getLogger().info("Reset and reloaded key and all certificates for new " +
"certificate {}.", newCertId);
- // notify notification receivers
- notificationReceivers.forEach(r -> r.notifyCertificateRenewed(
- this, oldCaCertId, newCertId));
+ notifyNotificationReceivers(oldCaCertId, newCertId);
}
public SecurityConfig getSecurityConfig() {
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/SCMCertificateClient.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/SCMCertificateClient.java
index 15e6614cd0..357001b44b 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/SCMCertificateClient.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/SCMCertificateClient.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.hdds.security.x509.certificate.client;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import
org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import
org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
import org.apache.hadoop.hdds.security.SecurityConfig;
@@ -27,14 +28,20 @@ import
org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
import
org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateSignRequest;
import org.apache.hadoop.hdds.security.x509.exception.CertificateException;
import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.OzoneSecurityUtil;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import static
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient.InitResponse.FAILURE;
import static
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient.InitResponse.GETCERT;
@@ -59,7 +66,7 @@ public class SCMCertificateClient extends
DefaultCertificateClient {
private String scmId;
private String cId;
private String scmHostname;
- private SCMSecurityProtocolClientSideTranslatorPB scmSecurityClient;
+ private ExecutorService executorService;
public SCMCertificateClient(SecurityConfig securityConfig,
SCMSecurityProtocolClientSideTranslatorPB scmClient,
@@ -228,4 +235,69 @@ public class SCMCertificateClient extends
DefaultCertificateClient {
throw new RuntimeException(e);
}
}
+
+ public void refreshCACertificates() throws IOException {
+ if (executorService == null) {
+ executorService = Executors.newSingleThreadExecutor(
+ new ThreadFactoryBuilder().setNameFormat(
+ getComponentName() + "-refreshCACertificates")
+ .setDaemon(true).build());
+ }
+ executorService.execute(new RefreshCACertificates(getScmSecureClient()));
+ }
+
+ /**
+ * Task to refresh root CA certificates for SCM.
+ */
+ public class RefreshCACertificates implements Runnable {
+ private final SCMSecurityProtocolClientSideTranslatorPB scmSecureClient;
+
+ public RefreshCACertificates(
+ SCMSecurityProtocolClientSideTranslatorPB client) {
+ this.scmSecureClient = client;
+ }
+
+ @Override
+ public void run() {
+ try {
+ // In case root CA certificate is rotated during this SCM is offline
+ // period, fetch the new root CA list from leader SCM and refresh ratis
+ // server's tlsConfig.
+ List<String> rootCAPems = scmSecureClient.getAllRootCaCertificates();
+
+ // SCM certificate client currently sets root CA as CA cert
+ Set<X509Certificate> certList = getAllRootCaCerts();
+ certList = certList.isEmpty() ? getAllCaCerts() : certList;
+
+ List<X509Certificate> rootCAsFromLeaderSCM =
+ OzoneSecurityUtil.convertToX509(rootCAPems);
+ rootCAsFromLeaderSCM.removeAll(certList);
+
+ if (rootCAsFromLeaderSCM.isEmpty()) {
+ LOG.info("CA certificates are not changed.");
+ return;
+ }
+
+ for (X509Certificate cert : rootCAsFromLeaderSCM) {
+ LOG.info("Fetched new root CA certificate {} from leader SCM",
+ cert.getSerialNumber().toString());
+ storeCertificate(
+ CertificateCodec.getPEMEncodedString(cert), CAType.SUBORDINATE);
+ }
+ String scmCertId = getCertificate().getSerialNumber().toString();
+ notifyNotificationReceivers(scmCertId, scmCertId);
+ } catch (IOException e) {
+ LOG.error("Failed to refresh CA certificates", e);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ super.close();
+ if (executorService != null) {
+ executorService.shutdownNow();
+ executorService = null;
+ }
+ }
}
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 3cb4fa8754..9f12993853 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
@@ -280,7 +280,7 @@ public final class StorageContainerManager extends
ServiceRuntimeInfoImpl
private ReplicationManager replicationManager;
private SCMSafeModeManager scmSafeModeManager;
- private CertificateClient scmCertificateClient;
+ private SCMCertificateClient scmCertificateClient;
private RootCARotationManager rootCARotationManager;
private ContainerTokenSecretManager containerTokenMgr;
@@ -956,15 +956,6 @@ public final class StorageContainerManager extends
ServiceRuntimeInfoImpl
return scmCertificateClient;
}
- @VisibleForTesting
- public void setScmCertificateClient(CertificateClient client)
- throws IOException {
- if (scmCertificateClient != null) {
- scmCertificateClient.close();
- }
- scmCertificateClient = client;
- }
-
public Clock getSystemClock() {
return systemClock;
}
@@ -1543,6 +1534,13 @@ public final class StorageContainerManager extends
ServiceRuntimeInfoImpl
// At this point leader is not known
scmHAMetricsUpdate(null);
+
+ if (scmCertificateClient != null) {
+ // In case root CA certificate is rotated during this SCM is offline
+ // period, fetch the new root CA list from leader SCM and refresh ratis
+ // server's tlsConfig.
+ scmCertificateClient.refreshCACertificates();
+ }
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]