From ce518c3fff90e22f6c015e480d68473c9cf2b34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20G=C3=A1l?= Date: Wed, 5 Jul 2023 15:18:37 +0200 Subject: [PATCH 1/6] HDDS-8591 Create root ca rotation poller --- .../apache/hadoop/hdds/HddsConfigKeys.java | 4 + .../hadoop/hdds/security/SecurityConfig.java | 14 ++ .../src/main/resources/ozone-default.xml | 11 ++ .../client/RootCaRotationPoller.java | 144 ++++++++++++++++++ .../utils/TestRootCaRotationPoller.java | 130 ++++++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java create mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java index ac6c08867be3..b58ab6996fdf 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java @@ -222,6 +222,10 @@ public final class HddsConfigKeys { "hdds.x509.ca.rotation.ack.timeout"; public static final String HDDS_X509_CA_ROTATION_ACK_TIMEOUT_DEFAULT = "PT15M"; + public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY = + "hdds.x509.rootca.client.polling.frequency"; + public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT + = "PT2h"; public static final String HDDS_CONTAINER_REPLICATION_COMPRESSION = "hdds.container.replication.compression"; diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java index f3e747de63b7..b297f607e4c5 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java @@ -52,6 +52,8 @@ import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_CA_ROTATION_TIME_OF_DAY_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE_DEFAULT; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PUBLIC_KEY_FILE; @@ -131,6 +133,7 @@ public class SecurityConfig { Pattern.compile("\\d{2}:\\d{2}:\\d{2}"); private final Duration caAckTimeout; private final SslProvider grpcSSLProvider; + private final Duration rootCaClientPollingFrequency; /** * Constructs a SecurityConfig. @@ -228,6 +231,13 @@ public SecurityConfig(ConfigurationSource configuration) { validateCertificateValidityConfig(); + String rootCaClientPollingFrequencyString = configuration.get( + HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY, + HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT); + + this.rootCaClientPollingFrequency = + Duration.parse(rootCaClientPollingFrequencyString); + this.externalRootCaCert = configuration.get( HDDS_X509_ROOTCA_CERTIFICATE_FILE, HDDS_X509_ROOTCA_CERTIFICATE_FILE_DEFAULT); @@ -552,6 +562,10 @@ public Duration getCaAckTimeout() { return caAckTimeout; } + public Duration getRootCaClientPollingFrequency() { + return rootCaClientPollingFrequency; + } + /** * Return true if using test certificates with authority as localhost. This * should be used only for unit test where certificates are generated by diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml index 484e5bfd3cd0..6f7b3c55fbce 100644 --- a/hadoop-hdds/common/src/main/resources/ozone-default.xml +++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml @@ -2268,6 +2268,17 @@ is failed. Default is 15 minutes. + + hdds.x509.rootca.client.polling.frequency + PT2h + Frequency to use for polling in certificate clients for a new + root ca certificate. Every time the specified time duration elapses, + the clients send a request to the SCMs to see if a new root ca + certificate was generated. Once there is a change, the system + automatically adds the new root ca to the clients' + trust stores and requests a new certificate to be signed. + + ozone.scm.security.handler.count.key 2 diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java new file mode 100644 index 000000000000..a49cfb0da7d2 --- /dev/null +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java @@ -0,0 +1,144 @@ +/* + * 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.hdds.security.x509.certificate.client; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB; +import org.apache.hadoop.hdds.security.SecurityConfig; +import org.apache.hadoop.ozone.OzoneSecurityUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Poller mechanism for Root Ca Rotation for clients. + */ +public class RootCaRotationPoller implements Runnable, Closeable { + + private static final Logger LOG = + LoggerFactory.getLogger(RootCaRotationPoller.class); + private final List, CompletableFuture>> + rootCARotationProcessors; + private final ScheduledExecutorService poller; + private final Duration pollingRate; + private Set knownRootCerts; + private final SCMSecurityProtocolClientSideTranslatorPB scmSecureClient; + + public RootCaRotationPoller(SecurityConfig securityConfig, + Set initiallyKnownRootCaCerts, + SCMSecurityProtocolClientSideTranslatorPB scmSecureClient) { + this.scmSecureClient = scmSecureClient; + this.knownRootCerts = initiallyKnownRootCaCerts; + poller = Executors.newScheduledThreadPool(1, + new ThreadFactoryBuilder().setNameFormat( + "RootCaRotationPoller") + .setDaemon(true).build()); + pollingRate = securityConfig.getRootCaClientPollingFrequency(); + rootCARotationProcessors = new ArrayList<>(); + } + + private void pollRootCas() { + try { + List pemEncodedRootCaList = + scmSecureClient.getAllRootCaCertificates(); + List rootCAsFromSCM = + OzoneSecurityUtil.convertToX509(pemEncodedRootCaList); + List scmCertsWithoutKnownCerts + = new ArrayList<>(rootCAsFromSCM); + scmCertsWithoutKnownCerts.removeAll(knownRootCerts); + if (scmCertsWithoutKnownCerts.isEmpty()) { + return; + } + LOG.info("Some root CAs are not known to the client out of the root " + + "CAs known to the SCMs. Root CA Cert ids known to the client: " + + getPrintableCertIds(knownRootCerts) + ". Root CA Cert ids from " + + "SCM not known by the client: " + + getPrintableCertIds(scmCertsWithoutKnownCerts)); + + CompletableFuture allRootCAProcessorFutures = + CompletableFuture.allOf(rootCARotationProcessors.stream() + .map(c -> c.apply(rootCAsFromSCM)) + .toArray(CompletableFuture[]::new)); + + allRootCAProcessorFutures.whenComplete((unused, throwable) -> { + if (throwable == null) { + knownRootCerts = new HashSet<>(rootCAsFromSCM); + } + }); + } catch (IOException e) { + LOG.error("Error while trying to rotate root ca certificate", e); + } + } + + public void addRootCARotationProcessor( + Function, CompletableFuture> processor) { + rootCARotationProcessors.add(processor); + } + + @Override + public void run() { + poller.scheduleAtFixedRate(this::pollRootCas, 0, + pollingRate.getSeconds(), TimeUnit.SECONDS); + } + + @Override + public void close() { + executorServiceShutdownGraceful(poller); + } + + private void executorServiceShutdownGraceful(ExecutorService executor) { + executor.shutdown(); + try { + if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { + executor.shutdownNow(); + } + if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { + LOG.error("Unable to shutdown root ca certificate rotation poller."); + } + } catch (InterruptedException e) { + LOG.error("Error attempting to shutdown.", e); + executor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + private String getPrintableCertIds(Collection certs) { + return StringUtils.join(certs.stream() + .map(X509Certificate::getSerialNumber) + .map(BigInteger::toString) + .collect(Collectors.toList()), ", "); + } +} diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java new file mode 100644 index 000000000000..e102310b3f00 --- /dev/null +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java @@ -0,0 +1,130 @@ +/* + * 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.hdds.security.x509.certificate.utils; + +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB; +import org.apache.hadoop.hdds.security.SecurityConfig; +import org.apache.hadoop.hdds.security.x509.certificate.client.RootCaRotationPoller; +import org.apache.hadoop.security.ssl.KeyStoreTestUtil; +import org.apache.ozone.test.GenericTestUtils; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.security.KeyPair; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY; + +/** + * Test for Root Ca Rotation polling mechanism on client side. + */ +public class TestRootCaRotationPoller { + + private SecurityConfig secConf; + + @Mock + private SCMSecurityProtocolClientSideTranslatorPB scmSecurityClient; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + OzoneConfiguration conf = new OzoneConfiguration(); + conf.set(HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY, "PT1s"); + secConf = new SecurityConfig(conf); + } + + @Test + public void testPollerDoesNotInvokeRootCaProcessor() throws Exception { + X509Certificate knownCert = generateX509Cert( + LocalDateTime.now(), Duration.ofSeconds(50)); + HashSet knownCerts = new HashSet<>(); + knownCerts.add(knownCert); + List certsFromScm = new ArrayList<>(); + certsFromScm.add(CertificateCodec.getPEMEncodedString(knownCert)); + RootCaRotationPoller poller = new RootCaRotationPoller(secConf, + knownCerts, scmSecurityClient); + + Mockito.when(scmSecurityClient.getAllRootCaCertificates()) + .thenReturn(certsFromScm); + AtomicBoolean atomicBoolean = new AtomicBoolean(); + atomicBoolean.set(false); + poller.addRootCARotationProcessor( + certificates -> CompletableFuture.supplyAsync(() -> { + atomicBoolean.set(true); + Assertions.assertEquals(certificates.size(), 2); + return null; + })); + poller.run(); + Assertions.assertThrows(TimeoutException.class, () -> + GenericTestUtils.waitFor(atomicBoolean::get, 50, 5000)); + } + + @Test + public void testPollerInvokesRootCaProcessors() throws Exception { + X509Certificate knownCert = generateX509Cert( + LocalDateTime.now(), Duration.ofSeconds(50)); + X509Certificate newRootCa = generateX509Cert( + LocalDateTime.now(), Duration.ofSeconds(50)); + HashSet knownCerts = new HashSet<>(); + knownCerts.add(knownCert); + List certsFromScm = new ArrayList<>(); + certsFromScm.add(CertificateCodec.getPEMEncodedString(knownCert)); + certsFromScm.add(CertificateCodec.getPEMEncodedString(newRootCa)); + RootCaRotationPoller poller = new RootCaRotationPoller(secConf, + knownCerts, scmSecurityClient); + poller.run(); + Mockito.when(scmSecurityClient.getAllRootCaCertificates()) + .thenReturn(certsFromScm); + AtomicBoolean atomicBoolean = new AtomicBoolean(); + atomicBoolean.set(false); + poller.addRootCARotationProcessor( + certificates -> CompletableFuture.supplyAsync(() -> { + atomicBoolean.set(true); + Assertions.assertEquals(certificates.size(), 2); + return null; + })); + GenericTestUtils.waitFor(atomicBoolean::get, 50, 5000); + } + + private X509Certificate generateX509Cert( + LocalDateTime startDate, Duration certLifetime) throws Exception { + KeyPair keyPair = KeyStoreTestUtil.generateKeyPair("RSA"); + LocalDateTime start = startDate == null ? LocalDateTime.now() : startDate; + LocalDateTime end = start.plus(certLifetime); + return new JcaX509CertificateConverter().getCertificate( + SelfSignedCertificate.newBuilder().setBeginDate(start) + .setEndDate(end).setClusterID("cluster").setKey(keyPair) + .setSubject("localhost").setConfiguration(secConf).setScmID("test") + .build()); + } +} From a89ce735415b545b259efbc7cf05dbfb01eb4b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20G=C3=A1l?= Date: Wed, 5 Jul 2023 15:27:04 +0200 Subject: [PATCH 2/6] HDDS-8591 Replace the phrase interval instead of frequency --- .../java/org/apache/hadoop/hdds/HddsConfigKeys.java | 6 +++--- .../apache/hadoop/hdds/security/SecurityConfig.java | 10 +++++----- .../common/src/main/resources/ozone-default.xml | 4 ++-- .../x509/certificate/client/RootCaRotationPoller.java | 6 +++--- .../certificate/utils/TestRootCaRotationPoller.java | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java index b58ab6996fdf..ba3df6447a5d 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java @@ -222,9 +222,9 @@ public final class HddsConfigKeys { "hdds.x509.ca.rotation.ack.timeout"; public static final String HDDS_X509_CA_ROTATION_ACK_TIMEOUT_DEFAULT = "PT15M"; - public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY = - "hdds.x509.rootca.client.polling.frequency"; - public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT + public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL = + "hdds.x509.rootca.client.polling.interval"; + public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT = "PT2h"; public static final String HDDS_CONTAINER_REPLICATION_COMPRESSION = diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java index b297f607e4c5..fcea09580423 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java @@ -52,8 +52,8 @@ import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_CA_ROTATION_TIME_OF_DAY_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE_DEFAULT; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PUBLIC_KEY_FILE; @@ -232,8 +232,8 @@ public SecurityConfig(ConfigurationSource configuration) { validateCertificateValidityConfig(); String rootCaClientPollingFrequencyString = configuration.get( - HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY, - HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY_DEFAULT); + HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL, + HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT); this.rootCaClientPollingFrequency = Duration.parse(rootCaClientPollingFrequencyString); @@ -562,7 +562,7 @@ public Duration getCaAckTimeout() { return caAckTimeout; } - public Duration getRootCaClientPollingFrequency() { + public Duration getRootCaClientPollingInterval() { return rootCaClientPollingFrequency; } diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml index 6f7b3c55fbce..c610622156c8 100644 --- a/hadoop-hdds/common/src/main/resources/ozone-default.xml +++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml @@ -2269,9 +2269,9 @@ - hdds.x509.rootca.client.polling.frequency + hdds.x509.rootca.client.polling.interval PT2h - Frequency to use for polling in certificate clients for a new + Interval to use for polling in certificate clients for a new root ca certificate. Every time the specified time duration elapses, the clients send a request to the SCMs to see if a new root ca certificate was generated. Once there is a change, the system diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java index a49cfb0da7d2..690d6085a4a4 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java @@ -53,7 +53,7 @@ public class RootCaRotationPoller implements Runnable, Closeable { private final List, CompletableFuture>> rootCARotationProcessors; private final ScheduledExecutorService poller; - private final Duration pollingRate; + private final Duration pollingInterval; private Set knownRootCerts; private final SCMSecurityProtocolClientSideTranslatorPB scmSecureClient; @@ -66,7 +66,7 @@ public RootCaRotationPoller(SecurityConfig securityConfig, new ThreadFactoryBuilder().setNameFormat( "RootCaRotationPoller") .setDaemon(true).build()); - pollingRate = securityConfig.getRootCaClientPollingFrequency(); + pollingInterval = securityConfig.getRootCaClientPollingInterval(); rootCARotationProcessors = new ArrayList<>(); } @@ -111,7 +111,7 @@ public void addRootCARotationProcessor( @Override public void run() { poller.scheduleAtFixedRate(this::pollRootCas, 0, - pollingRate.getSeconds(), TimeUnit.SECONDS); + pollingInterval.getSeconds(), TimeUnit.SECONDS); } @Override diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java index e102310b3f00..41f97d7bf1f7 100644 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java @@ -43,7 +43,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL; /** * Test for Root Ca Rotation polling mechanism on client side. @@ -59,7 +59,7 @@ public class TestRootCaRotationPoller { public void setup() { MockitoAnnotations.openMocks(this); OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(HDDS_X509_ROOTCA_CLIENT_POLLING_FREQUENCY, "PT1s"); + conf.set(HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL, "PT1s"); secConf = new SecurityConfig(conf); } From a9296fc49b76b514609191bfc42b1efb66e5fdaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20G=C3=A1l?= Date: Wed, 5 Jul 2023 15:31:08 +0200 Subject: [PATCH 3/6] HDDS-8591 Replace the phrase interval instead of frequency --- .../apache/hadoop/hdds/security/SecurityConfig.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java index fcea09580423..d38a9a3016c6 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java @@ -133,7 +133,7 @@ public class SecurityConfig { Pattern.compile("\\d{2}:\\d{2}:\\d{2}"); private final Duration caAckTimeout; private final SslProvider grpcSSLProvider; - private final Duration rootCaClientPollingFrequency; + private final Duration rootCaClientPollingInterval; /** * Constructs a SecurityConfig. @@ -231,12 +231,12 @@ public SecurityConfig(ConfigurationSource configuration) { validateCertificateValidityConfig(); - String rootCaClientPollingFrequencyString = configuration.get( + String rootCaClientPollingIntervalString = configuration.get( HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL, HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT); - this.rootCaClientPollingFrequency = - Duration.parse(rootCaClientPollingFrequencyString); + this.rootCaClientPollingInterval = + Duration.parse(rootCaClientPollingIntervalString); this.externalRootCaCert = configuration.get( HDDS_X509_ROOTCA_CERTIFICATE_FILE, @@ -563,7 +563,7 @@ public Duration getCaAckTimeout() { } public Duration getRootCaClientPollingInterval() { - return rootCaClientPollingFrequency; + return rootCaClientPollingInterval; } /** From 546757a534f9df64868b03e2c0accea003a2a3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20G=C3=A1l?= Date: Wed, 5 Jul 2023 16:46:42 +0200 Subject: [PATCH 4/6] HDDS-8591 Address renew comments --- .../org/apache/hadoop/hdds/HddsConfigKeys.java | 8 ++++---- .../hadoop/hdds/security/SecurityConfig.java | 8 ++++---- .../common/src/main/resources/ozone-default.xml | 2 +- .../certificate/client/RootCaRotationPoller.java | 15 +++++++-------- .../utils/TestRootCaRotationPoller.java | 4 ++-- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java index ba3df6447a5d..e1edd945532d 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java @@ -222,10 +222,10 @@ public final class HddsConfigKeys { "hdds.x509.ca.rotation.ack.timeout"; public static final String HDDS_X509_CA_ROTATION_ACK_TIMEOUT_DEFAULT = "PT15M"; - public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL = - "hdds.x509.rootca.client.polling.interval"; - public static final String HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT - = "PT2h"; + public static final String HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL = + "hdds.x509.rootca.certificate.polling.interval"; + public static final String + HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL_DEFAULT = "PT2h"; public static final String HDDS_CONTAINER_REPLICATION_COMPRESSION = "hdds.container.replication.compression"; diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java index d38a9a3016c6..78f7491c4f33 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java @@ -52,8 +52,8 @@ import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_CA_ROTATION_TIME_OF_DAY_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_FILE_DEFAULT; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PRIVATE_KEY_FILE_DEFAULT; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_PUBLIC_KEY_FILE; @@ -232,8 +232,8 @@ public SecurityConfig(ConfigurationSource configuration) { validateCertificateValidityConfig(); String rootCaClientPollingIntervalString = configuration.get( - HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL, - HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL_DEFAULT); + HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL, + HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL_DEFAULT); this.rootCaClientPollingInterval = Duration.parse(rootCaClientPollingIntervalString); diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml index c610622156c8..ce65be861dee 100644 --- a/hadoop-hdds/common/src/main/resources/ozone-default.xml +++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml @@ -2269,7 +2269,7 @@ - hdds.x509.rootca.client.polling.interval + hdds.x509.rootca.certificate.polling.interval PT2h Interval to use for polling in certificate clients for a new root ca certificate. Every time the specified time duration elapses, diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java index 690d6085a4a4..1756dcc496bf 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hdds.security.x509.certificate.client; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB; import org.apache.hadoop.hdds.security.SecurityConfig; import org.apache.hadoop.ozone.OzoneSecurityUtil; @@ -64,7 +63,7 @@ public RootCaRotationPoller(SecurityConfig securityConfig, this.knownRootCerts = initiallyKnownRootCaCerts; poller = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat( - "RootCaRotationPoller") + this.getClass().getSimpleName()) .setDaemon(true).build()); pollingInterval = securityConfig.getRootCaClientPollingInterval(); rootCARotationProcessors = new ArrayList<>(); @@ -99,7 +98,7 @@ private void pollRootCas() { } }); } catch (IOException e) { - LOG.error("Error while trying to rotate root ca certificate", e); + LOG.error("Error while trying to poll root ca certificate", e); } } @@ -126,19 +125,19 @@ private void executorServiceShutdownGraceful(ExecutorService executor) { executor.shutdownNow(); } if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { - LOG.error("Unable to shutdown root ca certificate rotation poller."); + LOG.warn("{} couldn't be shut down gracefully", + getClass().getSimpleName()); } } catch (InterruptedException e) { - LOG.error("Error attempting to shutdown.", e); - executor.shutdownNow(); + LOG.warn("{} couldn't be stopped gracefully", getClass().getSimpleName()); Thread.currentThread().interrupt(); } } private String getPrintableCertIds(Collection certs) { - return StringUtils.join(certs.stream() + return certs.stream() .map(X509Certificate::getSerialNumber) .map(BigInteger::toString) - .collect(Collectors.toList()), ", "); + .collect(Collectors.joining(", ")); } } diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java index 41f97d7bf1f7..7f2ed0a8135c 100644 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java @@ -43,7 +43,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL; +import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL; /** * Test for Root Ca Rotation polling mechanism on client side. @@ -59,7 +59,7 @@ public class TestRootCaRotationPoller { public void setup() { MockitoAnnotations.openMocks(this); OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(HDDS_X509_ROOTCA_CLIENT_POLLING_INTERVAL, "PT1s"); + conf.set(HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL, "PT1s"); secConf = new SecurityConfig(conf); } From 859c2f9431c68b3777f290128576b3460887cc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20G=C3=A1l?= Date: Wed, 5 Jul 2023 16:55:23 +0200 Subject: [PATCH 5/6] HDDS-8591 Fix missing client -> certificate rename --- .../apache/hadoop/hdds/security/SecurityConfig.java | 12 ++++++------ .../certificate/client/RootCaRotationPoller.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java index 78f7491c4f33..d2bd588d095d 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/security/SecurityConfig.java @@ -133,7 +133,7 @@ public class SecurityConfig { Pattern.compile("\\d{2}:\\d{2}:\\d{2}"); private final Duration caAckTimeout; private final SslProvider grpcSSLProvider; - private final Duration rootCaClientPollingInterval; + private final Duration rootCaCertificatePollingInterval; /** * Constructs a SecurityConfig. @@ -231,12 +231,12 @@ public SecurityConfig(ConfigurationSource configuration) { validateCertificateValidityConfig(); - String rootCaClientPollingIntervalString = configuration.get( + String rootCaCertificatePollingIntervalString = configuration.get( HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL, HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL_DEFAULT); - this.rootCaClientPollingInterval = - Duration.parse(rootCaClientPollingIntervalString); + this.rootCaCertificatePollingInterval = + Duration.parse(rootCaCertificatePollingIntervalString); this.externalRootCaCert = configuration.get( HDDS_X509_ROOTCA_CERTIFICATE_FILE, @@ -562,8 +562,8 @@ public Duration getCaAckTimeout() { return caAckTimeout; } - public Duration getRootCaClientPollingInterval() { - return rootCaClientPollingInterval; + public Duration getRootCaCertificatePollingInterval() { + return rootCaCertificatePollingInterval; } /** diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java index 1756dcc496bf..47cc368bbefe 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java @@ -65,7 +65,7 @@ public RootCaRotationPoller(SecurityConfig securityConfig, new ThreadFactoryBuilder().setNameFormat( this.getClass().getSimpleName()) .setDaemon(true).build()); - pollingInterval = securityConfig.getRootCaClientPollingInterval(); + pollingInterval = securityConfig.getRootCaCertificatePollingInterval(); rootCARotationProcessors = new ArrayList<>(); } From 419754459402f0c77e35604ed903ad813c2bd2a0 Mon Sep 17 00:00:00 2001 From: Sammi Chen Date: Thu, 6 Jul 2023 10:24:53 +0800 Subject: [PATCH 6/6] trigger CI