Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ef4a43c
HDDS-8591 Create polling mechanism for root ca mechanism
Galsza Jun 22, 2023
ff39ecf
HDDS-8591 Fix review comments, add logging
Galsza Jun 26, 2023
33a40d9
HDDS-8591 Switch to completable future
Galsza Jun 27, 2023
265be72
HDDS-8591 Fix whitespace change
Galsza Jun 27, 2023
5434206
HDDS-8592 Rename CertificateLifeTimeMonitor
Galsza Jun 28, 2023
c026001
HDDS-8592 Rename CertificateLifeTimeMonitor
Galsza Jun 28, 2023
657c50c
HDDS-8592 Refactor DefaultCertificateClient to have signAndStoreCerti…
Galsza Jun 28, 2023
aa00ff6
HDDS-8592 Remove warning from non thrown exception
Galsza Jun 28, 2023
833484d
HDDS-8592 Fetch root CAs from the scm and store them
Galsza Jun 28, 2023
f5bfba4
HDDS-8592 Add force parameter to CertificateRenewalService
Galsza Jun 28, 2023
0b37548
HDDS-8592 Change visibility of the method that shouldn't be seen from…
Galsza Jun 28, 2023
cc9ffca
HDDS-8592 create function for providing task to root ca rotation proc…
Galsza Jun 28, 2023
0bbacb3
HDDS-8592 remove unused import
Galsza Jun 28, 2023
cfa3ab6
HDDS-8591 refine test case for the poller not activating
Galsza Jun 28, 2023
a851885
HDDS-8591 remove unused import
Galsza Jun 28, 2023
164caaf
HDDS-8592 Refine log message to not always imply datanode certificate
Galsza Jun 28, 2023
650f9b1
HDDS-8592 Fix bug with biginteger, remove findbugs issue
Galsza Jun 29, 2023
74af9fd
HDDS-8593 Start up root ca rotation poller
Galsza Jun 28, 2023
6c5ae84
HDDS-8592 Fix failing unit test because of missing mock
Galsza Jun 29, 2023
802001c
Merge remote-tracking branch 'sgal/HDDS-8592_add_root_ca_to_cert_clie…
Galsza Jun 29, 2023
2a1403b
HDDS-8593 Fix findbugs issues
Galsza Jun 29, 2023
c7adcb0
HDDS-8593 Remove poller from SCMCertificateClient
Galsza Jun 29, 2023
d719380
HDDS-8591 Demonize thread for RootCaRotationPoller
Galsza Jun 30, 2023
823c436
Merge remote-tracking branch 'sgal/HDDS-8591_root_ca_rotation_polling…
Galsza Jun 30, 2023
8c2a5eb
Merge branch 'HDDS-8592_add_root_ca_to_cert_client' into HDDS-8593_ad…
Galsza Jun 30, 2023
ce518c3
HDDS-8591 Create root ca rotation poller
Galsza Jul 5, 2023
a89ce73
HDDS-8591 Replace the phrase interval instead of frequency
Galsza Jul 5, 2023
a9296fc
HDDS-8591 Replace the phrase interval instead of frequency
Galsza Jul 5, 2023
546757a
HDDS-8591 Address renew comments
Galsza Jul 5, 2023
859c2f9
HDDS-8591 Fix missing client -> certificate rename
Galsza Jul 5, 2023
070389f
HDDS-8592 Rename CertificateLifeTimeMonitor
Galsza Jun 28, 2023
3620279
Merge remote-tracking branch 'sgal/HDDS-8593_add_root_ca_rotation_pol…
Galsza Jul 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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_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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_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;
Expand Down Expand Up @@ -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 rootCaCertificatePollingInterval;

/**
* Constructs a SecurityConfig.
Expand Down Expand Up @@ -228,6 +231,13 @@ public SecurityConfig(ConfigurationSource configuration) {

validateCertificateValidityConfig();

String rootCaCertificatePollingIntervalString = configuration.get(
HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL,
HDDS_X509_ROOTCA_CERTIFICATE_POLLING_INTERVAL_DEFAULT);

this.rootCaCertificatePollingInterval =
Duration.parse(rootCaCertificatePollingIntervalString);

this.externalRootCaCert = configuration.get(
HDDS_X509_ROOTCA_CERTIFICATE_FILE,
HDDS_X509_ROOTCA_CERTIFICATE_FILE_DEFAULT);
Expand Down Expand Up @@ -552,6 +562,10 @@ public Duration getCaAckTimeout() {
return caAckTimeout;
}

public Duration getRootCaCertificatePollingInterval() {
return rootCaCertificatePollingInterval;
}

/**
* Return true if using test certificates with authority as localhost. This
* should be used only for unit test where certificates are generated by
Expand Down
22 changes: 22 additions & 0 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,28 @@
is failed. Default is 15 minutes.
</description>
</property>
<property>
<name>hdds.x509.rootca.certificate.polling.interval</name>
<value>PT2h</value>
<description>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
automatically adds the new root ca to the clients'
trust stores and requests a new certificate to be signed.
</description>
</property>
<property>
<name>hdds.x509.rootca.client.polling.frequency</name>
<value>PT2h</value>
<description>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.
</description>
</property>
<property>
<name>ozone.scm.security.handler.count.key</name>
<value>2</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import java.security.cert.CertificateExpiredException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import org.apache.hadoop.fs.FileUtil;
Expand Down Expand Up @@ -316,6 +318,10 @@ public void testCertificateRotation() throws Exception {
when(scmClient.getDataNodeCertificateChain(anyObject(), anyString()))
.thenReturn(responseProto);

List<String> rootCaList = new ArrayList<>();
rootCaList.add(pemCert);
when(scmClient.getAllRootCaCertificates()).thenReturn(rootCaList);

// check that new cert ID should not equal to current cert ID
String certId = newCertHolder.getSerialNumber().toString();
Assert.assertFalse(certId.equals(
Expand All @@ -338,6 +344,7 @@ public void testCertificateRotation() throws Exception {
// test the second time certificate rotation, generate a new cert
newCertHolder = generateX509CertHolder(null, null,
Duration.ofSeconds(CERT_LIFETIME));
rootCaList.remove(pemCert);
pemCert = CertificateCodec.getPEMEncodedString(newCertHolder);
responseProto = SCMSecurityProtocolProtos.SCMGetCertResponseProto
.newBuilder().setResponseCode(SCMSecurityProtocolProtos
Expand All @@ -348,6 +355,8 @@ public void testCertificateRotation() throws Exception {
.build();
when(scmClient.getDataNodeCertificateChain(anyObject(), anyString()))
.thenReturn(responseProto);
rootCaList.add(pemCert);
when(scmClient.getAllRootCaCertificates()).thenReturn(rootCaList);
String certId2 = newCertHolder.getSerialNumber().toString();

// check after renew, client will have the new cert ID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@
package org.apache.hadoop.hdds.security.x509.certificate.client;

import org.apache.hadoop.hdds.protocol.DatanodeDetails;
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.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.security.UserGroupInformation;
Expand All @@ -34,7 +32,6 @@

import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Path;
import java.security.KeyPair;
import java.util.function.Consumer;

Expand Down Expand Up @@ -98,43 +95,10 @@ public CertificateSignRequest.Builder getCSRBuilder()
}

@Override
public String signAndStoreCertificate(PKCS10CertificationRequest csr,
Path certificatePath, boolean renew) throws CertificateException {
try {
// TODO: For SCM CA we should fetch certificate from multiple SCMs.
SCMSecurityProtocolProtos.SCMGetCertResponseProto response =
getScmSecureClient().getDataNodeCertificateChain(
dn.getProtoBufMessage(), getEncodedString(csr));

// Persist certificates.
if (response.hasX509CACertificate()) {
String pemEncodedCert = response.getX509Certificate();
CertificateCodec certCodec = new CertificateCodec(
getSecurityConfig(), certificatePath);
// Certs will be added to cert map after reloadAllCertificate called
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 the default certificate ID
return CertificateCodec.getX509Certificate(pemEncodedCert)
.getSerialNumber()
.toString();
} else {
throw new CertificateException("Unable to retrieve datanode " +
"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 SCMGetCertResponseProto getCertificateSignResponse(
PKCS10CertificationRequest csr) throws IOException {
return getScmSecureClient().getDataNodeCertificateChain(
dn.getProtoBufMessage(), getEncodedString(csr));
}

@Override
Expand Down
Loading