Polish "Add SslInfoContributor and SslHealthIndicator"
See gh-41205
This commit is contained in:
parent
5e3796e814
commit
fd1472784e
|
|
@ -107,14 +107,14 @@ public class InfoContributorAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnEnabledInfoContributor(value = "ssl", fallback = InfoContributorFallback.DISABLE)
|
||||
@Order(DEFAULT_ORDER)
|
||||
public SslInfoContributor sslInfoContributor(SslInfo sslInfo) {
|
||||
SslInfoContributor sslInfoContributor(SslInfo sslInfo) {
|
||||
return new SslInfoContributor(sslInfo);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledInfoContributor(value = "ssl", fallback = InfoContributorFallback.DISABLE)
|
||||
public SslInfo sslInfo(SslBundles sslBundles, SslHealthIndicatorProperties sslHealthIndicatorProperties) {
|
||||
SslInfo sslInfo(SslBundles sslBundles, SslHealthIndicatorProperties sslHealthIndicatorProperties) {
|
||||
return new SslInfo(sslBundles, sslHealthIndicatorProperties.getCertificateValidityWarningThreshold());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@ public class SslHealthContributorAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "sslHealthIndicator")
|
||||
public SslHealthIndicator sslHealthIndicator(SslInfo sslInfo) {
|
||||
SslHealthIndicator sslHealthIndicator(SslInfo sslInfo) {
|
||||
return new SslHealthIndicator(sslInfo);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SslInfo sslInfo(SslBundles sslBundles, SslHealthIndicatorProperties sslHealthIndicatorProperties) {
|
||||
SslInfo sslInfo(SslBundles sslBundles, SslHealthIndicatorProperties sslHealthIndicatorProperties) {
|
||||
return new SslInfo(sslBundles, sslHealthIndicatorProperties.getCertificateValidityWarningThreshold());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,12 +227,6 @@
|
|||
"description": "Whether to enable Redis health check.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.health.ssl.certificate-validity-warning-threshold",
|
||||
"type": "java.time.Duration",
|
||||
"description": "If an SSL Certificate will be invalid within the time span defined by this threshold, it should trigger a warning.",
|
||||
"defaultValue": "14d"
|
||||
},
|
||||
{
|
||||
"name": "management.health.ssl.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
|
||||
/**
|
||||
* Tests for {@link SslHealthContributorAutoConfiguration}.
|
||||
*
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
class SslHealthContributorAutoConfigurationTests {
|
||||
|
||||
|
|
@ -56,24 +58,21 @@ class SslHealthContributorAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void beansShouldBeConfigured() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(SslHealthIndicator.class);
|
||||
assertThat(context).hasSingleBean(SslInfo.class);
|
||||
Health health = context.getBean(SslHealthIndicator.class).health();
|
||||
assertThat(health.getStatus()).isSameAs(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).hasSize(1);
|
||||
assertThat(invalidChains).first().isInstanceOf(CertificateChain.class);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void beansShouldBeConfiguredWithWarningThreshold() {
|
||||
this.contextRunner.withPropertyValues("management.health.ssl.certificate-validity-warning-threshold=1d")
|
||||
.run((context) -> {
|
||||
|
|
@ -84,16 +83,14 @@ class SslHealthContributorAutoConfigurationTests {
|
|||
.isEqualTo(Duration.ofDays(1));
|
||||
Health health = context.getBean(SslHealthIndicator.class).health();
|
||||
assertThat(health.getStatus()).isSameAs(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).hasSize(1);
|
||||
assertThat(invalidChains).first().isInstanceOf(CertificateChain.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void customBeansShouldBeConfigured() {
|
||||
this.contextRunner.withUserConfiguration(CustomSslInfoConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(SslHealthIndicator.class);
|
||||
|
|
@ -103,14 +100,22 @@ class SslHealthContributorAutoConfigurationTests {
|
|||
assertThat(context.getBean(SslInfo.class)).isSameAs(context.getBean("customSslInfo"));
|
||||
Health health = context.getBean(SslHealthIndicator.class).health();
|
||||
assertThat(health.getStatus()).isSameAs(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).hasSize(1);
|
||||
assertThat(invalidChains).first().isInstanceOf(CertificateChain.class);
|
||||
});
|
||||
}
|
||||
|
||||
private static void assertDetailsKeys(Health health) {
|
||||
assertThat(health.getDetails()).containsOnlyKeys("validChains", "invalidChains");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<CertificateChain> getInvalidChains(Health health) {
|
||||
return (List<CertificateChain>) health.getDetails().get("invalidChains");
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomSslInfoConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@
|
|||
package org.springframework.boot.actuate.ssl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Health.Builder;
|
||||
|
|
@ -26,12 +24,10 @@ import org.springframework.boot.actuate.health.HealthIndicator;
|
|||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.boot.info.SslInfo;
|
||||
import org.springframework.boot.info.SslInfo.CertificateChain;
|
||||
import org.springframework.boot.info.SslInfo.CertificateInfo.Validity;
|
||||
|
||||
/**
|
||||
* {@link HealthIndicator} that checks the certificates the application uses and reports
|
||||
* {@link Status#OUT_OF_SERVICE} when a certificate is invalid or "WILL_EXPIRE_SOON" if it
|
||||
* will expire within the configurable threshold.
|
||||
* {@link Status#OUT_OF_SERVICE} when a certificate is invalid.
|
||||
*
|
||||
* @author Jonatan Ivanov
|
||||
* @since 3.4.0
|
||||
|
|
@ -46,43 +42,38 @@ public class SslHealthIndicator extends AbstractHealthIndicator {
|
|||
|
||||
@Override
|
||||
protected void doHealthCheck(Builder builder) throws Exception {
|
||||
List<CertificateChain> notValidCertificateChains = this.sslInfo.getBundles()
|
||||
List<CertificateChain> certificateChains = this.sslInfo.getBundles()
|
||||
.stream()
|
||||
.flatMap((bundle) -> bundle.getCertificateChains().stream())
|
||||
.filter(this::containsNotValidCertificate)
|
||||
.toList();
|
||||
|
||||
if (notValidCertificateChains.isEmpty()) {
|
||||
List<CertificateChain> validCertificateChains = certificateChains.stream()
|
||||
.filter(this::containsOnlyValidCertificates)
|
||||
.toList();
|
||||
List<CertificateChain> invalidCertificateChains = certificateChains.stream()
|
||||
.filter(this::containsInvalidCertificate)
|
||||
.toList();
|
||||
builder.withDetail("validChains", validCertificateChains);
|
||||
builder.withDetail("invalidChains", invalidCertificateChains);
|
||||
if (invalidCertificateChains.isEmpty()) {
|
||||
builder.status(Status.UP);
|
||||
}
|
||||
else {
|
||||
Set<Validity.Status> statuses = collectCertificateStatuses(notValidCertificateChains);
|
||||
if (statuses.contains(Validity.Status.EXPIRED) || statuses.contains(Validity.Status.NOT_YET_VALID)) {
|
||||
builder.status(Status.OUT_OF_SERVICE);
|
||||
}
|
||||
else if (statuses.contains(Validity.Status.WILL_EXPIRE_SOON)) {
|
||||
builder.status(Status.UP);
|
||||
}
|
||||
else {
|
||||
builder.status(Status.OUT_OF_SERVICE);
|
||||
}
|
||||
builder.withDetail("certificateChains", notValidCertificateChains);
|
||||
builder.status(Status.OUT_OF_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsNotValidCertificate(CertificateChain certificateChain) {
|
||||
private boolean containsOnlyValidCertificates(CertificateChain certificateChain) {
|
||||
return certificateChain.getCertificates()
|
||||
.stream()
|
||||
.filter((certificate) -> certificate.getValidity() != null)
|
||||
.anyMatch((certificate) -> certificate.getValidity().getStatus() != Validity.Status.VALID);
|
||||
.allMatch((certificate) -> certificate.getValidity().getStatus().isValid());
|
||||
}
|
||||
|
||||
private Set<Validity.Status> collectCertificateStatuses(List<CertificateChain> certificateChains) {
|
||||
return certificateChains.stream()
|
||||
.flatMap((certificateChain) -> certificateChain.getCertificates().stream())
|
||||
private boolean containsInvalidCertificate(CertificateChain certificateChain) {
|
||||
return certificateChain.getCertificates()
|
||||
.stream()
|
||||
.filter((certificate) -> certificate.getValidity() != null)
|
||||
.map((certificate) -> certificate.getValidity().getStatus())
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
.anyMatch((certificate) -> !certificate.getValidity().getStatus().isValid());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,59 +66,66 @@ class SslHealthIndicatorTests {
|
|||
given(this.validity.getStatus()).willReturn(Validity.Status.VALID);
|
||||
Health health = this.healthIndicator.health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(health.getDetails()).isEmpty();
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> validChains = getValidChains(health);
|
||||
assertThat(validChains).hasSize(1);
|
||||
assertThat(validChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void shouldBeOutOfServiceIfACertificateIsExpired() {
|
||||
given(this.validity.getStatus()).willReturn(Validity.Status.EXPIRED);
|
||||
Health health = this.healthIndicator.health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> validChains = getValidChains(health);
|
||||
assertThat(validChains).isEmpty();
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).hasSize(1);
|
||||
assertThat(invalidChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void shouldBeOutOfServiceIfACertificateIsNotYetValid() {
|
||||
given(this.validity.getStatus()).willReturn(Validity.Status.NOT_YET_VALID);
|
||||
Health health = this.healthIndicator.health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> validChains = getValidChains(health);
|
||||
assertThat(validChains).isEmpty();
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).hasSize(1);
|
||||
assertThat(invalidChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void shouldReportWarningIfACertificateWillExpireSoon() {
|
||||
given(this.validity.getStatus()).willReturn(Validity.Status.WILL_EXPIRE_SOON);
|
||||
Health health = this.healthIndicator.health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
assertDetailsKeys(health);
|
||||
List<CertificateChain> validChains = getValidChains(health);
|
||||
assertThat(validChains).hasSize(1);
|
||||
assertThat(validChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
List<CertificateChain> invalidChains = getInvalidChains(health);
|
||||
assertThat(invalidChains).isEmpty();
|
||||
}
|
||||
|
||||
private static void assertDetailsKeys(Health health) {
|
||||
assertThat(health.getDetails()).containsOnlyKeys("validChains", "invalidChains");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void shouldBeOutOfServiceIfACertificateHasUnMappedValidityStatus() {
|
||||
given(this.validity.getStatus()).willReturn(mock(Validity.Status.class));
|
||||
Health health = this.healthIndicator.health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE);
|
||||
assertThat(health.getDetails()).hasSize(1);
|
||||
List<CertificateChain> certificateChains = (List<CertificateChain>) health.getDetails()
|
||||
.get("certificateChains");
|
||||
assertThat(certificateChains).hasSize(1);
|
||||
assertThat(certificateChains.get(0)).isInstanceOf(CertificateChain.class);
|
||||
private static List<CertificateChain> getInvalidChains(Health health) {
|
||||
return (List<CertificateChain>) health.getDetails().get("invalidChains");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<CertificateChain> getValidChains(Health health) {
|
||||
return (List<CertificateChain>) health.getDetails().get("validChains");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -651,12 +651,14 @@ with the `key` listed in the following table:
|
|||
|
||||
| `ssl`
|
||||
| javadoc:org.springframework.boot.actuate.ssl.SslHealthIndicator[]
|
||||
| Checks that SSL Cerificates are ok.
|
||||
| Checks that SSL Certificates are ok.
|
||||
|===
|
||||
|
||||
TIP: You can disable them all by setting the configprop:management.health.defaults.enabled[] property.
|
||||
|
||||
TIP: The `ssl` `HealthIndicator` has a "warning threshold" property. If an SSL Certificate will be invalid within the time span defined by this threshold, the `HealthIndicator` will warn you but it will still return HTTP 200 to not disrupt the application. You can use this threshold to give yourself enough lead time to rotate the soon to be expired certificate. See the `management.health.ssl.certificate-validity-warning-threshold` property.
|
||||
TIP: The `ssl` `HealthIndicator` has a "warning threshold" property named configprop:management.health.ssl.certificate-validity-warning-threshold[].
|
||||
If an SSL Certificate will be invalid within the time span defined by this threshold, the `HealthIndicator` will warn you but it will still return HTTP 200 to not disrupt the application.
|
||||
You can use this threshold to give yourself enough lead time to rotate the soon to be expired certificate.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -216,23 +216,33 @@ public class SslInfo {
|
|||
/**
|
||||
* The certificate is valid.
|
||||
*/
|
||||
VALID,
|
||||
VALID(true),
|
||||
|
||||
/**
|
||||
* The certificate's validity date range is in the future.
|
||||
*/
|
||||
NOT_YET_VALID,
|
||||
NOT_YET_VALID(false),
|
||||
|
||||
/**
|
||||
* The certificate's validity date range is in the past.
|
||||
*/
|
||||
EXPIRED,
|
||||
EXPIRED(false),
|
||||
|
||||
/**
|
||||
* The certificate is still valid but the end of its validity date range
|
||||
* The certificate is still valid, but the end of its validity date range
|
||||
* is within the defined threshold.
|
||||
*/
|
||||
WILL_EXPIRE_SOON
|
||||
WILL_EXPIRE_SOON(true);
|
||||
|
||||
private final boolean valid;
|
||||
|
||||
Status(boolean valid) {
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class SslInfoTests {
|
|||
assertThat(cert.getIssuer()).isEqualTo(cert.getSubject());
|
||||
assertThat(cert.getSerialNumber()).isNotEmpty();
|
||||
assertThat(cert.getVersion()).isEqualTo("V3");
|
||||
assertThat(cert.getSignatureAlgorithmName()).isEqualTo("SHA256withRSA");
|
||||
assertThat(cert.getSignatureAlgorithmName()).isNotEmpty();
|
||||
assertThat(cert.getValidityStarts()).isInThePast();
|
||||
assertThat(cert.getValidityEnds()).isInTheFuture();
|
||||
assertThat(cert.getValidity()).isNotNull();
|
||||
|
|
@ -182,7 +182,7 @@ class SslInfoTests {
|
|||
assertThat(cert.getIssuer()).isEqualTo(cert.getSubject());
|
||||
assertThat(cert.getSerialNumber()).isNotEmpty();
|
||||
assertThat(cert.getVersion()).isEqualTo("V3");
|
||||
assertThat(cert.getSignatureAlgorithmName()).isEqualTo("SHA256withRSA");
|
||||
assertThat(cert.getSignatureAlgorithmName()).isNotEmpty();
|
||||
assertThat(cert.getValidity()).isNotNull();
|
||||
});
|
||||
|
||||
|
|
@ -226,7 +226,6 @@ class SslInfoTests {
|
|||
SslStoreBundle sslStoreBundle = new JksSslStoreBundle(keyStoreDetails, null);
|
||||
sslBundleRegistry.registerBundle("test-%d".formatted(i), SslBundle.of(sslStoreBundle));
|
||||
}
|
||||
|
||||
return new SslInfo(sslBundleRegistry, Duration.ofDays(7));
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +239,6 @@ class SslInfoTests {
|
|||
.collect(Collectors.joining("\n"));
|
||||
throw new RuntimeException("Unexpected exit code from keytool: %d\n%s".formatted(exitCode, out));
|
||||
}
|
||||
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +259,6 @@ class SslInfoTests {
|
|||
);
|
||||
// @formatter:on
|
||||
processBuilder.redirectErrorStream(true);
|
||||
|
||||
return processBuilder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ server.port=8443
|
|||
management.endpoints.web.exposure.include=*
|
||||
management.endpoint.health.show-details=always
|
||||
management.health.ssl.certificate-validity-warning-threshold=7d
|
||||
# management.health.ssl.enabled=true
|
||||
management.health.ssl.enabled=true
|
||||
management.info.ssl.enabled=true
|
||||
|
||||
server.ssl.bundle=ssldemo
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -76,15 +76,15 @@ class SampleTomcatSslApplicationTests {
|
|||
JsonContent body = new JsonContent(entity.getBody());
|
||||
assertThat(body).extractingPath("status").isEqualTo("OUT_OF_SERVICE");
|
||||
assertThat(body).extractingPath("components.ssl.status").isEqualTo("OUT_OF_SERVICE");
|
||||
assertThat(body).extractingPath("components.ssl.details.certificateChains[0].alias")
|
||||
assertThat(body).extractingPath("components.ssl.details.invalidChains[0].alias")
|
||||
.isEqualTo("spring-boot-ssl-sample");
|
||||
assertThat(body).extractingPath("components.ssl.details.certificateChains[0].certificates[0].issuer")
|
||||
assertThat(body).extractingPath("components.ssl.details.invalidChains[0].certificates[0].issuer")
|
||||
.isEqualTo("CN=localhost,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown");
|
||||
assertThat(body).extractingPath("components.ssl.details.certificateChains[0].certificates[0].subject")
|
||||
assertThat(body).extractingPath("components.ssl.details.invalidChains[0].certificates[0].subject")
|
||||
.isEqualTo("CN=localhost,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown");
|
||||
assertThat(body).extractingPath("components.ssl.details.certificateChains[0].certificates[0].validity.status")
|
||||
assertThat(body).extractingPath("components.ssl.details.invalidChains[0].certificates[0].validity.status")
|
||||
.isEqualTo("EXPIRED");
|
||||
assertThat(body).extractingPath("components.ssl.details.certificateChains[0].certificates[0].validity.message")
|
||||
assertThat(body).extractingPath("components.ssl.details.invalidChains[0].certificates[0].validity.message")
|
||||
.asString()
|
||||
.startsWith("Not valid after ");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue