mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
Add method that checks if client should be notified for expiring certificate (#1245)
* fix merge conflict
This commit is contained in:
parent
50f3139b98
commit
5d8600731f
13 changed files with 274 additions and 45 deletions
|
@ -1267,10 +1267,16 @@ public final class RegistryConfig {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Config("expirationWarningDays")
|
@Config("expirationWarningDays")
|
||||||
public static int provideDaysToExpiration(RegistryConfigSettings config) {
|
public static int provideExpirationWarningDays(RegistryConfigSettings config) {
|
||||||
return config.sslCertificateValidation.expirationWarningDays;
|
return config.sslCertificateValidation.expirationWarningDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Config("expirationWarningIntervalDays")
|
||||||
|
public static int provideExpirationWarningIntervalDays(RegistryConfigSettings config) {
|
||||||
|
return config.sslCertificateValidation.expirationWarningIntervalDays;
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Config("minimumRsaKeyLength")
|
@Config("minimumRsaKeyLength")
|
||||||
public static int provideMinimumRsaKeyLength(RegistryConfigSettings config) {
|
public static int provideMinimumRsaKeyLength(RegistryConfigSettings config) {
|
||||||
|
|
|
@ -228,6 +228,7 @@ public class RegistryConfigSettings {
|
||||||
public static class SslCertificateValidation {
|
public static class SslCertificateValidation {
|
||||||
public Map<String, Integer> maxValidityDaysSchedule;
|
public Map<String, Integer> maxValidityDaysSchedule;
|
||||||
public int expirationWarningDays;
|
public int expirationWarningDays;
|
||||||
|
public int expirationWarningIntervalDays;
|
||||||
public int minimumRsaKeyLength;
|
public int minimumRsaKeyLength;
|
||||||
public Set<String> allowedEcdsaCurves;
|
public Set<String> allowedEcdsaCurves;
|
||||||
public String expirationWarningEmailBodyText;
|
public String expirationWarningEmailBodyText;
|
||||||
|
|
|
@ -452,6 +452,8 @@ sslCertificateValidation:
|
||||||
# The number of days before a certificate expires that indicates the
|
# The number of days before a certificate expires that indicates the
|
||||||
# certificate is nearing expiration and warnings should be sent.
|
# certificate is nearing expiration and warnings should be sent.
|
||||||
expirationWarningDays: 30
|
expirationWarningDays: 30
|
||||||
|
# The minimum number of days between two successive expiring notification emails.
|
||||||
|
expirationWarningIntervalDays: 15
|
||||||
# Text for expiring certificate notification email subject.
|
# Text for expiring certificate notification email subject.
|
||||||
expirationWarningEmailSubjectText: Certificate Expring Within 30 Days.
|
expirationWarningEmailSubjectText: Certificate Expring Within 30 Days.
|
||||||
# Text for expiring certificate notification email body that accepts 3 parameters:
|
# Text for expiring certificate notification email body that accepts 3 parameters:
|
||||||
|
|
|
@ -24,6 +24,7 @@ import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
import google.registry.util.DateTimeUtils;
|
import google.registry.util.DateTimeUtils;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
|
@ -32,10 +33,15 @@ import java.security.interfaces.ECPublicKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
|
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
|
||||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
import org.bouncycastle.jce.ECNamedCurveTable;
|
||||||
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||||
|
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||||
|
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
|
||||||
|
import org.bouncycastle.util.io.pem.PemObjectGenerator;
|
||||||
|
import org.bouncycastle.util.io.pem.PemWriter;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
|
|
||||||
|
@ -43,10 +49,11 @@ import org.joda.time.Days;
|
||||||
public class CertificateChecker {
|
public class CertificateChecker {
|
||||||
|
|
||||||
private final ImmutableSortedMap<DateTime, Integer> maxValidityLengthSchedule;
|
private final ImmutableSortedMap<DateTime, Integer> maxValidityLengthSchedule;
|
||||||
private final int daysToExpiration;
|
private final int expirationWarningDays;
|
||||||
private final int minimumRsaKeyLength;
|
private final int minimumRsaKeyLength;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final ImmutableSet<String> allowedEcdsaCurves;
|
private final ImmutableSet<String> allowedEcdsaCurves;
|
||||||
|
private final int expirationWarningIntervalDays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a CertificateChecker instance with the specified configuration parameters.
|
* Constructs a CertificateChecker instance with the specified configuration parameters.
|
||||||
|
@ -72,6 +79,7 @@ public class CertificateChecker {
|
||||||
@Config("maxValidityDaysSchedule")
|
@Config("maxValidityDaysSchedule")
|
||||||
ImmutableSortedMap<DateTime, Integer> maxValidityDaysSchedule,
|
ImmutableSortedMap<DateTime, Integer> maxValidityDaysSchedule,
|
||||||
@Config("expirationWarningDays") int expirationWarningDays,
|
@Config("expirationWarningDays") int expirationWarningDays,
|
||||||
|
@Config("expirationWarningIntervalDays") int expirationWarningIntervalDays,
|
||||||
@Config("minimumRsaKeyLength") int minimumRsaKeyLength,
|
@Config("minimumRsaKeyLength") int minimumRsaKeyLength,
|
||||||
@Config("allowedEcdsaCurves") ImmutableSet<String> allowedEcdsaCurves,
|
@Config("allowedEcdsaCurves") ImmutableSet<String> allowedEcdsaCurves,
|
||||||
Clock clock) {
|
Clock clock) {
|
||||||
|
@ -79,12 +87,46 @@ public class CertificateChecker {
|
||||||
maxValidityDaysSchedule.containsKey(START_OF_TIME),
|
maxValidityDaysSchedule.containsKey(START_OF_TIME),
|
||||||
"Max validity length schedule must contain an entry for START_OF_TIME");
|
"Max validity length schedule must contain an entry for START_OF_TIME");
|
||||||
this.maxValidityLengthSchedule = maxValidityDaysSchedule;
|
this.maxValidityLengthSchedule = maxValidityDaysSchedule;
|
||||||
this.daysToExpiration = expirationWarningDays;
|
this.expirationWarningDays = expirationWarningDays;
|
||||||
this.minimumRsaKeyLength = minimumRsaKeyLength;
|
this.minimumRsaKeyLength = minimumRsaKeyLength;
|
||||||
this.allowedEcdsaCurves = allowedEcdsaCurves;
|
this.allowedEcdsaCurves = allowedEcdsaCurves;
|
||||||
|
this.expirationWarningIntervalDays = expirationWarningIntervalDays;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getValidityLengthInDays(X509Certificate certificate) {
|
||||||
|
DateTime start = DateTime.parse(certificate.getNotBefore().toInstant().toString());
|
||||||
|
DateTime end = DateTime.parse(certificate.getNotAfter().toInstant().toString());
|
||||||
|
return Days.daysBetween(start.withTimeAtStartOfDay(), end.withTimeAtStartOfDay()).getDays();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the curve used for a public key is in the list of acceptable curves. */
|
||||||
|
private static boolean checkCurveName(PublicKey key, ImmutableSet<String> allowedEcdsaCurves) {
|
||||||
|
ECParameterSpec params;
|
||||||
|
// These 2 different instances of PublicKey need to be handled separately since their OIDs are
|
||||||
|
// encoded differently. More details on this can be found at
|
||||||
|
// https://stackoverflow.com/questions/49895713/how-to-find-the-matching-curve-name-from-an-ecpublickey.
|
||||||
|
if (key instanceof ECPublicKey) {
|
||||||
|
ECPublicKey ecKey = (ECPublicKey) key;
|
||||||
|
params = EC5Util.convertSpec(ecKey.getParams(), false);
|
||||||
|
} else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey) {
|
||||||
|
org.bouncycastle.jce.interfaces.ECPublicKey ecKey =
|
||||||
|
(org.bouncycastle.jce.interfaces.ECPublicKey) key;
|
||||||
|
params = ecKey.getParameters();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unrecognized instance of PublicKey.");
|
||||||
|
}
|
||||||
|
return allowedEcdsaCurves.stream()
|
||||||
|
.anyMatch(
|
||||||
|
curve -> {
|
||||||
|
ECNamedCurveParameterSpec cParams = ECNamedCurveTable.getParameterSpec(curve);
|
||||||
|
return cParams.getN().equals(params.getN())
|
||||||
|
&& cParams.getH().equals(params.getH())
|
||||||
|
&& cParams.getCurve().equals(params.getCurve())
|
||||||
|
&& cParams.getG().equals(params.getG());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the given certificate string for violations and throws an exception if any violations
|
* Checks the given certificate string for violations and throws an exception if any violations
|
||||||
* exist.
|
* exist.
|
||||||
|
@ -156,18 +198,7 @@ public class CertificateChecker {
|
||||||
* the violations the certificate has.
|
* the violations the certificate has.
|
||||||
*/
|
*/
|
||||||
public ImmutableSet<CertificateViolation> checkCertificate(String certificateString) {
|
public ImmutableSet<CertificateViolation> checkCertificate(String certificateString) {
|
||||||
X509Certificate certificate;
|
return checkCertificate(getCertificate(certificateString));
|
||||||
|
|
||||||
try {
|
|
||||||
certificate =
|
|
||||||
(X509Certificate)
|
|
||||||
CertificateFactory.getInstance("X509")
|
|
||||||
.generateCertificate(new ByteArrayInputStream(certificateString.getBytes(UTF_8)));
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
throw new IllegalArgumentException("Unable to read given certificate.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkCertificate(certificate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,42 +212,59 @@ public class CertificateChecker {
|
||||||
public boolean isNearingExpiration(X509Certificate certificate) {
|
public boolean isNearingExpiration(X509Certificate certificate) {
|
||||||
Date nearingExpirationDate =
|
Date nearingExpirationDate =
|
||||||
DateTime.parse(certificate.getNotAfter().toInstant().toString())
|
DateTime.parse(certificate.getNotAfter().toInstant().toString())
|
||||||
.minusDays(daysToExpiration)
|
.minusDays(expirationWarningDays)
|
||||||
.toDate();
|
.toDate();
|
||||||
return clock.nowUtc().toDate().after(nearingExpirationDate);
|
return clock.nowUtc().toDate().after(nearingExpirationDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getValidityLengthInDays(X509Certificate certificate) {
|
/** Converts the given string to a certificate object. */
|
||||||
DateTime start = DateTime.parse(certificate.getNotBefore().toInstant().toString());
|
public X509Certificate getCertificate(String certificateStr) {
|
||||||
DateTime end = DateTime.parse(certificate.getNotAfter().toInstant().toString());
|
X509Certificate certificate;
|
||||||
return Days.daysBetween(start.withTimeAtStartOfDay(), end.withTimeAtStartOfDay()).getDays();
|
try {
|
||||||
|
certificate =
|
||||||
|
(X509Certificate)
|
||||||
|
CertificateFactory.getInstance("X509")
|
||||||
|
.generateCertificate(new ByteArrayInputStream(certificateStr.getBytes(UTF_8)));
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("Unable to read given certificate %s", certificateStr), e);
|
||||||
|
}
|
||||||
|
return certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks if the curve used for a public key is in the list of acceptable curves. */
|
/** Serializes the certificate object to a certificate string. */
|
||||||
private static boolean checkCurveName(PublicKey key, ImmutableSet<String> allowedEcdsaCurves) {
|
public String serializeCertificate(X509Certificate certificate) throws Exception {
|
||||||
org.bouncycastle.jce.spec.ECParameterSpec params;
|
StringWriter sw = new StringWriter();
|
||||||
// These 2 different instances of PublicKey need to be handled separately since their OIDs are
|
try (PemWriter pw = new PemWriter(sw)) {
|
||||||
// encoded differently. More details on this can be found at
|
PemObjectGenerator generator = new JcaMiscPEMGenerator(certificate);
|
||||||
// https://stackoverflow.com/questions/49895713/how-to-find-the-matching-curve-name-from-an-ecpublickey.
|
pw.writeObject(generator);
|
||||||
if (key instanceof ECPublicKey) {
|
|
||||||
ECPublicKey ecKey = (ECPublicKey) key;
|
|
||||||
params = EC5Util.convertSpec(ecKey.getParams(), false);
|
|
||||||
} else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey) {
|
|
||||||
org.bouncycastle.jce.interfaces.ECPublicKey ecKey =
|
|
||||||
(org.bouncycastle.jce.interfaces.ECPublicKey) key;
|
|
||||||
params = ecKey.getParameters();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unrecognized instance of PublicKey.");
|
|
||||||
}
|
}
|
||||||
return allowedEcdsaCurves.stream()
|
return sw.toString();
|
||||||
.anyMatch(
|
}
|
||||||
curve -> {
|
|
||||||
ECNamedCurveParameterSpec cParams = ECNamedCurveTable.getParameterSpec(curve);
|
/** Returns whether the client should receive a notification email. */
|
||||||
return cParams.getN().equals(params.getN())
|
public boolean shouldReceiveExpiringNotification(
|
||||||
&& cParams.getH().equals(params.getH())
|
@Nullable DateTime lastExpiringNotificationSentDate, String certificateStr) {
|
||||||
&& cParams.getCurve().equals(params.getCurve())
|
X509Certificate certificate = getCertificate(certificateStr);
|
||||||
&& cParams.getG().equals(params.getG());
|
DateTime now = clock.nowUtc();
|
||||||
});
|
// expiration date is one day after lastValidDate
|
||||||
|
Date lastValidDate = certificate.getNotAfter();
|
||||||
|
if (lastValidDate.before(now.toDate())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Client should receive a notification if :
|
||||||
|
* 1) client has never received notification and the certificate has entered
|
||||||
|
* the expiring period, OR
|
||||||
|
* 2) client has received notification but the interval between now and
|
||||||
|
* lastExpiringNotificationSentDate is greater than expirationWarningIntervalDays.
|
||||||
|
*/
|
||||||
|
return !lastValidDate.after(now.plusDays(expirationWarningDays).toDate())
|
||||||
|
&& (lastExpiringNotificationSentDate == null
|
||||||
|
|| !lastExpiringNotificationSentDate
|
||||||
|
.plusDays(expirationWarningIntervalDays)
|
||||||
|
.toDate()
|
||||||
|
.after(now.toDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getViolationDisplayMessage(CertificateViolation certificateViolation) {
|
private String getViolationDisplayMessage(CertificateViolation certificateViolation) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ class EppLoginTlsTest extends EppTestCase {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
clock);
|
clock);
|
||||||
|
|
|
@ -64,6 +64,7 @@ class FlowRunnerTest {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
clock);
|
clock);
|
||||||
|
|
|
@ -53,6 +53,7 @@ final class TlsCredentialsTest {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
clock);
|
clock);
|
||||||
|
|
|
@ -50,6 +50,7 @@ class CertificateCheckerTest {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
fakeClock);
|
fakeClock);
|
||||||
|
@ -214,7 +215,7 @@ class CertificateCheckerTest {
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> certificateChecker.checkCertificate("bad certificate string"));
|
() -> certificateChecker.checkCertificate("bad certificate string"));
|
||||||
assertThat(thrown).hasMessageThat().isEqualTo("Unable to read given certificate.");
|
assertThat(thrown).hasMessageThat().contains("Unable to read given certificate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -241,6 +242,169 @@ class CertificateCheckerTest {
|
||||||
assertThat(certificateChecker.isNearingExpiration(certificate)).isFalse();
|
assertThat(certificateChecker.isNearingExpiration(certificate)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_getCertificate_throwsException_invalidCertificateString() {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() -> certificateChecker.getCertificate("invalidCertificateString"));
|
||||||
|
assertThat(thrown).hasMessageThat().contains("Unable to read given certificate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_getCertificate_returnsCertificateObject() throws Exception {
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-09-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-10-01T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
assertThat(certificateChecker.getCertificate(certificateStr).equals(certificate)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_serializeCertificate_returnsCertificateString() throws Exception {
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-09-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-10-01T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
assertThat(
|
||||||
|
certificateChecker.getCertificate(certificateChecker.serializeCertificate(certificate)))
|
||||||
|
.isEqualTo(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsFalse_greaterThan30() throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-07-20T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-09-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-10-01T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
assertThat(certificateChecker.shouldReceiveExpiringNotification(null, certificateStr))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsFalse_hasExpired() throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-10-20T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-09-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-10-01T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
assertThat(certificateChecker.shouldReceiveExpiringNotification(null, certificateStr))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsTrue_on15days() throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-08-16T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-09-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-08-30T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
DateTime lastExpiringNotificationSentDate = DateTime.parse("2021-08-01T00:00:00Z");
|
||||||
|
assertThat(
|
||||||
|
certificateChecker.shouldReceiveExpiringNotification(
|
||||||
|
lastExpiringNotificationSentDate, certificateStr))
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsTrue_on30days() throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-01-01T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-01-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-01-30T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
assertThat(certificateChecker.shouldReceiveExpiringNotification(null, certificateStr)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsFalse_between30and15_lastSentDateIsNotNull()
|
||||||
|
throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-07-05T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-06-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-07-25T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
DateTime lastExpiringNotificationSentDate = DateTime.parse("2021-07-04T00:00:00Z");
|
||||||
|
assertThat(
|
||||||
|
certificateChecker.shouldReceiveExpiringNotification(
|
||||||
|
lastExpiringNotificationSentDate, certificateStr))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsTrue_between30and15_lastSentDateIsNull()
|
||||||
|
throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-07-05T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-06-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-07-25T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
assertThat(certificateChecker.shouldReceiveExpiringNotification(null, certificateStr)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void
|
||||||
|
test_shouldReceiveExpiringNotification_returnsFalse_between15and0_lastSentDateBetween30and15_butLate()
|
||||||
|
throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-07-05T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-06-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-07-18T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
DateTime lastExpiringNotificationSentDate = DateTime.parse("2021-07-01T00:00:00Z");
|
||||||
|
// The first notification date is late and difference between now and
|
||||||
|
// lastExpiringNotificationSentDate is within expirationWarningIntervalDays.
|
||||||
|
assertThat(
|
||||||
|
certificateChecker.shouldReceiveExpiringNotification(
|
||||||
|
lastExpiringNotificationSentDate, certificateStr))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_shouldReceiveExpiringNotification_returnsTrue_between15and0_lastSentDateBetween30and15()
|
||||||
|
throws Exception {
|
||||||
|
fakeClock.setTo(DateTime.parse("2021-07-05T00:00:00Z"));
|
||||||
|
X509Certificate certificate =
|
||||||
|
SelfSignedCaCertificate.create(
|
||||||
|
SSL_HOST,
|
||||||
|
DateTime.parse("2020-06-02T00:00:00Z"),
|
||||||
|
DateTime.parse("2021-07-18T00:00:00Z"))
|
||||||
|
.cert();
|
||||||
|
String certificateStr = certificateChecker.serializeCertificate(certificate);
|
||||||
|
DateTime lastExpiringNotificationSentDate = DateTime.parse("2021-06-20T00:00:00Z");
|
||||||
|
assertThat(
|
||||||
|
certificateChecker.shouldReceiveExpiringNotification(
|
||||||
|
lastExpiringNotificationSentDate, certificateStr))
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test_CertificateViolation_RsaKeyLengthDisplayMessageFormatsCorrectly() {
|
void test_CertificateViolation_RsaKeyLengthDisplayMessageFormatsCorrectly() {
|
||||||
assertThat(RSA_KEY_LENGTH_TOO_SHORT.getDisplayMessage(certificateChecker))
|
assertThat(RSA_KEY_LENGTH_TOO_SHORT.getDisplayMessage(certificateChecker))
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
clock);
|
clock);
|
||||||
|
|
|
@ -67,6 +67,7 @@ class CreateRegistrarCommandTest extends CommandTestCase<CreateRegistrarCommand>
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
fakeClock);
|
fakeClock);
|
||||||
|
|
|
@ -53,6 +53,7 @@ class UpdateRegistrarCommandTest extends CommandTestCase<UpdateRegistrarCommand>
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
fakeClock);
|
fakeClock);
|
||||||
|
|
|
@ -65,6 +65,7 @@ class ValidateLoginCredentialsCommandTest extends CommandTestCase<ValidateLoginC
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
fakeClock);
|
fakeClock);
|
||||||
|
|
|
@ -128,6 +128,7 @@ public abstract class RegistrarSettingsActionTestCase {
|
||||||
new CertificateChecker(
|
new CertificateChecker(
|
||||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||||
30,
|
30,
|
||||||
|
15,
|
||||||
2048,
|
2048,
|
||||||
ImmutableSet.of("secp256r1", "secp384r1"),
|
ImmutableSet.of("secp256r1", "secp384r1"),
|
||||||
clock);
|
clock);
|
||||||
|
|
Loading…
Add table
Reference in a new issue