rootCAs) {
+ if (rootCaCertificates.containsAll(rootCAs)) {
+ return CompletableFuture.completedFuture(null);
+ }
+ CertificateRenewerService renewerService = new CertificateRenewerService(
+ this, true);
+ return CompletableFuture.runAsync(renewerService, executorService);
+ }
+
public synchronized void startCertificateMonitor() {
Preconditions.checkNotNull(getCertificate(),
"Component certificate should not be empty");
@@ -1268,7 +1335,8 @@ public synchronized void startCertificateMonitor() {
getComponentName() + "-CertificateLifetimeMonitor")
.setDaemon(true).build());
}
- this.executorService.scheduleAtFixedRate(new CertificateLifetimeMonitor(),
+ this.executorService.scheduleAtFixedRate(
+ new CertificateRenewerService(this, false),
timeBeforeGracePeriod, interval, TimeUnit.MILLISECONDS);
getLogger().info("CertificateLifetimeMonitor for {} is started with " +
"first delay {} ms and interval {} ms.", component,
@@ -1276,11 +1344,16 @@ public synchronized void startCertificateMonitor() {
}
/**
- * Task to monitor certificate lifetime and renew the certificate if needed.
+ * Task to monitor certificate lifetime and renew the certificate if needed.
*/
- public class CertificateLifetimeMonitor implements Runnable {
-
- public CertificateLifetimeMonitor() {
+ public class CertificateRenewerService implements Runnable {
+ private CertificateClient certClient;
+ private boolean forceRenewal;
+
+ public CertificateRenewerService(CertificateClient client,
+ boolean forceRenewal) {
+ this.certClient = client;
+ this.forceRenewal = forceRenewal;
}
@Override
@@ -1295,41 +1368,41 @@ public void run() {
synchronized (DefaultCertificateClient.class) {
X509Certificate currentCert = getCertificate();
Duration timeLeft = timeBeforeExpiryGracePeriod(currentCert);
- if (timeLeft.isZero()) {
- String newCertId;
- try {
- getLogger().info("Current certificate {} has entered the expiry" +
- " grace period {}. Starting renew key and certs.",
- currentCert.getSerialNumber().toString(),
- timeLeft, securityConfig.getRenewalGracePeriod());
- newCertId = renewAndStoreKeyAndCertificate(false);
- } catch (CertificateException e) {
- if (e.errorCode() ==
- CertificateException.ErrorCode.ROLLBACK_ERROR) {
- if (shutdownCallback != null) {
- getLogger().error("Failed to rollback key and cert after an " +
- " unsuccessful renew try.", e);
- shutdownCallback.run();
- }
+ if (!forceRenewal && !timeLeft.isZero()) {
+ return;
+ }
+ String newCertId;
+ try {
+ getLogger().info("Current certificate has entered the expiry" +
+ " grace period {}. Starting renew key and certs.",
+ timeLeft, securityConfig.getRenewalGracePeriod());
+ newCertId = renewAndStoreKeyAndCertificate(forceRenewal);
+ } catch (CertificateException e) {
+ if (e.errorCode() ==
+ CertificateException.ErrorCode.ROLLBACK_ERROR) {
+ if (shutdownCallback != null) {
+ getLogger().error("Failed to rollback key and cert after an " +
+ " unsuccessful renew try.", e);
+ shutdownCallback.run();
}
- getLogger().error("Failed to renew and store key and cert." +
- " Keep using existing certificates.", e);
- return;
- }
-
- // Persist new cert serial id in component VERSION file
- if (certIdSaveCallback != null) {
- certIdSaveCallback.accept(newCertId);
}
+ getLogger().error("Failed to renew and store key and cert." +
+ " Keep using existing certificates.", e);
+ return;
+ }
- // reset and reload all certs
- reloadKeyAndCertificate(newCertId);
- // cleanup backup directory
- cleanBackupDir();
+ // Persist new cert serial id in component VERSION file
+ if (certIdSaveCallback != null) {
+ certIdSaveCallback.accept(newCertId);
}
+
+ // reset and reload all certs
+ reloadKeyAndCertificate(newCertId);
+ // cleanup backup directory
+ cleanBackupDir();
+ }
}
}
- }
/**
* Set the CA certificate. For TEST only.
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..47cc368bbefe
--- /dev/null
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java
@@ -0,0 +1,143 @@
+/*
+ * 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.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 pollingInterval;
+ 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(
+ this.getClass().getSimpleName())
+ .setDaemon(true).build());
+ pollingInterval = securityConfig.getRootCaCertificatePollingInterval();
+ 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 poll root ca certificate", e);
+ }
+ }
+
+ public void addRootCARotationProcessor(
+ Function, CompletableFuture> processor) {
+ rootCARotationProcessors.add(processor);
+ }
+
+ @Override
+ public void run() {
+ poller.scheduleAtFixedRate(this::pollRootCas, 0,
+ pollingInterval.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.warn("{} couldn't be shut down gracefully",
+ getClass().getSimpleName());
+ }
+ } catch (InterruptedException e) {
+ LOG.warn("{} couldn't be stopped gracefully", getClass().getSimpleName());
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private String getPrintableCertIds(Collection certs) {
+ return certs.stream()
+ .map(X509Certificate::getSerialNumber)
+ .map(BigInteger::toString)
+ .collect(Collectors.joining(", "));
+ }
+}
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 26305624b490..48007ec70286 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 org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
import org.apache.hadoop.hdds.security.SecurityConfig;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
@@ -31,6 +32,7 @@
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;
@@ -183,8 +185,12 @@ public Logger getLogger() {
}
@Override
+ protected SCMGetCertResponseProto getCertificateSignResponse(PKCS10CertificationRequest request) throws IOException {
+ return null;
+ }
+
public String signAndStoreCertificate(PKCS10CertificationRequest request,
- Path certPath, boolean renew) throws CertificateException {
+ Path certPath, boolean renew) {
try {
HddsProtos.ScmNodeDetailsProto scmNodeDetailsProto =
HddsProtos.ScmNodeDetailsProto.newBuilder()
@@ -224,4 +230,9 @@ public String signAndStoreCertificate(PKCS10CertificationRequest request,
throw new RuntimeException(e);
}
}
+
+ @Override
+ protected void startRootCaRotationPoller() {
+ //SCM root CA rotation is handled separately from polling
+ }
}
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 c0af10a3da65..aea71ec82ee6 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
@@ -20,7 +20,7 @@
import org.apache.hadoop.hdds.HddsConfigKeys;
import org.apache.hadoop.hdds.protocol.MockDatanodeDetails;
-import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos;
+import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
import org.apache.hadoop.hdds.security.x509.certificate.authority.CAType;
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient.InitResponse;
@@ -484,15 +484,14 @@ public X509Certificate getCertificate() {
}
@Override
- public String signAndStoreCertificate(
- PKCS10CertificationRequest request, Path certificatePath) {
+ protected SCMGetCertResponseProto getCertificateSignResponse(
+ PKCS10CertificationRequest request) {
return null;
}
@Override
public String signAndStoreCertificate(
- PKCS10CertificationRequest request, Path certificatePath,
- boolean renew) throws CertificateException {
+ PKCS10CertificationRequest request) {
return null;
}
}) {
@@ -536,10 +535,10 @@ public void testRenewAndStoreKeyAndCertificate() throws Exception {
X509Certificate newCert = generateX509Cert(null);
String pemCert = CertificateCodec.getPEMEncodedString(newCert);
- SCMSecurityProtocolProtos.SCMGetCertResponseProto responseProto =
- SCMSecurityProtocolProtos.SCMGetCertResponseProto
- .newBuilder().setResponseCode(SCMSecurityProtocolProtos
- .SCMGetCertResponseProto.ResponseCode.success)
+ SCMGetCertResponseProto responseProto =
+ SCMGetCertResponseProto
+ .newBuilder()
+ .setResponseCode(SCMGetCertResponseProto.ResponseCode.success)
.setX509Certificate(pemCert)
.setX509CACertificate(pemCert)
.build();
@@ -626,17 +625,17 @@ public void testCloseCertificateClient(@TempDir File metaDir)
) {
@Override
- protected String signAndStoreCertificate(
- PKCS10CertificationRequest request, Path certificatePath) {
- return "";
+ protected SCMGetCertResponseProto getCertificateSignResponse(
+ PKCS10CertificationRequest request) {
+ return null;
}
@Override
- protected String signAndStoreCertificate(
- PKCS10CertificationRequest request, Path certificatePath,
- boolean renew) throws CertificateException {
- return null;
+ public String signAndStoreCertificate(
+ PKCS10CertificationRequest request) {
+ return "";
}
+
};
Thread[] threads = new Thread[Thread.activeCount()];
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..7f2ed0a8135c
--- /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_CERTIFICATE_POLLING_INTERVAL;
+
+/**
+ * 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_CERTIFICATE_POLLING_INTERVAL, "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());
+ }
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OMCertificateClient.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OMCertificateClient.java
index 1a94d16521af..997b7939cca5 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OMCertificateClient.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OMCertificateClient.java
@@ -24,9 +24,7 @@
import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
import org.apache.hadoop.hdds.security.SecurityConfig;
-import org.apache.hadoop.hdds.security.x509.certificate.authority.CAType;
import org.apache.hadoop.hdds.security.x509.certificate.client.CommonCertificateClient;
-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.om.OMStorage;
@@ -36,7 +34,6 @@
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.nio.file.Path;
import java.security.KeyPair;
import java.util.function.Consumer;
@@ -121,43 +118,14 @@ public CertificateSignRequest.Builder getCSRBuilder()
}
@Override
- public String signAndStoreCertificate(PKCS10CertificationRequest request,
- Path certificatePath, boolean renew) throws CertificateException {
- try {
- SCMGetCertResponseProto response = getScmSecureClient()
- .getOMCertChain(omInfo, getEncodedString(request));
-
- String pemEncodedCert = response.getX509Certificate();
- CertificateCodec certCodec = new CertificateCodec(
- getSecurityConfig(), certificatePath);
-
- // Store SCM CA certificate.
- if (response.hasX509CACertificate()) {
- String pemEncodedRootCert = response.getX509CACertificate();
- storeCertificate(pemEncodedRootCert,
- CAType.SUBORDINATE, certCodec, false, !renew);
- storeCertificate(pemEncodedCert, CAType.NONE, certCodec, false, !renew);
-
- // Store Root CA certificate if available.
- if (response.hasX509RootCACertificate()) {
- storeCertificate(response.getX509RootCACertificate(),
- CAType.ROOT, certCodec, false, !renew);
- }
- return CertificateCodec.getX509Certificate(pemEncodedCert)
- .getSerialNumber().toString();
- } else {
- throw new CertificateException("Unable to retrieve OM certificate " +
- "chain.");
- }
- } catch (IOException | java.security.cert.CertificateException e) {
- LOG.error("Error while signing and storing SCM signed certificate.", e);
- throw new CertificateException(
- "Error while signing and storing SCM signed certificate.", e);
- }
+ public Logger getLogger() {
+ return LOG;
}
@Override
- public Logger getLogger() {
- return LOG;
+ protected SCMGetCertResponseProto getCertificateSignResponse(
+ PKCS10CertificationRequest request) throws IOException {
+ return getScmSecureClient().getOMCertChain(
+ omInfo, getEncodedString(request));
}
}
diff --git a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/security/ReconCertificateClient.java b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/security/ReconCertificateClient.java
index 5381a6159546..6dd9afc8944a 100644
--- a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/security/ReconCertificateClient.java
+++ b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/security/ReconCertificateClient.java
@@ -18,12 +18,10 @@
package org.apache.hadoop.ozone.recon.security;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
-import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos;
+import org.apache.hadoop.hdds.protocol.proto.SCMSecurityProtocolProtos.SCMGetCertResponseProto;
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
import org.apache.hadoop.hdds.security.SecurityConfig;
-import org.apache.hadoop.hdds.security.x509.certificate.authority.CAType;
import org.apache.hadoop.hdds.security.x509.certificate.client.CommonCertificateClient;
-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.recon.scm.ReconStorageConfig;
@@ -34,11 +32,9 @@
import java.io.IOException;
import java.net.InetAddress;
-import java.nio.file.Path;
import java.security.KeyPair;
import java.util.function.Consumer;
-import static org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec.getX509Certificate;
import static org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateSignRequest.getEncodedString;
import static org.apache.hadoop.hdds.security.x509.exception.CertificateException.ErrorCode.CSR_ERROR;
@@ -89,48 +85,23 @@ public CertificateSignRequest.Builder getCSRBuilder()
}
@Override
- public String signAndStoreCertificate(PKCS10CertificationRequest csr,
- Path certificatePath, boolean renew) throws CertificateException {
- try {
- SCMSecurityProtocolProtos.SCMGetCertResponseProto response;
- HddsProtos.NodeDetailsProto.Builder reconDetailsProtoBuilder =
- HddsProtos.NodeDetailsProto.newBuilder()
- .setHostName(InetAddress.getLocalHost().getHostName())
- .setClusterId(clusterID)
- .setUuid(reconID)
- .setNodeType(HddsProtos.NodeType.RECON);
- // TODO: For SCM CA we should fetch certificate from multiple SCMs.
- response = getScmSecureClient().getCertificateChain(
- reconDetailsProtoBuilder.build(), getEncodedString(csr));
-
- // Persist certificates.
- if (response.hasX509CACertificate()) {
- String pemEncodedCert = response.getX509Certificate();
- CertificateCodec certCodec = new CertificateCodec(
- getSecurityConfig(), certificatePath);
- storeCertificate(pemEncodedCert, CAType.NONE, certCodec, false, !renew);
- storeCertificate(response.getX509CACertificate(),
- CAType.SUBORDINATE, certCodec, false, !renew);
-
- // Store Root CA certificate.
- if (response.hasX509RootCACertificate()) {
- storeCertificate(response.getX509RootCACertificate(),
- CAType.ROOT, certCodec, false, !renew);
- }
- return getX509Certificate(pemEncodedCert).getSerialNumber().toString();
- } else {
- throw new CertificateException("Unable to retrieve recon certificate " +
- "chain");
- }
- } catch (IOException | java.security.cert.CertificateException e) {
- LOG.error("Error while signing and storing SCM signed certificate.", e);
- throw new CertificateException(
- "Error while signing and storing SCM signed certificate.", e);
- }
+ public Logger getLogger() {
+ return LOG;
}
@Override
- public Logger getLogger() {
- return LOG;
+ protected SCMGetCertResponseProto getCertificateSignResponse(
+ PKCS10CertificationRequest request) throws IOException {
+ SCMGetCertResponseProto response;
+ HddsProtos.NodeDetailsProto.Builder reconDetailsProtoBuilder =
+ HddsProtos.NodeDetailsProto.newBuilder()
+ .setHostName(InetAddress.getLocalHost().getHostName())
+ .setClusterId(clusterID)
+ .setUuid(reconID)
+ .setNodeType(HddsProtos.NodeType.RECON);
+ // TODO: For SCM CA we should fetch certificate from multiple SCMs.
+ response = getScmSecureClient().getCertificateChain(
+ reconDetailsProtoBuilder.build(), getEncodedString(request));
+ return response;
}
}