Report the number of days until the CDS CA cert expires as a metric so we can set an alarm.

This commit is contained in:
Jon Chambers 2020-05-05 17:12:47 -04:00 committed by Jon Chambers
parent b1d11d4f69
commit 1c73c91133
3 changed files with 80 additions and 2 deletions

View File

@ -16,12 +16,15 @@
*/
package org.whispersystems.textsecuregcm.storage;
import com.codahale.metrics.SharedMetricRegistries;
import org.bouncycastle.openssl.PEMReader;
import org.glassfish.jersey.SslConfigurator;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.whispersystems.textsecuregcm.configuration.DirectoryServerConfiguration;
import org.whispersystems.textsecuregcm.entities.DirectoryReconciliationRequest;
import org.whispersystems.textsecuregcm.entities.DirectoryReconciliationResponse;
import org.whispersystems.textsecuregcm.util.CertificateExpirationGauge;
import org.whispersystems.textsecuregcm.util.Constants;
import javax.net.ssl.SSLContext;
import javax.ws.rs.client.Client;
@ -37,6 +40,8 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import static com.codahale.metrics.MetricRegistry.name;
public class DirectoryReconciliationClient {
private final String replicationUrl;
@ -47,6 +52,10 @@ public class DirectoryReconciliationClient {
{
this.replicationUrl = directoryServerConfiguration.getReplicationUrl();
this.client = initializeClient(directoryServerConfiguration);
SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME)
.register(name(getClass(), "days_until_certificate_expiration"),
new CertificateExpirationGauge(getCertificate(directoryServerConfiguration.getReplicationCaCertificate())));
}
public DirectoryReconciliationResponse sendChunk(DirectoryReconciliationRequest request) {
@ -74,8 +83,7 @@ public class DirectoryReconciliationClient {
throws CertificateException
{
try {
PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(caCertificatePem.getBytes())));
X509Certificate certificate = (X509Certificate) reader.readObject();
X509Certificate certificate = getCertificate(caCertificatePem);
if (certificate == null) {
throw new CertificateException("No certificate found in parsing!");
@ -92,4 +100,11 @@ public class DirectoryReconciliationClient {
}
}
private static X509Certificate getCertificate(final String certificatePem) throws CertificateException {
try (PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(certificatePem.getBytes())))) {
return (X509Certificate) reader.readObject();
} catch (IOException e) {
throw new CertificateException(e);
}
}
}

View File

@ -0,0 +1,32 @@
package org.whispersystems.textsecuregcm.util;
import com.codahale.metrics.CachedGauge;
import org.bouncycastle.openssl.PEMReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
/**
* Measures and reports the number of days until a certificate expires.
*/
public class CertificateExpirationGauge extends CachedGauge<Long> {
private final Instant certificateExpiration;
public CertificateExpirationGauge(final X509Certificate certificate) {
super(1, TimeUnit.HOURS);
certificateExpiration = certificate.getNotAfter().toInstant();
}
@Override
protected Long loadValue() {
return Duration.between(Instant.now(), certificateExpiration).toDays();
}
}

View File

@ -0,0 +1,31 @@
package org.whispersystems.textsecuregcm.util;
import org.junit.Test;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class CertificateExpirationGaugeTest {
@Test
public void loadValue() {
final X509Certificate certificate = mock(X509Certificate.class);
final long daysUntilExpiration = 17;
final Instant now = Instant.now();
final Instant later = now.plus(Duration.ofDays(daysUntilExpiration)).plus(Duration.ofMinutes(1));
when(certificate.getNotAfter()).thenReturn(new Date(later.toEpochMilli()));
final CertificateExpirationGauge gauge = new CertificateExpirationGauge(certificate);
assertEquals(daysUntilExpiration, (long) gauge.loadValue());
}
}