This is an automated email from the ASF dual-hosted git repository.

sammichen 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 3bf9b69921 HDDS-8593. Add RootCARotationPoller to CertClient (#5030)
3bf9b69921 is described below

commit 3bf9b699215ff604814fb626910f0baeafaaf989
Author: Galsza <[email protected]>
AuthorDate: Sun Jul 9 13:16:52 2023 +0200

    HDDS-8593. Add RootCARotationPoller to CertClient (#5030)
---
 .../hadoop/ozone/TestHddsSecureDatanodeInit.java   |  4 +-
 .../client/DefaultCertificateClient.java           | 55 +++++++++++++++++-----
 .../certificate/client/SCMCertificateClient.java   |  2 +-
 .../client/CertificateClientTestImpl.java          |  2 +-
 .../client/TestDefaultCertificateClient.java       |  2 +-
 .../main/compose/ozonesecure/root-ca-rotation.yaml |  1 +
 .../compose/ozonesecure/test-root-ca-rotation.sh   |  1 +
 7 files changed, 50 insertions(+), 17 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/TestHddsSecureDatanodeInit.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/TestHddsSecureDatanodeInit.java
index e9a6e59ff1..26abac2d95 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/TestHddsSecureDatanodeInit.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/TestHddsSecureDatanodeInit.java
@@ -327,7 +327,7 @@ public class TestHddsSecureDatanodeInit {
         client.getCertificate().getSerialNumber().toString()));
 
     // start monitor task to renew key and cert
-    client.startCertificateMonitor();
+    client.startCertificateRenewerService();
 
     // check after renew, client will have the new cert ID
     GenericTestUtils.waitFor(() -> {
@@ -402,7 +402,7 @@ public class TestHddsSecureDatanodeInit {
         client.getCertificate().getSerialNumber().toString()));
 
     // start monitor task to renew key and cert
-    client.startCertificateMonitor();
+    client.startCertificateRenewerService();
 
     // certificate failed to renew, client still hold the old expired cert.
     Thread.sleep(CERT_LIFETIME * 1000);
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 fb7587a838..a26bd12188 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
@@ -52,6 +52,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -127,6 +128,7 @@ public abstract class DefaultCertificateClient implements 
CertificateClient {
   private Runnable shutdownCallback;
   private SCMSecurityProtocolClientSideTranslatorPB scmSecurityClient;
   private final Set<CertificateNotification> notificationReceivers;
+  private RootCaRotationPoller rootCaRotationPoller;
 
   protected DefaultCertificateClient(
       SecurityConfig securityConfig,
@@ -169,19 +171,33 @@ public abstract class DefaultCertificateClient implements 
CertificateClient {
       return;
     }
 
-    if (shouldStartCertificateMonitor()) {
+    if (shouldStartCertificateRenewerService()) {
+      startRootCaRotationPoller();
       if (certPath != null && executorService == null) {
-        startCertificateMonitor();
+        startCertificateRenewerService();
       } else {
         if (executorService != null) {
-          getLogger().debug("CertificateLifetimeMonitor is already started.");
+          getLogger().debug("CertificateRenewerService is already started.");
         } else {
           getLogger().warn("Component certificate was not loaded.");
         }
       }
     } else {
-      getLogger().info("CertificateLifetimeMonitor is disabled for {}",
-          component);
+      getLogger().info("CertificateRenewerService and root ca rotation " +
+          "polling is disabled for {}", component);
+    }
+  }
+
+  private void startRootCaRotationPoller() {
+    if (rootCaRotationPoller == null) {
+      rootCaRotationPoller = new RootCaRotationPoller(securityConfig,
+          rootCaCertificates, scmSecurityClient);
+      rootCaRotationPoller.addRootCARotationProcessor(
+          this::getRootCaRotationListener);
+      rootCaRotationPoller.run();
+    } else {
+      getLogger().debug("Root CA certificate rotation poller is already " +
+          "started.");
     }
   }
 
@@ -985,6 +1001,10 @@ public abstract class DefaultCertificateClient implements 
CertificateClient {
       executorService = null;
     }
 
+    if (rootCaRotationPoller != null) {
+      rootCaRotationPoller.close();
+    }
+
     if (serverKeyStoresFactory != null) {
       serverKeyStoresFactory.destroy();
     }
@@ -1292,11 +1312,21 @@ public abstract class DefaultCertificateClient 
implements CertificateClient {
     return scmSecurityClient;
   }
 
-  protected boolean shouldStartCertificateMonitor() {
+  protected boolean shouldStartCertificateRenewerService() {
     return true;
   }
 
-  public synchronized void startCertificateMonitor() {
+  public synchronized CompletableFuture<Void> getRootCaRotationListener(
+      List<X509Certificate> rootCAs) {
+    if (rootCaCertificates.containsAll(rootCAs)) {
+      return CompletableFuture.completedFuture(null);
+    }
+    CertificateRenewerService renewerService =
+        new CertificateRenewerService(true);
+    return CompletableFuture.runAsync(renewerService, executorService);
+  }
+
+  public synchronized void startCertificateRenewerService() {
     Preconditions.checkNotNull(getCertificate(),
         "Component certificate should not be empty");
     // Schedule task to refresh certificate before it expires
@@ -1310,13 +1340,13 @@ public abstract class DefaultCertificateClient 
implements CertificateClient {
     if (executorService == null) {
       executorService = Executors.newScheduledThreadPool(1,
           new ThreadFactoryBuilder().setNameFormat(
-                  getComponentName() + "-CertificateLifetimeMonitor")
+                  getComponentName() + "-CertificateRenewerService")
               .setDaemon(true).build());
     }
     this.executorService.scheduleAtFixedRate(
         new CertificateRenewerService(false),
         timeBeforeGracePeriod, interval, TimeUnit.MILLISECONDS);
-    getLogger().info("CertificateLifetimeMonitor for {} is started with " +
+    getLogger().info("CertificateRenewerService for {} is started with " +
             "first delay {} ms and interval {} ms.", component,
         timeBeforeGracePeriod, interval);
   }
@@ -1349,10 +1379,11 @@ public abstract class DefaultCertificateClient 
implements CertificateClient {
         }
         String newCertId;
         try {
-          getLogger().info("Current certificate {} has entered the expiry" +
-                  " grace period {}. Starting renew key and certs.",
+          getLogger().info("Current certificate {} needs to be renewed " +
+                  "remaining grace period {}. Forced renewal due to root ca " +
+                  "rotation: {}.",
               currentCert.getSerialNumber().toString(),
-              timeLeft, securityConfig.getRenewalGracePeriod());
+              timeLeft, forceRenewal);
           newCertId = renewAndStoreKeyAndCertificate(forceRenewal);
         } catch (CertificateException e) {
           if (e.errorCode() ==
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 32a9326e46..262bb4b570 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
@@ -173,7 +173,7 @@ public class SCMCertificateClient extends 
DefaultCertificateClient {
   }
 
   @Override
-  protected boolean shouldStartCertificateMonitor() {
+  protected boolean shouldStartCertificateRenewerService() {
     return false;
   }
 
diff --git 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/CertificateClientTestImpl.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/CertificateClientTestImpl.java
index 57801a5c13..40395ac128 100644
--- 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/CertificateClientTestImpl.java
+++ 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/CertificateClientTestImpl.java
@@ -166,7 +166,7 @@ public class CertificateClientTestImpl implements 
CertificateClient {
           Duration.between(currentTime, gracePeriodStart);
 
       executorService = Executors.newScheduledThreadPool(1,
-          new 
ThreadFactoryBuilder().setNameFormat("CertificateLifetimeMonitor")
+          new ThreadFactoryBuilder().setNameFormat("CertificateRenewerService")
               .setDaemon(true).build());
       this.executorService.schedule(new RenewCertTask(),
           delay.toMillis(), TimeUnit.MILLISECONDS);
diff --git 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestDefaultCertificateClient.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestDefaultCertificateClient.java
index 1725a0b510..3bd352713a 100644
--- 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestDefaultCertificateClient.java
+++ 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestDefaultCertificateClient.java
@@ -656,7 +656,7 @@ public class TestDefaultCertificateClient {
     Thread.enumerate(threads);
     Predicate<Thread> monitorFilterPredicate =
         t -> t != null
-            && t.getName().equals(compName + "-CertificateLifetimeMonitor");
+            && t.getName().equals(compName + "-CertificateRenewerService");
     long monitorThreadCount = Arrays.stream(threads)
         .filter(monitorFilterPredicate)
         .count();
diff --git 
a/hadoop-ozone/dist/src/main/compose/ozonesecure/root-ca-rotation.yaml 
b/hadoop-ozone/dist/src/main/compose/ozonesecure/root-ca-rotation.yaml
index 8f7b944b0f..9dccb44945 100644
--- a/hadoop-ozone/dist/src/main/compose/ozonesecure/root-ca-rotation.yaml
+++ b/hadoop-ozone/dist/src/main/compose/ozonesecure/root-ca-rotation.yaml
@@ -25,6 +25,7 @@ x-root-cert-rotation-config:
     - OZONE-SITE.XML_hdds.x509.renew.grace.duration=PT45S
     - OZONE-SITE.XML_hdds.x509.ca.rotation.check.interval=PT1S
     - OZONE-SITE.XML_hdds.x509.ca.rotation.ack.timeout=PT20S
+    - OZONE-SITE.XML_hdds.x509.rootca.certificate.polling.interval=PT10s
     - OZONE-SITE.XML_hdds.block.token.expiry.time=15s
     - OZONE-SITE.XML_ozone.manager.delegation.token.max-lifetime=15s
     - OZONE-SITE.XML_ozone.manager.delegation.token.renew-interval=15s
diff --git 
a/hadoop-ozone/dist/src/main/compose/ozonesecure/test-root-ca-rotation.sh 
b/hadoop-ozone/dist/src/main/compose/ozonesecure/test-root-ca-rotation.sh
index 66f1a6d01a..9858d41eb8 100755
--- a/hadoop-ozone/dist/src/main/compose/ozonesecure/test-root-ca-rotation.sh
+++ b/hadoop-ozone/dist/src/main/compose/ozonesecure/test-root-ca-rotation.sh
@@ -40,6 +40,7 @@ wait_for_execute_command scm 30 "jps | grep 
StorageContainerManagerStarter |  se
 
 # wait and verify root CA is rotated
 wait_for_execute_command scm 180 "ozone admin cert info 2"
+wait_for_execute_command datanode 30 "find 
/data/metadata/dn/certs/ROOTCA-2.crt"
 
 # verify om operations and data operations
 execute_commands_in_container scm "ozone sh volume create /r-v1 && ozone sh 
bucket create /r-v1/r-b1"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to